diff --git a/bitmaps_png/CMakeLists.txt b/bitmaps_png/CMakeLists.txt index 9ff06927c5..5c8d42b9b9 100644 --- a/bitmaps_png/CMakeLists.txt +++ b/bitmaps_png/CMakeLists.txt @@ -123,6 +123,7 @@ set( BMAPS_MID add_hierarchical_subsheet add_junction add_keepout_area + add_library add_line2bus add_line_label add_line @@ -227,6 +228,7 @@ set( BMAPS_MID export_idf export_footprint_names export_module + export_part export fabrication file_footprint @@ -275,6 +277,7 @@ set( BMAPS_MID import_footprint_names import_hierarchical_label import_module + import_part import_setup import info @@ -466,6 +469,7 @@ set( BMAPS_MID rotate_pos_z save_as save_library + save_part save_part_in_mem save_project save_setup @@ -483,6 +487,7 @@ set( BMAPS_MID sim_probe sim_add_signal sim_settings + search_tree setcolor_3d_bg setcolor_silkscreen setcolor_soldermask diff --git a/bitmaps_png/cpp_26/add_library.cpp b/bitmaps_png/cpp_26/add_library.cpp new file mode 100644 index 0000000000..a85345ab3d --- /dev/null +++ b/bitmaps_png/cpp_26/add_library.cpp @@ -0,0 +1,83 @@ + +/* Do not modify this file, it was automatically generated by the + * PNG2cpp CMake script, using a *.png file as input. + */ + +#include + +static const unsigned char png[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x08, 0x06, 0x00, 0x00, 0x00, 0xa9, 0x4a, 0x4c, + 0xce, 0x00, 0x00, 0x04, 0x1e, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xad, 0xd6, 0x7d, 0x4c, 0x13, + 0x67, 0x1c, 0x07, 0xf0, 0x03, 0x13, 0xb3, 0xb1, 0x7f, 0x97, 0x2c, 0x7b, 0x49, 0xda, 0x7b, 0x0e, + 0x46, 0xad, 0xae, 0x36, 0x2a, 0x06, 0x34, 0x8e, 0xd2, 0x2b, 0x25, 0x5b, 0x70, 0xc1, 0x69, 0x7d, + 0xe9, 0xb6, 0x90, 0xc5, 0xea, 0x64, 0xbe, 0xc4, 0x89, 0x94, 0xbe, 0xce, 0x66, 0x4a, 0xb6, 0xb1, + 0xe9, 0xe6, 0x1b, 0x2f, 0xc1, 0x01, 0x31, 0x0c, 0x6d, 0xa9, 0x22, 0x2f, 0xa2, 0x09, 0x8e, 0x81, + 0x28, 0xb0, 0x01, 0x43, 0xcc, 0xd5, 0x21, 0xa0, 0xc6, 0x11, 0x92, 0xbd, 0x64, 0xa4, 0x34, 0x5a, + 0xb4, 0x14, 0x7f, 0x7b, 0xee, 0x8e, 0x97, 0xca, 0xb5, 0x61, 0x6d, 0x7a, 0xc9, 0x37, 0xf7, 0xe4, + 0x7a, 0x7d, 0x3e, 0x7d, 0xee, 0xf9, 0xf5, 0x79, 0x8e, 0x20, 0xe6, 0x1d, 0x2a, 0x0b, 0xfa, 0x2a, + 0xcd, 0x4c, 0x56, 0xd1, 0x06, 0xf4, 0xa9, 0x32, 0x9f, 0x5a, 0xa3, 0x3e, 0xf8, 0xca, 0x4b, 0xc4, + 0xff, 0x38, 0x3a, 0x1c, 0xc4, 0x8b, 0x8c, 0x9d, 0xf0, 0x31, 0x35, 0x31, 0x93, 0x82, 0xe0, 0xeb, + 0x82, 0x2f, 0x28, 0x2d, 0x68, 0x24, 0xe9, 0x04, 0x05, 0xc9, 0x47, 0xc9, 0xc7, 0xa9, 0x36, 0x34, + 0xae, 0x32, 0xa2, 0x49, 0xda, 0x42, 0x8e, 0x2a, 0xcd, 0x64, 0x7d, 0xba, 0x1e, 0xad, 0x0a, 0x05, + 0xf5, 0x34, 0x10, 0x71, 0x8c, 0x83, 0x00, 0x7f, 0x7f, 0xa2, 0x20, 0xec, 0xf5, 0xe7, 0x6e, 0x5e, + 0x6f, 0x7b, 0x2d, 0x8e, 0xed, 0x38, 0xe1, 0x62, 0x3c, 0xc4, 0x5f, 0xe2, 0x93, 0x50, 0x1b, 0x0f, + 0xd2, 0x1f, 0x29, 0x50, 0x58, 0x49, 0xaf, 0xca, 0x20, 0x56, 0x2c, 0x04, 0x01, 0x23, 0x15, 0x44, + 0x00, 0xa9, 0xf4, 0xe2, 0x64, 0x76, 0x14, 0x2c, 0x20, 0xad, 0x97, 0x42, 0xca, 0xd5, 0x94, 0x59, + 0x8c, 0x36, 0x22, 0x9f, 0x22, 0x77, 0xe5, 0xcb, 0x84, 0xc6, 0xb1, 0x48, 0x10, 0x9b, 0x2d, 0x56, + 0x00, 0x79, 0x5a, 0x42, 0x43, 0xe9, 0x06, 0xf1, 0xae, 0x94, 0x42, 0xf4, 0x98, 0xed, 0x5c, 0x7b, + 0x43, 0x0b, 0x6d, 0x7f, 0xb5, 0x71, 0xd0, 0x92, 0x73, 0x14, 0x28, 0x4d, 0xe8, 0x6f, 0x42, 0xe5, + 0x80, 0x60, 0x89, 0x51, 0xd7, 0x78, 0x04, 0x90, 0xdf, 0x13, 0x1a, 0xc2, 0x9d, 0x55, 0xac, 0x28, + 0xa6, 0xb8, 0xce, 0x0f, 0xdf, 0x3e, 0x0c, 0x25, 0x83, 0x25, 0x5c, 0x7b, 0xf9, 0x19, 0x0a, 0xd2, + 0xcc, 0xe8, 0x1a, 0xdb, 0x69, 0xd6, 0x29, 0x1f, 0x6c, 0x2c, 0x9e, 0x9a, 0xcd, 0xbb, 0xc7, 0x1e, + 0x41, 0xac, 0xda, 0xe9, 0x0d, 0x0b, 0xc2, 0xd5, 0xf6, 0xfb, 0xb2, 0xb3, 0x3c, 0xe4, 0x7c, 0xe8, + 0x84, 0xfd, 0xdd, 0xfb, 0xb9, 0xf6, 0xea, 0xe3, 0xd4, 0x24, 0x6d, 0x22, 0xbf, 0x60, 0xa1, 0xf7, + 0x8b, 0xfc, 0xa0, 0x29, 0x85, 0xd9, 0x64, 0x7e, 0xef, 0x0d, 0x0f, 0xd2, 0x68, 0x88, 0x45, 0xb8, + 0x10, 0x9e, 0xbe, 0xe9, 0xe4, 0x21, 0x97, 0xdb, 0x05, 0xea, 0x6b, 0x6a, 0xae, 0xbd, 0xae, 0x00, + 0xb9, 0x69, 0x3d, 0x95, 0x15, 0x15, 0x48, 0xa5, 0x17, 0x2d, 0x51, 0x5a, 0xc8, 0x47, 0x6c, 0xc7, + 0x92, 0x7a, 0x09, 0x8c, 0xfb, 0xc6, 0x21, 0xb1, 0x2e, 0x91, 0x83, 0x70, 0x69, 0x7b, 0x15, 0x06, + 0x89, 0x38, 0x10, 0x6a, 0xe8, 0x8f, 0x10, 0x4a, 0x37, 0xa0, 0x6d, 0x6b, 0xbf, 0xe4, 0x2b, 0x2e, + 0xf3, 0xe7, 0x4c, 0xe8, 0x1b, 0xeb, 0xe3, 0x90, 0x44, 0x07, 0x85, 0x2b, 0x8e, 0xf4, 0x12, 0x84, + 0x2d, 0x36, 0x10, 0xf2, 0x4c, 0x44, 0x08, 0x29, 0x8d, 0xe4, 0x37, 0x2b, 0x4f, 0xa2, 0x29, 0xb6, + 0x73, 0x7d, 0xaf, 0x1e, 0xaa, 0x1f, 0x54, 0x73, 0x90, 0xac, 0x92, 0x1d, 0x11, 0xea, 0x25, 0x08, + 0x88, 0x89, 0x0e, 0x64, 0x25, 0x3b, 0x64, 0x15, 0xfc, 0xfc, 0x94, 0x0f, 0x97, 0x83, 0xf5, 0x96, + 0x95, 0x6b, 0xaf, 0x3a, 0x4d, 0x3d, 0x53, 0x99, 0xc9, 0x93, 0x51, 0x83, 0x70, 0x55, 0x8d, 0x4b, + 0xec, 0x3c, 0xd4, 0xf9, 0x4f, 0x27, 0x6c, 0x6a, 0xdb, 0xc4, 0xb5, 0xd7, 0x14, 0x22, 0x0f, 0x6d, + 0x14, 0x67, 0x47, 0x05, 0xca, 0x30, 0x89, 0x5e, 0xc5, 0xf3, 0xf0, 0x24, 0xbe, 0x96, 0x5f, 0x76, + 0x18, 0x37, 0x03, 0xb2, 0x46, 0x19, 0xd7, 0x4e, 0xb3, 0x22, 0x4f, 0x46, 0x3e, 0xb9, 0x3c, 0x2a, + 0x90, 0x32, 0x5f, 0xf4, 0xce, 0xdb, 0x47, 0x90, 0x7b, 0x66, 0x7d, 0xdb, 0x63, 0x35, 0x82, 0xde, + 0x70, 0x04, 0xf4, 0x79, 0x05, 0x90, 0x75, 0x20, 0x69, 0x52, 0x63, 0x5b, 0xba, 0x38, 0x6c, 0xc8, + 0xf5, 0x96, 0x10, 0xc2, 0xa3, 0x31, 0xad, 0xfe, 0x8e, 0x7a, 0x3a, 0x03, 0xd5, 0x7d, 0x7e, 0x1d, + 0x98, 0x92, 0x11, 0xe8, 0xfb, 0xfa, 0x01, 0x7c, 0xbc, 0x7b, 0xc3, 0x28, 0xff, 0x70, 0xc3, 0x84, + 0x82, 0x2d, 0xaa, 0xb4, 0x15, 0x35, 0xca, 0xcb, 0x10, 0xcc, 0x41, 0xed, 0xc0, 0x14, 0x8f, 0x40, + 0x2f, 0x86, 0x72, 0x76, 0x7e, 0xd0, 0x12, 0x0c, 0x6a, 0xbd, 0x1b, 0x09, 0x84, 0xf7, 0x1b, 0x69, + 0x35, 0x15, 0x14, 0xca, 0xcd, 0xde, 0x7d, 0x2a, 0x18, 0xb4, 0xe0, 0xca, 0x30, 0x1f, 0x62, 0x77, + 0xd0, 0x7d, 0xdb, 0x75, 0xfe, 0xbd, 0x06, 0x33, 0xcc, 0xa4, 0xc9, 0xd4, 0x35, 0x0d, 0xdd, 0x87, + 0xaa, 0x8c, 0xcb, 0xcd, 0x17, 0xd3, 0xbb, 0x0b, 0xd8, 0x6c, 0x53, 0x35, 0x83, 0xe6, 0x84, 0x2f, + 0x32, 0x88, 0x36, 0x8a, 0x52, 0xec, 0xb9, 0x97, 0xfd, 0xec, 0x9c, 0x30, 0xa5, 0xd3, 0x61, 0xdb, + 0xc5, 0xd3, 0xe7, 0xd2, 0xb9, 0xb4, 0x1f, 0x1a, 0x84, 0x0f, 0xbf, 0xf5, 0x46, 0x06, 0xa9, 0xf2, + 0x51, 0x4e, 0xc5, 0x27, 0x97, 0xa6, 0x7e, 0x39, 0x34, 0x0c, 0x33, 0xe9, 0xb2, 0x0c, 0x41, 0xa7, + 0x79, 0x08, 0x3a, 0x0c, 0x83, 0x70, 0x33, 0xef, 0x2e, 0xdc, 0x38, 0xc0, 0x66, 0x00, 0x9a, 0x74, + 0xb7, 0x39, 0xe8, 0x33, 0x07, 0x80, 0xbd, 0x1b, 0x60, 0xcf, 0xb9, 0x10, 0xd0, 0x7d, 0x2d, 0xc0, + 0x98, 0x1d, 0xe0, 0xde, 0x96, 0x80, 0x11, 0x99, 0xc9, 0xca, 0x63, 0xd9, 0x3f, 0x40, 0xb5, 0xae, + 0x19, 0x5a, 0xf6, 0x32, 0xd0, 0xba, 0xef, 0x0e, 0x5c, 0xd9, 0xd1, 0x03, 0xad, 0x39, 0x77, 0xa0, + 0x65, 0xa7, 0x0b, 0xae, 0x68, 0xfa, 0xef, 0x5d, 0xdd, 0x72, 0x6b, 0x90, 0x4d, 0xf9, 0x7b, 0xbf, + 0x82, 0xf6, 0xe8, 0x04, 0xfc, 0x31, 0x06, 0xdc, 0x31, 0xf0, 0x67, 0x08, 0xe8, 0xc9, 0x30, 0x7f, + 0xc3, 0xc4, 0xc0, 0x1c, 0x14, 0xb8, 0x07, 0xb1, 0xdb, 0xb7, 0xbc, 0x51, 0x0e, 0x67, 0x75, 0x4d, + 0x1c, 0xf4, 0xd3, 0x76, 0x17, 0xd4, 0xa5, 0x76, 0xa5, 0xcd, 0x2f, 0x86, 0xdf, 0x1e, 0xf2, 0xfd, + 0xb4, 0x0f, 0x85, 0x80, 0xc6, 0x2e, 0xf0, 0x37, 0xfc, 0x7b, 0x3e, 0x60, 0x44, 0x06, 0xe4, 0x93, + 0x97, 0x51, 0x20, 0xb1, 0xe3, 0x8a, 0xc3, 0x2b, 0x03, 0x75, 0x81, 0x7a, 0x0e, 0xaa, 0x59, 0x77, + 0x9d, 0xc6, 0x4a, 0x4c, 0x20, 0xa4, 0x3d, 0x03, 0x60, 0xac, 0x05, 0xd8, 0x5a, 0x16, 0x6a, 0x8e, + 0x96, 0xe2, 0xe1, 0x2a, 0xf8, 0xf3, 0x1c, 0x44, 0x16, 0x2a, 0x8c, 0x64, 0x87, 0x22, 0x4f, 0xec, + 0x49, 0x3d, 0x28, 0x9a, 0x48, 0x36, 0x8b, 0xdc, 0x55, 0x1f, 0x35, 0x3d, 0xe3, 0x1e, 0x9d, 0xce, + 0x05, 0xa7, 0x93, 0xec, 0xeb, 0x31, 0x84, 0xdf, 0xed, 0xc4, 0x2f, 0x10, 0xf4, 0x79, 0xbe, 0xbc, + 0x4b, 0x60, 0x36, 0x61, 0xfd, 0x8f, 0xf8, 0x5f, 0x4c, 0x2c, 0x96, 0x6f, 0x7c, 0x23, 0x61, 0xed, + 0x8e, 0xd7, 0x37, 0x1f, 0xdf, 0x50, 0xd6, 0x53, 0xb4, 0xb9, 0x72, 0xd4, 0x99, 0xd9, 0xd9, 0x60, + 0x5b, 0x56, 0x24, 0xc3, 0x9f, 0xc5, 0xf1, 0x90, 0x7d, 0xc1, 0x97, 0x13, 0xfc, 0xb2, 0x28, 0x0c, + 0xbe, 0xfe, 0x1f, 0x61, 0x1f, 0xc8, 0xed, 0xe9, 0xe0, 0xae, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, +}; + +const BITMAP_OPAQUE add_library_xpm[1] = {{ png, sizeof( png ), "add_library_xpm" }}; + +//EOF diff --git a/bitmaps_png/cpp_26/export_part.cpp b/bitmaps_png/cpp_26/export_part.cpp new file mode 100644 index 0000000000..892c598114 --- /dev/null +++ b/bitmaps_png/cpp_26/export_part.cpp @@ -0,0 +1,69 @@ + +/* Do not modify this file, it was automatically generated by the + * PNG2cpp CMake script, using a *.png file as input. + */ + +#include + +static const unsigned char png[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x08, 0x06, 0x00, 0x00, 0x00, 0xa9, 0x4a, 0x4c, + 0xce, 0x00, 0x00, 0x03, 0x3c, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xb5, 0x96, 0x7b, 0x48, 0x53, + 0x51, 0x1c, 0xc7, 0xef, 0x9c, 0xc6, 0x8a, 0xfe, 0xc9, 0xfe, 0x8a, 0xe8, 0xaf, 0xca, 0x3f, 0x12, + 0x04, 0xff, 0xc8, 0xf7, 0x4c, 0xc2, 0x08, 0x09, 0x7a, 0x91, 0x98, 0xd1, 0x0b, 0x05, 0xd3, 0x68, + 0x62, 0x2f, 0xc2, 0x12, 0x73, 0xbe, 0x89, 0xfc, 0x23, 0x84, 0x95, 0xa1, 0xfd, 0x13, 0x81, 0xb8, + 0xa9, 0x69, 0x39, 0x9d, 0xb3, 0xcd, 0x6d, 0xce, 0xbd, 0xe7, 0x1e, 0xee, 0xe5, 0x36, 0xcd, 0xc8, + 0x9a, 0x56, 0xa8, 0x85, 0x6b, 0x13, 0xb7, 0x5f, 0xe7, 0x5c, 0x9d, 0x98, 0x48, 0x6e, 0xe6, 0x2e, + 0x7c, 0xb9, 0xe7, 0x9e, 0x7b, 0xcf, 0xf9, 0xdc, 0xdf, 0xef, 0xf7, 0x3d, 0x9c, 0x43, 0x10, 0xeb, + 0xae, 0x0a, 0x82, 0x38, 0x82, 0x6e, 0x14, 0x22, 0x9c, 0x17, 0x82, 0x24, 0x20, 0x01, 0x93, 0x42, + 0xe9, 0xaf, 0x26, 0x88, 0x03, 0xe1, 0x04, 0x65, 0x60, 0x50, 0x05, 0x85, 0x02, 0x4c, 0x2a, 0xf5, + 0x17, 0x6a, 0x5f, 0x0f, 0x2b, 0x48, 0xd3, 0xd2, 0x02, 0xaf, 0xd2, 0xd3, 0xfd, 0x2b, 0xd1, 0xf5, + 0xa1, 0xe8, 0xf6, 0x87, 0x05, 0x64, 0xe7, 0xf3, 0xc1, 0xeb, 0xf5, 0x82, 0x82, 0xc5, 0x82, 0x2a, + 0x1a, 0xcd, 0xc7, 0x8c, 0x88, 0xf8, 0x89, 0xfa, 0x0b, 0xc2, 0x02, 0x5a, 0x5c, 0x5c, 0x24, 0x35, + 0x63, 0xb3, 0x41, 0x4b, 0x6a, 0xaa, 0x6f, 0x25, 0xa5, 0x3d, 0x35, 0x04, 0xb1, 0x2f, 0x2c, 0x20, + 0x2c, 0xaf, 0xc7, 0x03, 0xd2, 0x86, 0x06, 0xa8, 0x8c, 0x8a, 0xf2, 0x55, 0x52, 0xa9, 0xdf, 0xd1, + 0x37, 0xe7, 0xc3, 0x02, 0x0a, 0xe8, 0x8b, 0x5e, 0x0f, 0x2f, 0xe2, 0xe3, 0x03, 0xd1, 0xb1, 0x6b, + 0x09, 0x62, 0x6f, 0xd0, 0x93, 0x33, 0x09, 0x82, 0x81, 0x06, 0xf2, 0xb1, 0x50, 0x5b, 0x8d, 0x27, + 0x31, 0xb2, 0xd9, 0xe4, 0xc4, 0x73, 0x53, 0x53, 0x64, 0xea, 0x02, 0xc2, 0xcf, 0x1e, 0xb7, 0x1b, + 0x44, 0x35, 0x35, 0x50, 0x19, 0x19, 0xe9, 0x43, 0xce, 0xfc, 0x86, 0xc6, 0x9c, 0xf9, 0x2f, 0x90, + 0x7b, 0x7e, 0x1e, 0xaa, 0x69, 0x34, 0x20, 0xff, 0x7e, 0x45, 0xf8, 0x19, 0xf7, 0xe3, 0x9f, 0x98, + 0xd2, 0x6a, 0x81, 0x15, 0x17, 0xb7, 0xb4, 0xf2, 0xae, 0xad, 0x8e, 0x20, 0xf6, 0x6c, 0x39, 0x75, + 0x1b, 0x45, 0xb4, 0x36, 0x95, 0x9e, 0x85, 0x85, 0x40, 0x74, 0x7e, 0x54, 0xbb, 0xcf, 0x68, 0x6c, + 0xe6, 0xb6, 0xd4, 0x68, 0xbd, 0x26, 0xb8, 0x2e, 0x98, 0x1e, 0x99, 0x85, 0x8f, 0x52, 0x29, 0x34, + 0xc6, 0xc4, 0xe0, 0xe8, 0xf0, 0xda, 0x6b, 0x42, 0xda, 0xbd, 0x25, 0x50, 0x20, 0x5d, 0xeb, 0x25, + 0x2b, 0x1b, 0x03, 0xde, 0x25, 0x3d, 0x18, 0x58, 0x93, 0xe0, 0x9e, 0x9b, 0x87, 0xde, 0x92, 0x12, + 0xbc, 0xc0, 0xfd, 0xc8, 0x28, 0x6e, 0x34, 0x8f, 0x68, 0x4d, 0x49, 0x18, 0x9b, 0x82, 0xe6, 0x5d, + 0x2e, 0xb2, 0x36, 0xf8, 0xbe, 0x11, 0x48, 0x55, 0xe5, 0x00, 0xe9, 0x3d, 0x1b, 0x7c, 0xc8, 0x37, + 0x02, 0xf7, 0x66, 0xe9, 0xd6, 0x40, 0xb8, 0x26, 0x13, 0x12, 0x09, 0x69, 0x04, 0x7c, 0x5f, 0x5f, + 0x23, 0x0c, 0x52, 0x94, 0xdb, 0x61, 0xb0, 0xd0, 0x0c, 0xb2, 0x07, 0x63, 0xd0, 0x71, 0x9c, 0x07, + 0x8d, 0xfb, 0x72, 0x78, 0x21, 0xa5, 0x2e, 0xe0, 0xba, 0xfa, 0x5d, 0x87, 0xa1, 0xf3, 0x84, 0x00, + 0x7a, 0x73, 0x84, 0xa4, 0x44, 0x0c, 0xf3, 0xaa, 0x84, 0x85, 0x26, 0x50, 0x55, 0x3b, 0x61, 0xe0, + 0xaa, 0x11, 0xf8, 0x97, 0x0d, 0x28, 0x32, 0x2b, 0xf0, 0x72, 0x0d, 0x3f, 0x38, 0xc9, 0xf2, 0x26, + 0x61, 0x86, 0x30, 0x32, 0xa4, 0x75, 0x34, 0xfa, 0x66, 0x08, 0x44, 0xc5, 0x1a, 0xd0, 0x3f, 0x9b, + 0x04, 0x4d, 0xdd, 0x38, 0xa8, 0xab, 0x9c, 0xa0, 0x7c, 0xec, 0x00, 0x59, 0xe9, 0x18, 0x48, 0xef, + 0x5a, 0x41, 0x52, 0x6c, 0x21, 0x41, 0xfd, 0xb9, 0x7a, 0xe8, 0xbb, 0xa0, 0x03, 0x61, 0x81, 0x09, + 0x44, 0x45, 0xe6, 0xc5, 0x8e, 0x34, 0x95, 0xa5, 0x35, 0x45, 0x7a, 0x30, 0x28, 0x10, 0xd6, 0x27, + 0xf1, 0x24, 0x02, 0x69, 0x41, 0x5b, 0x3f, 0x0e, 0xf2, 0x87, 0x63, 0x30, 0x7c, 0xdf, 0x06, 0x43, + 0xb7, 0xad, 0x20, 0xbe, 0x65, 0x81, 0xc1, 0x1b, 0x26, 0x10, 0xe4, 0x8f, 0xfe, 0x05, 0xe2, 0x9e, + 0x1d, 0x81, 0xbe, 0x6c, 0x3d, 0xf9, 0xbe, 0x3b, 0x4b, 0xed, 0x6a, 0x4f, 0x56, 0xe4, 0x07, 0xe5, + 0xba, 0x69, 0xdd, 0x2c, 0xc8, 0x1f, 0xd9, 0x43, 0x02, 0xbd, 0x3f, 0xa5, 0x85, 0x77, 0x59, 0x1a, + 0x32, 0x3a, 0x5e, 0xb6, 0x7e, 0x96, 0x93, 0x24, 0x6b, 0x0d, 0x0e, 0x54, 0x16, 0x3a, 0x08, 0xb7, + 0x07, 0x8b, 0xcc, 0xd0, 0x75, 0x52, 0xf5, 0x95, 0x9d, 0xa0, 0xd8, 0xdc, 0xde, 0x4e, 0xae, 0x09, + 0xc4, 0x77, 0x74, 0x41, 0x83, 0x7a, 0xcf, 0x8d, 0xa0, 0x7e, 0x33, 0x08, 0xf2, 0x46, 0x7f, 0x77, + 0xd0, 0xe5, 0x86, 0xb6, 0xe4, 0xe1, 0x43, 0x41, 0x6d, 0x7c, 0x4f, 0xa3, 0xe3, 0x7d, 0x82, 0x3c, + 0x8d, 0x5f, 0xfb, 0x64, 0x1c, 0x34, 0xb5, 0x4e, 0x64, 0x06, 0x07, 0xa8, 0x98, 0x0e, 0x64, 0x6b, + 0x07, 0x02, 0xdb, 0x49, 0x73, 0x04, 0x40, 0x03, 0x57, 0x8c, 0xa4, 0x41, 0x7a, 0x4e, 0x8f, 0x4c, + 0x23, 0xe7, 0x31, 0x2b, 0x08, 0x88, 0xf8, 0xa7, 0xbd, 0xd5, 0xcd, 0xcd, 0xab, 0x5b, 0x79, 0x4d, + 0x54, 0xf4, 0x40, 0x6b, 0x62, 0x77, 0x79, 0x3b, 0x5d, 0x55, 0xb2, 0x2c, 0xf9, 0xb2, 0x52, 0x91, + 0xd2, 0x14, 0x3a, 0xbc, 0x8e, 0x06, 0xae, 0x19, 0x49, 0xf7, 0x49, 0x18, 0x16, 0x6f, 0xe7, 0x31, + 0xa5, 0x89, 0x73, 0x54, 0x19, 0xbb, 0xad, 0x87, 0x13, 0x04, 0x66, 0x2b, 0xc9, 0xe8, 0xec, 0xc0, + 0xbb, 0xa8, 0x9f, 0xe1, 0xa4, 0xc8, 0x5f, 0xb6, 0xc5, 0x9a, 0x76, 0x6c, 0xfb, 0x71, 0x0b, 0x83, + 0xc4, 0xc5, 0xd6, 0xa5, 0xae, 0x4c, 0xb5, 0xf3, 0x6d, 0x92, 0x3a, 0x31, 0xd4, 0x5d, 0x36, 0xe8, + 0x03, 0x24, 0x87, 0xae, 0x78, 0xde, 0x41, 0x57, 0xbe, 0x46, 0x05, 0xdf, 0xb9, 0xd9, 0xb7, 0x7f, + 0x00, 0x15, 0xb1, 0xf0, 0x25, 0x56, 0x5d, 0x02, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, + 0x44, 0xae, 0x42, 0x60, 0x82, +}; + +const BITMAP_OPAQUE export_part_xpm[1] = {{ png, sizeof( png ), "export_part_xpm" }}; + +//EOF diff --git a/bitmaps_png/cpp_26/import_part.cpp b/bitmaps_png/cpp_26/import_part.cpp new file mode 100644 index 0000000000..e675d0b843 --- /dev/null +++ b/bitmaps_png/cpp_26/import_part.cpp @@ -0,0 +1,64 @@ + +/* Do not modify this file, it was automatically generated by the + * PNG2cpp CMake script, using a *.png file as input. + */ + +#include + +static const unsigned char png[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x08, 0x06, 0x00, 0x00, 0x00, 0xa9, 0x4a, 0x4c, + 0xce, 0x00, 0x00, 0x02, 0xf2, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xb5, 0x96, 0x5f, 0x48, 0x53, + 0x51, 0x1c, 0xc7, 0xcf, 0xdc, 0xbd, 0x77, 0x7f, 0x9c, 0xff, 0x8a, 0x1e, 0x2c, 0x82, 0x08, 0x14, + 0xf4, 0x41, 0x91, 0xa8, 0x17, 0x6b, 0xa9, 0x29, 0x66, 0xa5, 0xa6, 0x96, 0xa9, 0xe8, 0x34, 0x2b, + 0x53, 0x68, 0x69, 0x2f, 0x51, 0x38, 0xa6, 0x9b, 0xae, 0x10, 0x19, 0x3d, 0x58, 0xcb, 0x85, 0x5b, + 0x45, 0x64, 0x7f, 0x96, 0xfd, 0x5f, 0xe9, 0x2c, 0xc8, 0x42, 0xc2, 0x50, 0x49, 0x7b, 0x49, 0x44, + 0xea, 0x21, 0x43, 0x56, 0x84, 0x26, 0xae, 0x4d, 0xda, 0x7e, 0x9d, 0x73, 0xd9, 0x2d, 0x35, 0x67, + 0xd3, 0x76, 0x0f, 0x7c, 0xb9, 0xf7, 0x9c, 0x7b, 0xcf, 0xef, 0x73, 0x7e, 0x7f, 0xce, 0xe1, 0x20, + 0xb4, 0xa0, 0xd5, 0x23, 0x14, 0x8b, 0x1f, 0x02, 0xc4, 0x67, 0xc3, 0x90, 0x2d, 0x58, 0xa0, 0x11, + 0x08, 0x6c, 0x8d, 0x08, 0xad, 0xe7, 0x13, 0x94, 0x44, 0x40, 0xf5, 0x02, 0x01, 0x68, 0x84, 0xc2, + 0x69, 0xfc, 0x5e, 0xc6, 0x2b, 0x68, 0xc0, 0x64, 0x02, 0xb3, 0x5c, 0xee, 0xf1, 0x7a, 0xd7, 0x89, + 0xbd, 0x5b, 0xc7, 0x0b, 0x68, 0xb4, 0xbb, 0x1b, 0x5c, 0x2e, 0x17, 0xf4, 0x19, 0x0c, 0xd0, 0x20, + 0x16, 0xbb, 0x35, 0x41, 0x41, 0xdf, 0xf1, 0x78, 0x05, 0x2f, 0xa0, 0xd9, 0xd9, 0x59, 0x56, 0xf6, + 0x91, 0x11, 0x30, 0x25, 0x26, 0xba, 0xbd, 0x21, 0xb5, 0xea, 0x10, 0x8a, 0xe4, 0x05, 0x44, 0xe4, + 0x72, 0x3a, 0xa1, 0x57, 0xaf, 0x07, 0x2d, 0x4d, 0xbb, 0xb5, 0x42, 0xe1, 0x57, 0xfc, 0x4f, 0x2e, + 0x2f, 0x20, 0x4e, 0x9f, 0x87, 0x86, 0xa0, 0x35, 0x21, 0x81, 0xf3, 0xce, 0x72, 0x06, 0xa1, 0xd5, + 0x7e, 0x1b, 0xd7, 0x20, 0xa4, 0xc4, 0x13, 0xbb, 0x89, 0xf0, 0x7b, 0x3f, 0x31, 0xf2, 0xce, 0x62, + 0x61, 0x0d, 0x4f, 0x8e, 0x8f, 0xb3, 0xa1, 0xe3, 0x44, 0xfa, 0x4e, 0x87, 0x03, 0x7a, 0x74, 0x3a, + 0xd0, 0x52, 0x94, 0x1b, 0x57, 0xe6, 0x17, 0x3c, 0x27, 0xfb, 0xbf, 0x40, 0x8e, 0xa9, 0x29, 0x68, + 0x14, 0x8b, 0x81, 0x5d, 0xbd, 0x57, 0xa4, 0x4f, 0xc6, 0xc9, 0x22, 0xc6, 0x07, 0x07, 0xc1, 0x10, + 0x17, 0xf7, 0xd3, 0xfb, 0xed, 0xf6, 0x59, 0x84, 0x22, 0x56, 0x1c, 0xba, 0xc5, 0x3c, 0x9a, 0x1b, + 0x4a, 0xe7, 0xcc, 0x0c, 0xe7, 0x9d, 0x07, 0xe7, 0xee, 0x13, 0x9e, 0x9b, 0x1a, 0x90, 0x1c, 0xf9, + 0xd2, 0xc7, 0xde, 0x5e, 0x68, 0x89, 0x8e, 0x26, 0xde, 0x91, 0xbd, 0x67, 0xc4, 0x92, 0xf9, 0x0d, + 0x6a, 0xeb, 0xaa, 0x83, 0x19, 0xc7, 0x34, 0x6b, 0x88, 0x0b, 0xd7, 0x52, 0x22, 0xff, 0x3c, 0xad, + 0xa9, 0x21, 0x1b, 0xdc, 0x83, 0x0b, 0xc5, 0x81, 0xed, 0xf4, 0xcc, 0x49, 0x89, 0xd2, 0x27, 0x48, + 0x71, 0x3e, 0x16, 0x8e, 0x9a, 0x36, 0x43, 0xdf, 0x5b, 0x2b, 0x9b, 0x9b, 0xa9, 0x89, 0x09, 0x7e, + 0x40, 0xe5, 0xc6, 0x78, 0xc8, 0x6f, 0x97, 0x82, 0xc2, 0x1c, 0x09, 0xa5, 0xe9, 0x14, 0x8c, 0xbd, + 0xec, 0xf9, 0x2b, 0x47, 0xf3, 0x42, 0x17, 0x15, 0xb5, 0x74, 0xe8, 0xe4, 0xb5, 0xf4, 0x85, 0xe4, + 0x7a, 0xda, 0x48, 0x94, 0x71, 0x9c, 0x7a, 0x54, 0x94, 0x29, 0x04, 0x75, 0x6b, 0x16, 0x14, 0x5f, + 0xdc, 0x08, 0x07, 0x6e, 0x4a, 0xa1, 0xe4, 0xbe, 0x0c, 0x14, 0x1d, 0x21, 0x50, 0x50, 0xc9, 0x40, + 0xed, 0x1a, 0xd1, 0xbc, 0x30, 0x2e, 0x2c, 0x06, 0xbc, 0xf2, 0x1d, 0x3e, 0xf3, 0x92, 0xae, 0xa2, + 0xec, 0x59, 0x97, 0x18, 0x58, 0xa8, 0xdc, 0x2b, 0xe2, 0xdf, 0xa0, 0xf2, 0xae, 0x30, 0xa8, 0x7c, + 0x11, 0x01, 0xc7, 0x3a, 0x62, 0xe0, 0xee, 0x9b, 0x96, 0x95, 0x95, 0xb7, 0x2f, 0x50, 0x8e, 0x59, + 0x04, 0xf9, 0x37, 0xa4, 0x50, 0x7c, 0x4f, 0x06, 0x07, 0x9f, 0x84, 0xc2, 0x91, 0xe7, 0xe1, 0x50, + 0xf5, 0x6a, 0x15, 0x54, 0xd9, 0xd6, 0x82, 0xb2, 0x29, 0x1e, 0xd4, 0xc1, 0x14, 0x39, 0x8e, 0xec, + 0x18, 0x92, 0xe5, 0x57, 0x49, 0xa7, 0xe8, 0xe8, 0xd1, 0xc5, 0x40, 0xd9, 0x6d, 0x22, 0xd8, 0x77, + 0x4d, 0x02, 0x85, 0x96, 0x60, 0x50, 0x3c, 0x0c, 0x81, 0xf2, 0xce, 0x50, 0x38, 0xfc, 0x2c, 0x9c, + 0x05, 0x1e, 0xb2, 0x85, 0x41, 0x9e, 0x5a, 0x34, 0xb9, 0x4b, 0xc9, 0x14, 0xfa, 0xbd, 0x49, 0x7d, + 0x81, 0x58, 0xaf, 0x2e, 0x63, 0xaf, 0xda, 0x25, 0x50, 0x74, 0x27, 0x18, 0x4a, 0x1e, 0xc8, 0xa0, + 0xf4, 0x71, 0x08, 0x94, 0x59, 0x43, 0xd9, 0x67, 0x9e, 0x49, 0x6a, 0x4f, 0xa9, 0x63, 0x9a, 0x03, + 0x02, 0xe2, 0x72, 0xb5, 0xff, 0xba, 0x04, 0x0a, 0x6e, 0x49, 0x59, 0x60, 0x21, 0x56, 0x86, 0x5e, + 0x34, 0x9c, 0xac, 0x16, 0xed, 0x5e, 0xd6, 0x89, 0xfd, 0x2f, 0x10, 0x97, 0xaf, 0xbc, 0xab, 0x62, + 0xc8, 0x69, 0x93, 0xfc, 0x48, 0xd1, 0x32, 0xd6, 0xad, 0xa7, 0x96, 0x71, 0xae, 0x71, 0x2d, 0x49, + 0x4d, 0xf5, 0xa7, 0x35, 0xd1, 0xc3, 0x44, 0x19, 0x5a, 0x7a, 0x6c, 0xef, 0x09, 0x0a, 0x4a, 0xf4, + 0x1b, 0x20, 0xbb, 0x59, 0xf2, 0x07, 0x66, 0x64, 0x20, 0xad, 0x89, 0xf9, 0x20, 0x57, 0xd1, 0xd5, + 0x01, 0xbf, 0x9c, 0x64, 0x56, 0xd3, 0x6e, 0x02, 0xc9, 0x34, 0x30, 0x9e, 0xe4, 0x06, 0xfa, 0xb5, + 0xfc, 0x24, 0x13, 0xc3, 0xcb, 0x75, 0x2b, 0x55, 0x43, 0xbf, 0xdf, 0x79, 0x8e, 0xfe, 0xb6, 0x5d, + 0x45, 0x9b, 0x37, 0x55, 0x20, 0x9a, 0x8f, 0x9b, 0x10, 0x7b, 0x81, 0xdc, 0x76, 0x9a, 0x1e, 0x48, + 0x52, 0x09, 0xf7, 0x04, 0xca, 0xee, 0x2f, 0xa6, 0x8a, 0xf5, 0x99, 0x69, 0x7e, 0xb8, 0x6a, 0x00, + 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, +}; + +const BITMAP_OPAQUE import_part_xpm[1] = {{ png, sizeof( png ), "import_part_xpm" }}; + +//EOF diff --git a/bitmaps_png/cpp_26/new_library.cpp b/bitmaps_png/cpp_26/new_library.cpp index e5b20aca8b..f9a920a7cb 100644 --- a/bitmaps_png/cpp_26/new_library.cpp +++ b/bitmaps_png/cpp_26/new_library.cpp @@ -8,94 +8,74 @@ static const unsigned char png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x08, 0x06, 0x00, 0x00, 0x00, 0xa9, 0x4a, 0x4c, - 0xce, 0x00, 0x00, 0x00, 0x04, 0x73, 0x42, 0x49, 0x54, 0x08, 0x08, 0x08, 0x08, 0x7c, 0x08, 0x64, - 0x88, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0d, 0xd7, 0x00, 0x00, 0x0d, - 0xd7, 0x01, 0x42, 0x28, 0x9b, 0x78, 0x00, 0x00, 0x00, 0x19, 0x74, 0x45, 0x58, 0x74, 0x53, 0x6f, - 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x00, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x6e, 0x6b, 0x73, 0x63, - 0x61, 0x70, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x9b, 0xee, 0x3c, 0x1a, 0x00, 0x00, 0x05, 0x0e, 0x49, - 0x44, 0x41, 0x54, 0x48, 0x89, 0x95, 0x96, 0x5b, 0x68, 0x1c, 0xe7, 0x15, 0x80, 0xbf, 0xf3, 0xff, - 0x73, 0xdb, 0x99, 0x95, 0x54, 0x49, 0x96, 0x2c, 0xa9, 0xb2, 0x14, 0x5b, 0x89, 0xf0, 0x05, 0xc7, - 0x52, 0x52, 0xb0, 0xa9, 0xd4, 0x26, 0x2e, 0x76, 0xd2, 0x42, 0x02, 0xb1, 0xf1, 0x85, 0xa4, 0xb4, - 0x0f, 0xa5, 0xc5, 0xe4, 0x21, 0x0f, 0x01, 0x37, 0x50, 0xd7, 0x34, 0xae, 0x69, 0x63, 0x19, 0x42, - 0x13, 0x68, 0x21, 0x90, 0xbe, 0xd5, 0x14, 0x4c, 0x4d, 0x29, 0x85, 0xa6, 0xd0, 0x36, 0x81, 0x40, - 0x2e, 0x76, 0x52, 0x93, 0x58, 0x06, 0x47, 0xb1, 0xc9, 0xcd, 0x21, 0xad, 0x25, 0x79, 0x55, 0xcb, - 0xd9, 0xfb, 0xce, 0xcc, 0xff, 0xf7, 0x61, 0x6d, 0x27, 0xab, 0xdd, 0x4d, 0xc8, 0x79, 0x9a, 0x73, - 0xe6, 0xcc, 0xf9, 0xe6, 0xdc, 0xfe, 0x19, 0x61, 0x85, 0xec, 0x38, 0xbc, 0x6e, 0x26, 0xb5, 0x76, - 0x58, 0xa5, 0xf2, 0xba, 0xb5, 0x72, 0xee, 0x6f, 0x47, 0xe7, 0x4e, 0xfe, 0xf9, 0xcd, 0x6b, 0x6b, - 0x8c, 0x5d, 0xe9, 0x59, 0x17, 0x47, 0xc3, 0xfe, 0x6d, 0x7d, 0xff, 0x99, 0xbf, 0x34, 0xb3, 0x65, - 0xf9, 0xfc, 0xa1, 0x2b, 0x28, 0x91, 0x26, 0x27, 0x63, 0xad, 0xd3, 0x64, 0x83, 0xef, 0x17, 0x56, - 0xab, 0x61, 0x1d, 0x9b, 0x5d, 0x7e, 0x9e, 0xe4, 0xa3, 0x85, 0x2b, 0x9d, 0x27, 0xce, 0x94, 0x59, - 0x28, 0xb4, 0x06, 0xf5, 0x66, 0x2c, 0x3b, 0x37, 0x7f, 0x4d, 0x3b, 0xae, 0xab, 0x11, 0xdc, 0xf5, - 0xe3, 0xe3, 0x4d, 0x3e, 0xef, 0x5e, 0xbc, 0x48, 0x03, 0xe8, 0xc1, 0x23, 0x43, 0x61, 0xb9, 0xca, - 0xc0, 0xf2, 0xb0, 0x60, 0x95, 0x0e, 0x01, 0x52, 0x5f, 0x30, 0x08, 0x97, 0x16, 0x6b, 0x2d, 0x41, - 0xd3, 0xeb, 0x3c, 0x00, 0xa2, 0x6c, 0x96, 0x1c, 0xa0, 0xb5, 0x6e, 0xe9, 0xa7, 0x3e, 0xaf, 0x94, - 0x4b, 0xde, 0x9d, 0xb1, 0x4f, 0xc9, 0x2a, 0xf0, 0x94, 0x47, 0x5f, 0xd0, 0x87, 0xb4, 0xa8, 0x44, - 0xb3, 0x88, 0x88, 0x38, 0x8d, 0x8e, 0x23, 0xbf, 0x6b, 0x50, 0x1b, 0x32, 0x12, 0xc5, 0x44, 0x2d, - 0xac, 0xdb, 0x26, 0x7a, 0x26, 0x38, 0x70, 0xc7, 0x01, 0x84, 0x2f, 0x07, 0x2d, 0x5d, 0xaf, 0xf5, - 0x85, 0xfe, 0x0a, 0x50, 0xf8, 0x8d, 0xf6, 0x20, 0xb4, 0xbb, 0xed, 0x89, 0x07, 0x7e, 0x15, 0x56, - 0x32, 0x86, 0xb1, 0x8e, 0x31, 0x32, 0x3a, 0x83, 0x93, 0xd6, 0x5d, 0x94, 0x08, 0x5a, 0x09, 0x22, - 0x20, 0x02, 0xc6, 0x82, 0xb9, 0x31, 0x21, 0x5a, 0x8b, 0x64, 0x7a, 0x1f, 0xf9, 0xf5, 0xe0, 0x64, - 0x1e, 0x7a, 0x7a, 0x6e, 0x04, 0x6b, 0x28, 0x56, 0x23, 0x28, 0x21, 0xd9, 0xea, 0x05, 0x19, 0x32, - 0xf9, 0x69, 0x9e, 0x7b, 0x71, 0x09, 0x4f, 0x2b, 0xe2, 0xb4, 0x80, 0x56, 0x8a, 0xc8, 0xd7, 0x68, - 0xad, 0x50, 0x37, 0xde, 0xdb, 0x5a, 0x48, 0x8d, 0xc5, 0xd1, 0x8a, 0x99, 0x17, 0xae, 0x88, 0xab, - 0xe5, 0x47, 0xd5, 0xe4, 0xbb, 0x3c, 0xbc, 0x6d, 0x15, 0xf7, 0x8d, 0x2f, 0x03, 0x8d, 0x63, 0x7a, - 0x0b, 0xbb, 0x77, 0x2f, 0x5a, 0x1b, 0x59, 0x77, 0x68, 0xf6, 0x10, 0x83, 0x83, 0x8b, 0x14, 0xaa, - 0x86, 0x77, 0x73, 0x70, 0x6e, 0x1e, 0xe6, 0x0b, 0x42, 0xe8, 0x3b, 0x44, 0xbe, 0x43, 0x36, 0x70, - 0xc8, 0x06, 0x2e, 0x51, 0xe0, 0x10, 0xfa, 0x0e, 0xb9, 0xb2, 0x66, 0x76, 0x1e, 0x3e, 0xfe, 0x54, - 0xb1, 0x54, 0x34, 0x4c, 0xad, 0x2d, 0xc3, 0x27, 0x3f, 0x6d, 0x0f, 0xba, 0xb6, 0x76, 0x74, 0xdc, - 0x68, 0x1b, 0x17, 0xa5, 0xc2, 0x91, 0x77, 0x7e, 0xc6, 0xb1, 0x3d, 0xc3, 0xf4, 0x87, 0x96, 0x7c, - 0xc5, 0x52, 0xa8, 0x42, 0xe8, 0x6b, 0xa2, 0x40, 0x13, 0x05, 0x2e, 0xd9, 0xa0, 0x0e, 0x0d, 0x7d, - 0xcd, 0x72, 0xd9, 0x92, 0x18, 0xc1, 0xb1, 0x35, 0x9e, 0xd9, 0xdf, 0x4d, 0x94, 0xff, 0x3d, 0x54, - 0xe6, 0x9a, 0xfa, 0x78, 0xab, 0x74, 0xa2, 0xf4, 0x44, 0x35, 0x22, 0x05, 0x88, 0x4d, 0x8c, 0xd7, - 0xb1, 0xc4, 0x23, 0x53, 0x19, 0xe4, 0x74, 0x95, 0x77, 0xae, 0x0a, 0x9e, 0xa3, 0xf0, 0x1d, 0x8d, - 0xeb, 0xd4, 0xdf, 0x2d, 0x4d, 0x0d, 0xd5, 0x44, 0xc8, 0xb8, 0xc2, 0x68, 0x57, 0xca, 0xa3, 0xf7, - 0x0e, 0x24, 0xdd, 0xa5, 0x3f, 0x3a, 0x54, 0xfe, 0xd4, 0x04, 0x69, 0xc8, 0x28, 0x15, 0x7b, 0x57, - 0x25, 0x4b, 0x16, 0x60, 0x63, 0xe7, 0x46, 0x5e, 0x5d, 0x7c, 0x95, 0xb8, 0xfb, 0x35, 0xa6, 0x6f, - 0xf7, 0xd9, 0x34, 0xa8, 0x71, 0xb5, 0x22, 0xf0, 0x34, 0xa1, 0xaf, 0xc9, 0x06, 0x0e, 0x81, 0xa7, - 0x09, 0x5c, 0xc5, 0x78, 0xbf, 0x62, 0xe7, 0x86, 0x88, 0xef, 0x6c, 0x0c, 0x4f, 0xcf, 0xbf, 0xfd, - 0x58, 0x4b, 0x48, 0x03, 0x08, 0x87, 0xa9, 0x38, 0x2b, 0x0a, 0x60, 0x7d, 0xd7, 0x7a, 0xe6, 0xae, - 0xcf, 0x71, 0x78, 0xf6, 0x30, 0x53, 0x1b, 0x3f, 0x61, 0x28, 0x4c, 0x19, 0xed, 0x56, 0x88, 0x80, - 0xa3, 0x14, 0x8e, 0x16, 0x94, 0x12, 0xd6, 0xf6, 0x6a, 0x46, 0x3a, 0x0d, 0xdf, 0x1a, 0x0b, 0xcd, - 0xd2, 0xd2, 0xc9, 0xfd, 0xd6, 0xa6, 0x5f, 0x0e, 0x92, 0x94, 0x4d, 0xb5, 0xb0, 0x7e, 0xbd, 0xa1, - 0x6b, 0x03, 0x73, 0xd7, 0xe7, 0x30, 0xd6, 0xf0, 0xf3, 0xbf, 0x3c, 0x5a, 0x78, 0x72, 0x57, 0xef, - 0x7c, 0xa8, 0xca, 0x74, 0x05, 0x50, 0xae, 0x25, 0x94, 0xaa, 0x29, 0x03, 0x59, 0xc1, 0x31, 0x45, - 0x1e, 0xff, 0xde, 0x08, 0x3f, 0x3c, 0xfe, 0x66, 0xed, 0xf2, 0x99, 0x1f, 0x5c, 0x6f, 0x4b, 0xb9, - 0x09, 0xba, 0xff, 0xd0, 0xe8, 0x20, 0x16, 0x3f, 0xf1, 0xea, 0xb3, 0xdb, 0xe1, 0x76, 0x70, 0x29, - 0x7f, 0x09, 0x80, 0xea, 0xe2, 0xb2, 0x7d, 0xe5, 0xfc, 0x5f, 0x0f, 0x1e, 0xdf, 0x3f, 0xb2, 0xd0, - 0xa9, 0x4a, 0x28, 0x31, 0x44, 0x9e, 0x25, 0xad, 0xe6, 0x79, 0x6a, 0xcf, 0x6d, 0x9c, 0x78, 0x2d, - 0xe6, 0xed, 0xf7, 0x97, 0xdb, 0x1c, 0xb9, 0x2b, 0x40, 0x71, 0xca, 0x44, 0x1c, 0x49, 0xe5, 0xe6, - 0x21, 0xf0, 0xd0, 0xcb, 0x0f, 0x51, 0x4a, 0x4a, 0x48, 0x6a, 0xd1, 0x09, 0x99, 0x3f, 0xfc, 0x63, - 0xe6, 0xd4, 0xaa, 0xc8, 0x3d, 0xfa, 0x93, 0x6f, 0xaf, 0xe2, 0xeb, 0xd9, 0x18, 0xcf, 0x94, 0xf8, - 0xe5, 0xae, 0x21, 0xce, 0x5e, 0xd6, 0xbc, 0x7c, 0xb1, 0x4d, 0xb9, 0x2e, 0x4e, 0x35, 0x83, 0x44, - 0xa9, 0xc9, 0x4a, 0x24, 0x99, 0x95, 0xbe, 0x5e, 0x49, 0x30, 0x9a, 0xcb, 0xa7, 0x8e, 0x5c, 0xa8, - 0x69, 0xcd, 0x73, 0xef, 0x5d, 0xfe, 0x1f, 0x3b, 0xd7, 0x47, 0x1c, 0xd8, 0xde, 0xcb, 0x6d, 0x7d, - 0x19, 0x4e, 0x9c, 0xf9, 0x82, 0x14, 0x56, 0xf4, 0xab, 0xde, 0x23, 0x47, 0xbe, 0x59, 0xcb, 0x5a, - 0xaf, 0x19, 0x64, 0x11, 0x6b, 0xcf, 0xde, 0xd4, 0x7f, 0xfc, 0x9b, 0xb3, 0xdc, 0x3d, 0xd6, 0xcb, - 0x58, 0x7f, 0x17, 0x67, 0x3e, 0x58, 0xb9, 0x92, 0x5f, 0x2c, 0xf5, 0x3d, 0xb2, 0x76, 0xb2, 0x16, - 0xa9, 0xa6, 0x9b, 0x7e, 0xc1, 0x56, 0x54, 0x62, 0x4f, 0xdf, 0xd4, 0x93, 0xd4, 0x72, 0xec, 0xef, - 0x86, 0xd0, 0xd7, 0xe4, 0xda, 0x7c, 0x9f, 0xda, 0x82, 0xee, 0x3b, 0xb8, 0x3a, 0x32, 0xa9, 0xf4, - 0xc7, 0x99, 0xe6, 0x53, 0x3a, 0x28, 0x52, 0x45, 0x71, 0xee, 0xf3, 0xb6, 0x7c, 0x05, 0x4a, 0xf1, - 0x57, 0x83, 0x00, 0xa8, 0xd4, 0x0d, 0xee, 0x8c, 0x3d, 0x4a, 0xae, 0xf6, 0x38, 0x3e, 0x79, 0x9c, - 0xe7, 0xb7, 0x3e, 0x4f, 0x7f, 0xd0, 0x8f, 0x58, 0xd0, 0x65, 0x42, 0xcf, 0x9a, 0xf3, 0x5f, 0x3d, - 0x6c, 0x0b, 0x90, 0x18, 0x3d, 0x51, 0xcd, 0xe2, 0x4c, 0xf7, 0x4f, 0xb3, 0x7b, 0x64, 0x37, 0xdb, - 0x07, 0xb6, 0xb3, 0x6f, 0x74, 0x1f, 0x4e, 0xc5, 0x62, 0x85, 0xe5, 0x17, 0x66, 0x3e, 0xbe, 0xb6, - 0xf2, 0xa1, 0xe1, 0x6e, 0xd8, 0x73, 0x17, 0xac, 0xee, 0x6c, 0x13, 0x35, 0x9c, 0x80, 0xa1, 0x27, - 0x21, 0xb3, 0xf9, 0x96, 0xc9, 0xb1, 0x8e, 0xdd, 0x5a, 0xeb, 0x90, 0xf0, 0xc2, 0xf2, 0x05, 0x72, - 0xd5, 0x1c, 0x1d, 0x6e, 0x07, 0x6f, 0xe4, 0xde, 0xc0, 0x2b, 0x82, 0x55, 0xcc, 0xb6, 0x8a, 0xf3, - 0xf8, 0x0e, 0x58, 0xd3, 0x0d, 0x5b, 0xd6, 0xc0, 0xc1, 0x93, 0x2d, 0x1c, 0x86, 0x8e, 0x82, 0x3f, - 0x06, 0x99, 0x2d, 0xf0, 0xfe, 0xee, 0x3a, 0xc8, 0xc0, 0xd6, 0x5a, 0x28, 0x7c, 0x5a, 0x59, 0xe0, - 0x9e, 0x7f, 0xde, 0x83, 0xa7, 0x3c, 0x0a, 0x49, 0x81, 0x9e, 0x22, 0x89, 0xb2, 0xe6, 0xf5, 0x56, - 0xa0, 0x5c, 0xbe, 0x0e, 0xba, 0x9a, 0x6f, 0x93, 0x51, 0x69, 0xb6, 0x0e, 0x2a, 0x7d, 0xd6, 0x5e, - 0x47, 0xa5, 0x32, 0xe6, 0x54, 0xc1, 0xa9, 0x42, 0xcd, 0xaf, 0x51, 0x33, 0xf5, 0x9f, 0x10, 0xbf, - 0x60, 0x8b, 0x92, 0xf0, 0x56, 0xab, 0x38, 0x4f, 0xff, 0x0b, 0x46, 0x7b, 0xe1, 0xc3, 0x5c, 0x1b, - 0xd0, 0x7f, 0x7f, 0x01, 0x8b, 0xbf, 0x85, 0xe4, 0xea, 0x67, 0x20, 0xb0, 0xcf, 0xf6, 0x7c, 0xc4, - 0x14, 0xc6, 0x6c, 0x46, 0x70, 0xe3, 0x90, 0x4a, 0xb5, 0x43, 0x45, 0x5e, 0x91, 0xc0, 0x38, 0x72, - 0xae, 0x55, 0x9c, 0x38, 0x81, 0xf7, 0x16, 0xda, 0x40, 0x00, 0xb0, 0x90, 0x2c, 0x36, 0x58, 0x1a, - 0x66, 0xfa, 0xde, 0x27, 0x6e, 0x1f, 0xf6, 0x24, 0x9d, 0x34, 0x62, 0xef, 0xb6, 0x22, 0x9b, 0x5e, - 0x3a, 0xf6, 0xe1, 0x3e, 0x6e, 0xed, 0xa5, 0x15, 0x76, 0x9c, 0x32, 0xad, 0xc2, 0x8a, 0x92, 0xfc, - 0xbf, 0x1f, 0xdb, 0x3b, 0x10, 0x94, 0x29, 0xb6, 0xdc, 0x62, 0x81, 0xff, 0x03, 0xfb, 0x5a, 0xcd, - 0xb5, 0xd6, 0xa0, 0xef, 0x61, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, - 0x82, + 0xce, 0x00, 0x00, 0x04, 0x20, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xad, 0x96, 0x7b, 0x6c, 0x53, + 0x55, 0x18, 0xc0, 0x6f, 0x57, 0xb3, 0x88, 0x33, 0x8b, 0x28, 0x66, 0xd6, 0xa9, 0xed, 0x3d, 0xb7, + 0xb0, 0xd1, 0xb1, 0xd2, 0xb9, 0xc9, 0x63, 0x64, 0xac, 0x6b, 0xbb, 0x4e, 0x79, 0x64, 0x44, 0x58, + 0x84, 0xfd, 0xc3, 0x1f, 0x26, 0xf8, 0x08, 0x68, 0x0c, 0xda, 0xe7, 0x9a, 0x55, 0x1e, 0x66, 0x42, + 0xd4, 0x39, 0xd0, 0x41, 0x86, 0x03, 0xc5, 0x0c, 0xda, 0x59, 0xe7, 0x1e, 0x19, 0x53, 0x64, 0x40, + 0x16, 0x18, 0x41, 0x40, 0x71, 0x35, 0xe3, 0x51, 0x25, 0x98, 0x2c, 0x1a, 0x2a, 0x5b, 0x5b, 0x58, + 0xdb, 0xf5, 0xb1, 0xcf, 0xef, 0xb6, 0xd9, 0x56, 0x7b, 0xdb, 0x6c, 0xc3, 0x9e, 0xe4, 0x97, 0x9e, + 0x9c, 0xdc, 0x7c, 0xbf, 0xfb, 0x9d, 0xfb, 0xf5, 0x7c, 0x87, 0x02, 0xa0, 0x1e, 0x46, 0xb2, 0x91, + 0xe5, 0xc8, 0xfa, 0x2f, 0x4f, 0xcd, 0x6d, 0xaf, 0xb3, 0xcd, 0x3b, 0x55, 0xfb, 0x75, 0xd6, 0xce, + 0x37, 0x1b, 0x9e, 0x55, 0x6f, 0x6b, 0x78, 0x3c, 0x93, 0x9a, 0xc1, 0x38, 0x6f, 0xa5, 0xe6, 0xd8, + 0x2d, 0x54, 0xc0, 0xde, 0xca, 0x0b, 0x72, 0xc0, 0x75, 0x0a, 0x83, 0x0b, 0x90, 0x17, 0x91, 0x9d, + 0x88, 0xf5, 0xe2, 0x8d, 0x39, 0xbe, 0x6f, 0x07, 0x32, 0xe1, 0xc3, 0x93, 0x4f, 0x8c, 0xbd, 0xda, + 0x98, 0x7d, 0x6f, 0x4d, 0x2d, 0x1d, 0x2c, 0x37, 0xd1, 0x43, 0x0a, 0x23, 0xdd, 0x51, 0xae, 0x21, + 0x45, 0xc9, 0x44, 0x97, 0x3a, 0xa9, 0x47, 0xec, 0x56, 0x0a, 0x42, 0x57, 0x73, 0x38, 0xb0, 0xeb, + 0xac, 0x48, 0x86, 0x18, 0x90, 0xb3, 0xe3, 0x40, 0x0d, 0xb9, 0xee, 0xf3, 0xc1, 0xe1, 0x49, 0x07, + 0xdb, 0xed, 0x4c, 0x78, 0xfd, 0x82, 0x00, 0x8a, 0x4f, 0xd0, 0x90, 0xdf, 0x42, 0x40, 0x6e, 0xa2, + 0xbd, 0x2a, 0x9d, 0x48, 0x3e, 0x9d, 0x08, 0xec, 0x12, 0x0e, 0x13, 0xa2, 0x52, 0xa4, 0x11, 0x71, + 0x84, 0xc7, 0xa9, 0xb1, 0x50, 0x98, 0x07, 0xae, 0x31, 0x3e, 0xf4, 0x3b, 0x33, 0xa0, 0xce, 0x8e, + 0x82, 0x1f, 0x84, 0x20, 0x69, 0x67, 0x40, 0xa9, 0x27, 0x01, 0xf9, 0xf6, 0xc2, 0x79, 0x54, 0x95, + 0x95, 0xcf, 0xc1, 0x6c, 0x4e, 0xe3, 0x88, 0x3c, 0xbd, 0x1c, 0xd1, 0x4a, 0x64, 0x3f, 0x72, 0x23, + 0x14, 0xa6, 0x02, 0x41, 0x14, 0x8d, 0xa0, 0xe8, 0xd7, 0x11, 0x01, 0x5c, 0xf7, 0xbc, 0x07, 0xa5, + 0x28, 0x92, 0x5a, 0x08, 0x28, 0x0c, 0xe4, 0x0e, 0xa5, 0xb2, 0x42, 0x22, 0x78, 0xea, 0x56, 0x0f, + 0x47, 0x14, 0xf2, 0x70, 0x44, 0x8b, 0x90, 0xed, 0xc8, 0xf7, 0xae, 0x51, 0xfe, 0x3d, 0xe7, 0x28, + 0x1f, 0x06, 0xdd, 0xe9, 0x70, 0xe9, 0xee, 0x0b, 0xd0, 0x3d, 0xb4, 0x15, 0x96, 0xe2, 0xd6, 0x15, + 0x7c, 0xc1, 0x40, 0x99, 0x91, 0xfc, 0xc8, 0x06, 0x5d, 0xb7, 0x3f, 0x00, 0xeb, 0x1b, 0xc3, 0x93, + 0xac, 0xfa, 0xf8, 0x3e, 0xa4, 0xa9, 0xbf, 0xf1, 0xce, 0x44, 0xf4, 0x24, 0x22, 0x47, 0x74, 0xa7, + 0x07, 0x32, 0x5c, 0x27, 0x6e, 0x3d, 0x0a, 0x87, 0x1d, 0x8f, 0xc1, 0xc5, 0x7f, 0xde, 0x82, 0x0f, + 0x06, 0x36, 0x43, 0x7e, 0x27, 0x03, 0x4b, 0x3f, 0x65, 0x82, 0x4a, 0x03, 0xbd, 0x83, 0x15, 0xbd, + 0xfc, 0x79, 0x08, 0xaa, 0x0e, 0xc2, 0x24, 0x6b, 0xea, 0xbd, 0x33, 0x16, 0xa5, 0x23, 0x59, 0x81, + 0x00, 0x55, 0xa8, 0x6f, 0x7e, 0x2a, 0xf8, 0xda, 0x39, 0x01, 0x6c, 0xec, 0xcb, 0x86, 0x9b, 0x9e, + 0x1e, 0xa8, 0x3c, 0xad, 0x80, 0x9c, 0x76, 0x31, 0x94, 0xec, 0x26, 0x2e, 0xa5, 0x86, 0x59, 0xf7, + 0x7f, 0x45, 0x3c, 0xe4, 0xa1, 0x6d, 0x0d, 0x4f, 0x17, 0x54, 0xee, 0x16, 0x8e, 0x16, 0x76, 0xd3, + 0x50, 0xd4, 0xbd, 0x00, 0xdc, 0x81, 0x3b, 0xb0, 0xb0, 0x23, 0x07, 0xc4, 0xdf, 0x89, 0x01, 0x4b, + 0xdb, 0x2b, 0xd7, 0xe5, 0x8a, 0x62, 0x45, 0x9d, 0x57, 0x67, 0x29, 0x9a, 0x18, 0x15, 0x06, 0x52, + 0x5d, 0x52, 0x47, 0xdc, 0x0b, 0x30, 0x83, 0xb5, 0x67, 0x56, 0xc3, 0xcf, 0xc3, 0x57, 0x22, 0x92, + 0x1c, 0x2b, 0x5b, 0x71, 0xb4, 0x97, 0xa2, 0xcc, 0x69, 0xb1, 0x22, 0x8f, 0xef, 0x01, 0x45, 0x0a, + 0x3d, 0xbd, 0xb7, 0x70, 0x1f, 0x09, 0xb3, 0xc1, 0x35, 0x97, 0x35, 0xd0, 0x72, 0xab, 0x25, 0x22, + 0x92, 0x1e, 0x61, 0x33, 0x22, 0x97, 0x29, 0x0a, 0x78, 0xa9, 0x11, 0x99, 0xe8, 0xf3, 0xd2, 0xc3, + 0x4c, 0x24, 0x78, 0xb3, 0xa3, 0x19, 0x4c, 0xbf, 0x98, 0x22, 0xf3, 0xa2, 0xcf, 0x98, 0x71, 0x95, + 0x91, 0xde, 0x97, 0x32, 0x11, 0x56, 0x95, 0x3b, 0xd7, 0x12, 0x15, 0xf5, 0x3b, 0xfb, 0x61, 0xc3, + 0xd9, 0x0d, 0x91, 0x79, 0xf1, 0x1e, 0xe2, 0x51, 0xea, 0x45, 0x9b, 0x53, 0x22, 0xaa, 0x30, 0x08, + 0x05, 0xf8, 0x1d, 0xfc, 0xe2, 0x36, 0x71, 0x24, 0xb8, 0xdd, 0x65, 0x07, 0x69, 0x97, 0x34, 0x32, + 0x2f, 0x33, 0x11, 0x4f, 0x85, 0x96, 0x5e, 0x9c, 0x12, 0x91, 0x42, 0x2b, 0x7c, 0x69, 0xe5, 0x2e, + 0xe2, 0x62, 0x03, 0xc7, 0x32, 0xdf, 0xc6, 0x80, 0x4a, 0x4f, 0x82, 0x55, 0xe6, 0xbc, 0xf4, 0x59, + 0x8b, 0x7e, 0xcb, 0xe7, 0x8a, 0x30, 0x1b, 0xc3, 0x92, 0x4f, 0x98, 0xb1, 0x78, 0x51, 0xde, 0x51, + 0x2c, 0x84, 0x1a, 0xe2, 0x88, 0x6e, 0xee, 0x2c, 0x45, 0xf1, 0x87, 0x6a, 0x44, 0x64, 0x22, 0x5d, + 0xb2, 0x26, 0x02, 0xf1, 0xa2, 0x82, 0x83, 0x58, 0xda, 0x46, 0xfa, 0x78, 0x22, 0xd1, 0x99, 0xeb, + 0x0f, 0x22, 0xaa, 0xa1, 0x87, 0x24, 0x2d, 0x0c, 0x47, 0xb4, 0xec, 0x23, 0xe2, 0x2b, 0xd7, 0x8a, + 0xde, 0x4e, 0x24, 0x9a, 0xf6, 0x64, 0x88, 0x17, 0xa9, 0xdf, 0xcd, 0xca, 0x60, 0xbf, 0xc3, 0xfc, + 0x36, 0x31, 0x47, 0x24, 0xdf, 0x41, 0x5c, 0xe5, 0x7a, 0x51, 0x69, 0x4a, 0x44, 0x4a, 0xbd, 0x70, + 0x79, 0x69, 0x2d, 0x71, 0x4b, 0x3a, 0x24, 0xd8, 0xec, 0x6c, 0xd0, 0xfb, 0x57, 0x2f, 0x14, 0xf7, + 0x14, 0x03, 0x2b, 0x66, 0x7b, 0xd0, 0x6a, 0xdd, 0x73, 0x73, 0x53, 0x22, 0x52, 0x69, 0xc9, 0x1b, + 0xcb, 0xf6, 0x92, 0xd1, 0x2d, 0x17, 0xb6, 0xc0, 0xc4, 0xa8, 0x1f, 0xac, 0x87, 0x85, 0xc7, 0x98, + 0x68, 0x0f, 0x9a, 0x1c, 0x53, 0xa2, 0x77, 0xac, 0x00, 0x96, 0x9f, 0x00, 0xb6, 0x1e, 0x4b, 0x22, + 0xfa, 0xa3, 0x1a, 0x60, 0xd8, 0x02, 0xf0, 0xfb, 0x2b, 0x31, 0x19, 0x19, 0xe9, 0x23, 0xcf, 0x1f, + 0x20, 0xb0, 0xa2, 0x67, 0x05, 0x38, 0xfd, 0x4e, 0xf0, 0x87, 0xfd, 0xb0, 0xa9, 0x6f, 0x13, 0x2c, + 0x3e, 0x84, 0x3d, 0xa8, 0x86, 0x9c, 0x4c, 0x24, 0xfa, 0x73, 0x38, 0xfa, 0x42, 0xd7, 0xfe, 0x4e, + 0x22, 0xf2, 0x3b, 0xa2, 0x0f, 0xf8, 0xae, 0x4d, 0x89, 0xca, 0x8c, 0xf4, 0xe0, 0xa2, 0xaf, 0xa2, + 0x85, 0xc0, 0x6e, 0x9f, 0xac, 0x4b, 0x16, 0x99, 0x2f, 0x61, 0x7b, 0x90, 0x51, 0xf4, 0x7e, 0x22, + 0xd1, 0x95, 0xdb, 0xd1, 0x38, 0x7d, 0x37, 0x93, 0x88, 0x86, 0x6d, 0xd1, 0x07, 0xee, 0x1e, 0x8f, + 0xc9, 0x48, 0x47, 0x02, 0xb2, 0x26, 0x06, 0x72, 0x2d, 0xff, 0x2d, 0x04, 0xb6, 0x07, 0xa9, 0xb4, + 0xa2, 0xca, 0x44, 0xa2, 0xea, 0x43, 0x00, 0xfa, 0x36, 0x80, 0x8d, 0x4d, 0xc9, 0xbe, 0x51, 0x1e, + 0xa6, 0x2b, 0x8f, 0xfe, 0x4e, 0x89, 0xe8, 0x3d, 0x78, 0x3a, 0x9f, 0xc3, 0xd3, 0xdb, 0xa3, 0x30, + 0xd0, 0xbe, 0x92, 0x5d, 0xf4, 0x08, 0x66, 0x13, 0x50, 0x1a, 0x88, 0x1f, 0xfb, 0x90, 0x30, 0x91, + 0xa8, 0xea, 0x00, 0x4c, 0x32, 0xab, 0xff, 0xd1, 0xc4, 0x90, 0x6b, 0xc4, 0xcf, 0xa8, 0xb5, 0xf4, + 0x5a, 0xbc, 0x56, 0x99, 0xf1, 0xb4, 0x68, 0xc5, 0x25, 0x5e, 0xbc, 0x68, 0xba, 0xcb, 0x09, 0x5e, + 0x16, 0xb9, 0xe0, 0xfa, 0xbf, 0x1c, 0x59, 0xd1, 0x95, 0xe1, 0x38, 0xaf, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; const BITMAP_OPAQUE new_library_xpm[1] = {{ png, sizeof( png ), "new_library_xpm" }}; diff --git a/bitmaps_png/cpp_26/save_library.cpp b/bitmaps_png/cpp_26/save_library.cpp index 8ae7fb3c30..f617babf02 100644 --- a/bitmaps_png/cpp_26/save_library.cpp +++ b/bitmaps_png/cpp_26/save_library.cpp @@ -8,58 +8,90 @@ static const unsigned char png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x08, 0x06, 0x00, 0x00, 0x00, 0xa9, 0x4a, 0x4c, - 0xce, 0x00, 0x00, 0x03, 0x22, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xed, 0x95, 0x6b, 0x48, 0x53, - 0x61, 0x18, 0xc7, 0xd7, 0x07, 0x71, 0x69, 0x48, 0x6a, 0x69, 0x11, 0x45, 0x5a, 0x61, 0x50, 0x39, - 0xe7, 0x1d, 0x0b, 0xcb, 0x2e, 0x8a, 0x74, 0x45, 0x0a, 0x2c, 0xf2, 0x82, 0x1f, 0x8a, 0x8c, 0x28, - 0x4c, 0xbc, 0x24, 0x86, 0x6e, 0x35, 0x75, 0xb1, 0x74, 0x17, 0xdc, 0x25, 0x82, 0x70, 0xd0, 0x87, - 0x72, 0x31, 0x51, 0x19, 0x44, 0x28, 0xce, 0x30, 0xe7, 0x19, 0x23, 0x9a, 0x39, 0x37, 0xef, 0xcc, - 0xa6, 0xa2, 0x42, 0x37, 0x2b, 0x45, 0x7c, 0x7a, 0x9f, 0x83, 0x1b, 0x2b, 0x97, 0x66, 0x9b, 0xdf, - 0x3a, 0xf0, 0xe7, 0x5c, 0x9e, 0xe7, 0xf9, 0xff, 0xde, 0xf7, 0x39, 0xef, 0x79, 0x0f, 0x83, 0xb1, - 0xd2, 0x71, 0xb1, 0x75, 0xd3, 0xbe, 0x22, 0xc3, 0x38, 0xbb, 0xd4, 0xe8, 0x52, 0x7b, 0xf2, 0x0d, - 0x36, 0x46, 0x76, 0xeb, 0x46, 0x86, 0xdb, 0x07, 0x01, 0xc5, 0x94, 0xf7, 0x4c, 0xad, 0xbf, 0x66, - 0x04, 0x57, 0x22, 0xb1, 0x49, 0x46, 0xe6, 0xab, 0xc0, 0xff, 0xa0, 0x65, 0x41, 0x3e, 0xb9, 0x46, - 0xd8, 0x70, 0xbd, 0x9b, 0x96, 0x6f, 0x6e, 0xb7, 0xfb, 0x20, 0x66, 0x0e, 0x15, 0xea, 0x93, 0xdd, - 0x71, 0x0e, 0xc5, 0xcc, 0x6a, 0xcb, 0x8c, 0xe3, 0x98, 0xa6, 0x03, 0x6e, 0xf6, 0x40, 0x50, 0x9e, - 0x09, 0x82, 0x6f, 0xf7, 0xc2, 0x16, 0xa2, 0xa0, 0xbc, 0x5e, 0x08, 0xbc, 0x65, 0x02, 0x8c, 0x61, - 0x8e, 0x23, 0x9f, 0xd4, 0xfe, 0x35, 0xc8, 0xeb, 0xf2, 0x9b, 0xc8, 0xa8, 0xd2, 0x77, 0x53, 0xb1, - 0x5c, 0x33, 0x44, 0x73, 0xcc, 0x10, 0xcf, 0x1b, 0x80, 0xed, 0x05, 0x16, 0x08, 0x29, 0xee, 0x83, - 0x5d, 0x25, 0xfd, 0xb4, 0x42, 0xef, 0xf4, 0xc3, 0x8e, 0x42, 0x0b, 0x24, 0xf2, 0x07, 0x21, 0x86, - 0xe4, 0x1c, 0xaa, 0xb4, 0x40, 0x58, 0xc1, 0xdb, 0x69, 0xaf, 0xac, 0xce, 0xa8, 0x55, 0xcd, 0xca, - 0xef, 0x4a, 0xc7, 0xa5, 0xa4, 0x2a, 0xcb, 0xc7, 0x6d, 0xf9, 0xbd, 0xb0, 0x93, 0x00, 0xc2, 0x4a, - 0x07, 0x60, 0x7f, 0xd9, 0x10, 0xb0, 0x38, 0xc3, 0xc0, 0xe2, 0x0e, 0xc3, 0x81, 0xf2, 0x61, 0xd8, - 0x7b, 0x77, 0x90, 0x06, 0x86, 0x14, 0x5b, 0xe0, 0x28, 0xdf, 0xfc, 0x89, 0x99, 0xd3, 0x9e, 0xf9, - 0x4f, 0x2d, 0xdc, 0x7a, 0x83, 0xaa, 0x3e, 0xfe, 0x70, 0x70, 0x2e, 0x8c, 0x18, 0xa2, 0x79, 0x6c, - 0x85, 0x15, 0x12, 0xf8, 0xa3, 0x70, 0xf0, 0xc1, 0x28, 0xc4, 0x55, 0x5a, 0x81, 0x7d, 0x6f, 0x84, - 0x86, 0x9f, 0x12, 0x0e, 0xcd, 0xfa, 0x5f, 0xed, 0xe4, 0xad, 0xca, 0x5c, 0x26, 0x93, 0xb1, 0x14, - 0x0a, 0x45, 0x21, 0x4a, 0x2e, 0x7f, 0x54, 0x94, 0x50, 0xd2, 0x61, 0x4a, 0x11, 0x5a, 0x69, 0xc8, - 0x61, 0x81, 0x0d, 0x4e, 0x88, 0xc6, 0x21, 0x59, 0x34, 0x01, 0x49, 0xd5, 0x63, 0x10, 0x5f, 0x35, - 0x0a, 0x69, 0x32, 0xeb, 0x42, 0x74, 0xc1, 0x6b, 0xa3, 0xbd, 0x06, 0x85, 0x1e, 0x2b, 0x82, 0x48, - 0xe2, 0xfb, 0xfa, 0xfa, 0x7a, 0x50, 0xab, 0xd5, 0xb4, 0x9e, 0xa9, 0x1a, 0xe0, 0x4c, 0x95, 0x01, - 0x4e, 0x8a, 0x6d, 0x70, 0xac, 0x66, 0x0c, 0x4e, 0x4b, 0x27, 0xe1, 0xac, 0x7c, 0x8a, 0x06, 0x5e, - 0x50, 0x4c, 0x40, 0xea, 0x7d, 0x1d, 0x3c, 0x7f, 0xa1, 0x76, 0xe4, 0x63, 0x2d, 0x7a, 0x2c, 0x0b, - 0x11, 0x0a, 0x85, 0x49, 0x24, 0xe9, 0x0b, 0x45, 0x51, 0xd0, 0xd2, 0xd2, 0x02, 0x5a, 0xad, 0x16, - 0xf4, 0x7a, 0x3d, 0x68, 0xda, 0xf4, 0x90, 0x21, 0x35, 0x43, 0xaa, 0x64, 0x8c, 0xcc, 0x66, 0x1c, - 0x52, 0xc4, 0x13, 0x90, 0x26, 0x27, 0xaa, 0xee, 0x81, 0x97, 0x5a, 0x8a, 0xce, 0xc1, 0x5c, 0xac, - 0xc1, 0x6b, 0xe2, 0xf1, 0x59, 0x2c, 0x16, 0x1f, 0xf9, 0x23, 0x48, 0x24, 0x12, 0xb5, 0x37, 0x35, - 0x35, 0x2d, 0x74, 0x75, 0x75, 0x01, 0x39, 0x83, 0x4e, 0xa7, 0xa3, 0x0b, 0x51, 0x52, 0x75, 0x17, - 0x64, 0x28, 0x06, 0x21, 0x51, 0xf0, 0x01, 0x92, 0x85, 0x36, 0x38, 0x2f, 0xe9, 0x03, 0xa5, 0x86, - 0x72, 0xc4, 0x9d, 0x6b, 0x9a, 0x9b, 0x9b, 0x17, 0x24, 0x12, 0x49, 0xbb, 0x4b, 0x88, 0x40, 0x20, - 0x60, 0xd5, 0xd4, 0xd4, 0xcc, 0x60, 0x01, 0x8e, 0xcc, 0x3e, 0x3a, 0x67, 0x95, 0x3c, 0xa1, 0x20, - 0x5d, 0x36, 0x02, 0xe9, 0xd2, 0x21, 0xa8, 0x78, 0x4a, 0x2d, 0x89, 0xdb, 0xeb, 0xb0, 0x23, 0xc4, - 0xeb, 0x2b, 0x9f, 0xcf, 0x8f, 0x5c, 0x02, 0x22, 0x0f, 0x1b, 0x54, 0x2a, 0xd5, 0xbc, 0xab, 0xd9, - 0x38, 0x2b, 0x43, 0xa8, 0x87, 0x5c, 0x99, 0xde, 0x65, 0xcc, 0xb9, 0x96, 0xbc, 0xab, 0x79, 0xf4, - 0xfc, 0x05, 0xc2, 0xe5, 0x72, 0x43, 0x78, 0x3c, 0xde, 0x37, 0x4c, 0xc0, 0x5e, 0x37, 0x36, 0x36, - 0xba, 0x25, 0xf4, 0x40, 0x2f, 0xe2, 0x39, 0x53, 0x56, 0x56, 0xb6, 0xdb, 0x01, 0xe2, 0x70, 0x38, - 0x8f, 0xeb, 0xea, 0xea, 0x66, 0x5d, 0x8d, 0xd2, 0x1d, 0x29, 0x95, 0xca, 0x39, 0xf4, 0x76, 0x80, - 0xc8, 0x0a, 0xf9, 0x51, 0x5b, 0x5b, 0x0b, 0x6b, 0x21, 0xb2, 0x28, 0xbe, 0xdb, 0x39, 0xeb, 0xf0, - 0x81, 0xcd, 0x66, 0xf3, 0xb8, 0xac, 0x56, 0x2b, 0x0d, 0x43, 0x06, 0xbd, 0x87, 0xda, 0x41, 0x9e, - 0x6e, 0x9d, 0x46, 0xa3, 0xb1, 0x83, 0xbc, 0xe8, 0xbf, 0x82, 0x27, 0x41, 0xe1, 0x86, 0x70, 0x88, - 0x30, 0x44, 0xd0, 0xd7, 0xb8, 0x30, 0x16, 0x41, 0x4c, 0x04, 0xf9, 0x7a, 0x12, 0x84, 0x10, 0xb6, - 0x81, 0xfd, 0x3b, 0xc8, 0x97, 0xfe, 0x23, 0xe0, 0x0d, 0xf6, 0xd3, 0xd3, 0xad, 0x73, 0x02, 0xf9, - 0x21, 0xc8, 0x1f, 0x6f, 0xb0, 0x9f, 0xee, 0x7e, 0x3f, 0xae, 0xb4, 0x08, 0xf2, 0x47, 0x50, 0x00, - 0xd9, 0xd6, 0xdb, 0xd7, 0x6a, 0x79, 0x93, 0x0d, 0x56, 0x8b, 0x0c, 0x04, 0x79, 0x13, 0x6d, 0x26, - 0x0a, 0x5e, 0x23, 0xa1, 0xb7, 0xf7, 0x4f, 0x9c, 0xdd, 0x44, 0xac, 0x31, 0x0f, 0x89, 0xb8, 0x00, - 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, + 0xce, 0x00, 0x00, 0x05, 0x24, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xad, 0xd6, 0x7f, 0x50, 0x93, + 0x75, 0x1c, 0x07, 0xf0, 0x91, 0x5d, 0x77, 0x69, 0x67, 0x75, 0xdd, 0x69, 0x5a, 0x17, 0x7b, 0x9e, + 0x0d, 0x7f, 0x80, 0x09, 0x81, 0x1a, 0x48, 0x8a, 0xec, 0x07, 0x6a, 0x61, 0x9e, 0xe9, 0x34, 0xe9, + 0x3a, 0xb5, 0x3f, 0x2c, 0xcc, 0xea, 0xec, 0x0c, 0xf6, 0x03, 0x4e, 0x48, 0x31, 0x83, 0x48, 0x44, + 0x45, 0x74, 0x8a, 0x16, 0x2a, 0x0e, 0x22, 0x4a, 0xed, 0xc2, 0x32, 0x3b, 0xfc, 0x91, 0x65, 0x59, + 0x19, 0x9b, 0x0c, 0xf7, 0x6c, 0x83, 0x31, 0xd8, 0xc6, 0x04, 0xc7, 0x60, 0x30, 0x60, 0xe3, 0xdd, + 0xf3, 0xec, 0xb9, 0x89, 0xb0, 0xa1, 0x70, 0xe7, 0x73, 0xf7, 0xbe, 0xe7, 0x7b, 0xdf, 0x7d, 0xf7, + 0xbc, 0xf6, 0x7d, 0x9e, 0xcf, 0xf3, 0xfd, 0x8e, 0xc3, 0x19, 0x76, 0x88, 0x32, 0xc8, 0x5d, 0x89, + 0x0a, 0xe2, 0xb8, 0x50, 0x4a, 0x6e, 0x12, 0xa4, 0xf3, 0xe6, 0x77, 0xf7, 0xf6, 0x99, 0x4a, 0x2f, + 0xd9, 0xf0, 0xd5, 0xc5, 0xe0, 0x39, 0x71, 0xc5, 0x06, 0x8f, 0x77, 0xc0, 0x6c, 0xae, 0xdb, 0xf9, + 0x8c, 0x5a, 0xc5, 0xe9, 0x53, 0x57, 0x84, 0xf4, 0x07, 0x84, 0xee, 0x1f, 0xee, 0x70, 0x04, 0x19, + 0x64, 0xd3, 0xdc, 0x42, 0x1e, 0x62, 0xf3, 0x09, 0x57, 0x42, 0x16, 0xd9, 0x71, 0xd3, 0xd4, 0x88, + 0xa4, 0x3c, 0x2d, 0x22, 0xb7, 0x05, 0x8f, 0x60, 0x57, 0x1d, 0x5a, 0x9d, 0xbd, 0x16, 0x2b, 0x95, + 0x37, 0x49, 0x5d, 0xce, 0x81, 0xe7, 0xc6, 0xf4, 0x80, 0x30, 0xfd, 0x43, 0x90, 0x65, 0x59, 0x53, + 0xc7, 0x8b, 0x64, 0x64, 0x7f, 0xd8, 0xb7, 0x7c, 0xf0, 0xbf, 0x63, 0x53, 0x6b, 0x33, 0x41, 0x94, + 0x57, 0x8f, 0xc7, 0x53, 0x6b, 0x83, 0x46, 0x4c, 0x7f, 0xc6, 0x40, 0x9d, 0xd6, 0x03, 0x3e, 0x08, + 0xea, 0xf0, 0x80, 0x04, 0x40, 0xa2, 0x34, 0x6e, 0x2c, 0x33, 0x0b, 0x06, 0x08, 0x3f, 0x1d, 0x8e, + 0xb8, 0xea, 0x38, 0xa8, 0x5b, 0x9b, 0x46, 0x01, 0xf5, 0x59, 0xbb, 0x6c, 0xca, 0xc9, 0x43, 0x20, + 0xe7, 0x85, 0x91, 0x21, 0xb1, 0x94, 0xfb, 0x5e, 0x5c, 0x2e, 0xe9, 0x62, 0xa0, 0x94, 0xcb, 0x29, + 0xa8, 0xb1, 0xd5, 0x40, 0xd3, 0x6a, 0x7e, 0x20, 0x54, 0xd7, 0xd4, 0xe5, 0xed, 0x6a, 0x3d, 0xfa, + 0xec, 0x10, 0xc8, 0xe3, 0xbc, 0x0f, 0xa4, 0x08, 0x3b, 0x56, 0x75, 0x53, 0x85, 0x32, 0x63, 0x19, + 0xae, 0xdd, 0xbe, 0x86, 0xda, 0x3b, 0xb5, 0xa8, 0xbf, 0x6d, 0xf5, 0x41, 0x13, 0x36, 0xa9, 0x31, + 0x71, 0xb3, 0x06, 0x4f, 0x7e, 0xa0, 0xc1, 0x53, 0x1f, 0x6a, 0x30, 0x91, 0x3e, 0x3f, 0xf1, 0xbe, + 0xda, 0x07, 0xdd, 0x6a, 0x71, 0x0d, 0x78, 0xbd, 0xbd, 0x47, 0xda, 0x74, 0x85, 0x40, 0xdb, 0x71, + 0x36, 0x9e, 0xae, 0x91, 0x21, 0xba, 0xda, 0xea, 0x7e, 0x30, 0x9c, 0x46, 0xf5, 0x7f, 0xed, 0xd8, + 0xa0, 0xd4, 0xe1, 0xdd, 0x12, 0x3d, 0xde, 0x51, 0x52, 0x58, 0x9c, 0xaf, 0xc3, 0xa4, 0x2d, 0x75, + 0x98, 0xb2, 0xb5, 0x1e, 0xcf, 0x7d, 0xc2, 0x66, 0x2a, 0xdd, 0x9e, 0xfc, 0xb1, 0x16, 0x4b, 0xbf, + 0xd4, 0xf9, 0xc6, 0x30, 0x63, 0xd7, 0x1f, 0xba, 0x85, 0x73, 0xf4, 0x77, 0xe1, 0x36, 0xd0, 0x50, + 0x67, 0x70, 0x48, 0x22, 0xe1, 0x8c, 0xa3, 0x0b, 0xa1, 0x37, 0xb2, 0x6a, 0x16, 0x6e, 0xd8, 0xb5, + 0x90, 0xec, 0xab, 0x47, 0x42, 0xae, 0x1e, 0xd1, 0xdb, 0x29, 0x44, 0x66, 0x53, 0xe0, 0x4a, 0x75, + 0xe0, 0x2b, 0xf4, 0x98, 0x9e, 0xc9, 0xc4, 0x80, 0xb0, 0x0c, 0x3d, 0x08, 0x19, 0x85, 0xb9, 0x39, + 0x06, 0xc4, 0xd0, 0x63, 0x96, 0x16, 0x18, 0xb1, 0x6c, 0xb7, 0x16, 0x5d, 0x9d, 0xcd, 0x00, 0xb5, + 0x72, 0xe4, 0x5b, 0x27, 0x4a, 0x0b, 0x9d, 0x29, 0xc8, 0x20, 0xba, 0x98, 0xe7, 0xb3, 0xa2, 0x66, + 0x05, 0x28, 0xab, 0x8b, 0xc6, 0x28, 0x84, 0x29, 0x74, 0xe0, 0xc9, 0x29, 0x84, 0x6f, 0x33, 0x20, + 0x72, 0x7b, 0x03, 0xa2, 0x73, 0x4c, 0x88, 0xa1, 0x13, 0xb5, 0xbd, 0x11, 0x11, 0x59, 0x46, 0x1f, + 0x18, 0x99, 0xad, 0xa7, 0x91, 0x7a, 0x50, 0x2d, 0x36, 0xa0, 0x25, 0xeb, 0xfe, 0xcf, 0x48, 0x2c, + 0x25, 0xd7, 0xc6, 0x7f, 0xc6, 0x56, 0x5c, 0xf2, 0xaf, 0xc9, 0x30, 0xb9, 0x4c, 0xa8, 0xfa, 0xa7, + 0x19, 0xab, 0x8b, 0x0c, 0x98, 0x95, 0x6d, 0xa4, 0x81, 0x46, 0xc4, 0x7d, 0x6e, 0xc6, 0xc2, 0xfc, + 0x16, 0x5f, 0xe2, 0x73, 0xcd, 0x98, 0xb3, 0xd3, 0x84, 0x39, 0x39, 0x0d, 0x58, 0xb9, 0x4f, 0x8f, + 0xf3, 0xea, 0x8e, 0xfe, 0x36, 0xaa, 0xe8, 0xc1, 0xc5, 0x20, 0x90, 0x11, 0x79, 0x31, 0x7b, 0x49, + 0x2f, 0x03, 0xa5, 0x5d, 0x4f, 0xc3, 0x49, 0xe3, 0x49, 0x94, 0x37, 0x94, 0xa3, 0xf0, 0xa7, 0x66, + 0xac, 0x39, 0x64, 0xc2, 0xcb, 0xbb, 0x9a, 0x90, 0xb8, 0xdb, 0x82, 0x25, 0xfb, 0x6c, 0x78, 0x75, + 0x7f, 0x2b, 0x84, 0x05, 0x16, 0xbc, 0x92, 0x67, 0x46, 0x8a, 0xd2, 0x84, 0xe2, 0x5f, 0xac, 0x18, + 0x18, 0xe8, 0xbf, 0xa8, 0xa9, 0x18, 0x37, 0x0a, 0x28, 0x93, 0xf8, 0x6d, 0xf6, 0x51, 0x9e, 0xef, + 0x25, 0x2d, 0xa1, 0x4a, 0x90, 0xf9, 0x6f, 0x26, 0xa6, 0x7d, 0x3f, 0x0d, 0xd7, 0xcd, 0x7f, 0x60, + 0xcb, 0x71, 0x23, 0x56, 0x1f, 0x6c, 0x86, 0x80, 0xbe, 0x78, 0x72, 0x91, 0x1d, 0xaf, 0x17, 0xdb, + 0x21, 0x2e, 0xb4, 0xe2, 0xed, 0x12, 0x0b, 0xa4, 0xaa, 0x06, 0x68, 0x1a, 0x9c, 0x5e, 0xbb, 0xbd, + 0x74, 0xca, 0xa8, 0xca, 0x5b, 0x28, 0x27, 0x3a, 0x66, 0xa8, 0x58, 0xe8, 0xaa, 0xfd, 0x2a, 0x56, + 0xd5, 0xac, 0xf2, 0xb5, 0x97, 0xec, 0x8d, 0xee, 0x74, 0xb8, 0x9c, 0x96, 0xf5, 0x74, 0x65, 0xad, + 0x28, 0xb6, 0xf8, 0x66, 0x22, 0xda, 0xc3, 0x20, 0x36, 0x6c, 0x38, 0x4c, 0xc1, 0xe6, 0x1c, 0x40, + 0x4c, 0xea, 0xf9, 0x9e, 0xbf, 0xce, 0x70, 0xc6, 0x3f, 0x10, 0x5a, 0x2c, 0x0f, 0x9d, 0x22, 0x94, + 0x11, 0x6e, 0x7e, 0x15, 0xbb, 0xec, 0xa8, 0x1d, 0x6a, 0xcc, 0x3e, 0x3b, 0xdb, 0xd7, 0x4e, 0xcc, + 0x24, 0x9d, 0x67, 0xae, 0x96, 0xbe, 0x65, 0xa3, 0xdf, 0xfe, 0x75, 0x87, 0xf4, 0x10, 0xef, 0x69, + 0xc6, 0xf2, 0x03, 0x16, 0xa4, 0x1c, 0xa0, 0x60, 0x71, 0x78, 0xf0, 0xc5, 0x8f, 0xbd, 0x78, 0x24, + 0xe9, 0x9b, 0xee, 0x51, 0x41, 0x82, 0xf4, 0xd0, 0xa5, 0x0b, 0x77, 0x90, 0x0e, 0xff, 0xfa, 0xe6, + 0x4f, 0x58, 0x25, 0x0f, 0xcc, 0xda, 0x27, 0xc9, 0x8a, 0x78, 0xcc, 0xeb, 0xc5, 0xa6, 0xcb, 0xda, + 0x0e, 0xac, 0x3f, 0xd2, 0x00, 0xc9, 0x7e, 0x3d, 0x74, 0xd6, 0x6e, 0x9c, 0xb9, 0x01, 0x24, 0x17, + 0x74, 0x07, 0x87, 0x34, 0x2f, 0x06, 0x42, 0xf4, 0x6c, 0xe4, 0xf3, 0x76, 0xf3, 0x7a, 0x87, 0x43, + 0x11, 0xa5, 0x7c, 0xd0, 0xab, 0x39, 0xc5, 0xde, 0x5c, 0x84, 0x1c, 0x3b, 0x67, 0xa4, 0xb7, 0x05, + 0x3b, 0xce, 0xdf, 0x74, 0xa0, 0xdf, 0x0b, 0xfa, 0xb9, 0xdd, 0x07, 0x0a, 0xb6, 0xa8, 0x0a, 0x33, + 0xc9, 0xb3, 0x51, 0x4a, 0x12, 0xc3, 0xa1, 0x97, 0x0e, 0xf2, 0x20, 0x54, 0x10, 0xa7, 0xfc, 0xd0, + 0xa3, 0x8b, 0x2b, 0xa0, 0xb5, 0x0e, 0xc0, 0x78, 0x1b, 0xb8, 0xa4, 0x03, 0x24, 0x63, 0x86, 0x32, + 0x88, 0xe6, 0xf0, 0x93, 0xbc, 0x00, 0x28, 0x36, 0x9f, 0xec, 0x11, 0xa7, 0x73, 0x3f, 0xf2, 0x43, + 0x1c, 0x51, 0x39, 0xd6, 0x95, 0x78, 0x90, 0x7a, 0x82, 0x45, 0xc6, 0x04, 0x25, 0x6d, 0x9d, 0x3c, + 0xc1, 0xb7, 0x07, 0x55, 0xf1, 0x03, 0xa0, 0x45, 0x9f, 0x92, 0x0e, 0xb1, 0x8c, 0x9b, 0x70, 0x2f, + 0xf4, 0x46, 0x91, 0xe7, 0x2e, 0x32, 0x26, 0x48, 0x28, 0x0b, 0x8d, 0x4b, 0xd8, 0x46, 0x76, 0x30, + 0xfb, 0x4f, 0x65, 0x63, 0x25, 0x2e, 0x58, 0x2e, 0x60, 0x7e, 0xf5, 0x7c, 0x30, 0xb0, 0x50, 0x46, + 0xf6, 0xbd, 0x26, 0x7d, 0xe1, 0xe9, 0x87, 0x02, 0x89, 0xd2, 0xc9, 0xd4, 0xd8, 0x3c, 0xd2, 0xb5, + 0xf1, 0xf7, 0x8d, 0xf0, 0x1f, 0x05, 0x75, 0x05, 0x98, 0x59, 0xc6, 0x83, 0x40, 0x4e, 0xb6, 0x0e, + 0xae, 0xed, 0x83, 0xd0, 0x96, 0x72, 0x40, 0xf5, 0x27, 0xb0, 0xb9, 0x6c, 0x04, 0xc8, 0x90, 0x02, + 0xb4, 0xab, 0x00, 0xfd, 0x9a, 0x7b, 0x66, 0xa4, 0x20, 0x8e, 0x45, 0x17, 0x93, 0x88, 0xaf, 0x8e, + 0x87, 0xdd, 0x6d, 0x87, 0xdb, 0xeb, 0xc6, 0xda, 0x4b, 0x6b, 0x11, 0x79, 0x98, 0x87, 0xc4, 0x0c, + 0xf2, 0xe7, 0x60, 0x90, 0xa9, 0x9d, 0xfd, 0x41, 0x5a, 0xeb, 0x08, 0x90, 0x9b, 0x62, 0x07, 0xf4, + 0x68, 0x07, 0x21, 0x66, 0x0f, 0x9a, 0xf5, 0x35, 0x5b, 0x08, 0xcc, 0xed, 0x8b, 0x3a, 0x1b, 0xe5, + 0x6b, 0xcf, 0xdb, 0xc3, 0xeb, 0x17, 0x2a, 0xb8, 0xd9, 0xc1, 0xa0, 0xbf, 0x1b, 0xd9, 0xeb, 0x30, + 0x95, 0x17, 0x14, 0x6a, 0xaf, 0x64, 0x07, 0xb4, 0x9d, 0xba, 0x67, 0x46, 0x52, 0xb2, 0x2f, 0x4a, + 0xc9, 0xc3, 0x0c, 0xd5, 0xd0, 0x42, 0x58, 0x90, 0x43, 0x3a, 0x44, 0xe9, 0xdc, 0xe5, 0xc1, 0xa0, + 0x94, 0xc3, 0x80, 0xac, 0x0a, 0x78, 0x53, 0x39, 0xd2, 0x33, 0x8a, 0xa0, 0xa7, 0xbb, 0x88, 0x3d, + 0x0f, 0x42, 0x44, 0xae, 0x40, 0x41, 0x5e, 0xa1, 0x57, 0x6f, 0xa7, 0x40, 0x4e, 0xf4, 0x2c, 0xd8, + 0x41, 0xdc, 0xa1, 0x67, 0xd3, 0x27, 0x94, 0x93, 0x6e, 0x81, 0x82, 0x08, 0x0d, 0x06, 0x49, 0x8a, + 0x71, 0x37, 0x63, 0x7a, 0x8f, 0xfc, 0xc7, 0xa2, 0x34, 0xfe, 0xf3, 0x49, 0xe9, 0xc4, 0x32, 0x91, + 0x94, 0x9b, 0x45, 0xaf, 0x16, 0x15, 0x74, 0x57, 0xc8, 0x70, 0x28, 0x58, 0x42, 0x92, 0x2a, 0x9c, + 0x7e, 0x88, 0xfe, 0xb3, 0x18, 0x18, 0xba, 0xff, 0x7f, 0xd1, 0x69, 0x21, 0x60, 0xa3, 0x7d, 0xdf, + 0xe5, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; const BITMAP_OPAQUE save_library_xpm[1] = {{ png, sizeof( png ), "save_library_xpm" }}; diff --git a/bitmaps_png/cpp_26/save_part.cpp b/bitmaps_png/cpp_26/save_part.cpp new file mode 100644 index 0000000000..e7aecc035d --- /dev/null +++ b/bitmaps_png/cpp_26/save_part.cpp @@ -0,0 +1,70 @@ + +/* Do not modify this file, it was automatically generated by the + * PNG2cpp CMake script, using a *.png file as input. + */ + +#include + +static const unsigned char png[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x08, 0x06, 0x00, 0x00, 0x00, 0xa9, 0x4a, 0x4c, + 0xce, 0x00, 0x00, 0x03, 0x4e, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xb5, 0x96, 0x6b, 0x48, 0x93, + 0x51, 0x18, 0xc7, 0xcf, 0xd2, 0xe1, 0x4a, 0xbf, 0x74, 0x31, 0x83, 0xae, 0x14, 0x2d, 0x32, 0x32, + 0x2c, 0xad, 0xe9, 0xc8, 0x6e, 0xc3, 0x22, 0xd3, 0x48, 0x08, 0x02, 0xcb, 0x24, 0x2a, 0x50, 0x91, + 0x2c, 0x2b, 0xb3, 0x8b, 0x6d, 0xd3, 0x75, 0x97, 0xb2, 0x68, 0x65, 0x69, 0x7d, 0xe8, 0x4b, 0xa8, + 0x15, 0xdd, 0xe8, 0x62, 0x41, 0x31, 0x27, 0x49, 0xde, 0x62, 0x96, 0xce, 0x6d, 0x6e, 0x5e, 0x66, + 0xf3, 0x12, 0xb8, 0x22, 0x53, 0x71, 0xfb, 0x77, 0xce, 0xcb, 0x06, 0x59, 0x5b, 0xe5, 0x9c, 0x0f, + 0x3c, 0x3c, 0xef, 0xfb, 0x70, 0xde, 0xe7, 0x77, 0xfe, 0xe7, 0xf2, 0x9e, 0x43, 0xc8, 0x6f, 0x26, + 0x25, 0x24, 0x98, 0x06, 0xde, 0xaf, 0xb9, 0x05, 0x87, 0x6a, 0x4c, 0xa1, 0x27, 0x34, 0x16, 0x57, + 0x1e, 0x7c, 0xa4, 0xb6, 0x87, 0xbf, 0x5d, 0xb5, 0x84, 0x8c, 0xc4, 0x28, 0x64, 0x39, 0x75, 0xc8, + 0x78, 0xbc, 0x97, 0xb9, 0x84, 0xcc, 0x74, 0xe6, 0x45, 0xb2, 0x7a, 0xe3, 0xf8, 0x64, 0x0d, 0x5c, + 0xf9, 0x52, 0x69, 0x83, 0x8d, 0xbf, 0xa3, 0x3c, 0x6c, 0xa4, 0xa0, 0xd5, 0x0c, 0x24, 0xe5, 0xf1, + 0x20, 0xf3, 0xf1, 0xf9, 0x46, 0x9f, 0x93, 0xc6, 0x14, 0x54, 0x5d, 0x54, 0x84, 0x5b, 0x51, 0x51, + 0x76, 0x87, 0xba, 0xe7, 0x22, 0xe9, 0x87, 0xd6, 0x31, 0x01, 0xe9, 0xca, 0xca, 0x30, 0x30, 0x30, + 0x80, 0x4a, 0xa5, 0x12, 0x39, 0x02, 0x81, 0x6d, 0x4d, 0x46, 0x99, 0x8d, 0x15, 0x9d, 0x90, 0xa2, + 0x41, 0x40, 0x6a, 0x3d, 0xe7, 0xfe, 0x29, 0xf5, 0xa3, 0x07, 0x55, 0x3e, 0x79, 0x85, 0x17, 0x75, + 0xdd, 0x78, 0x5a, 0xdd, 0x8d, 0x3b, 0x8f, 0x35, 0x90, 0x64, 0xa9, 0xec, 0x93, 0xf6, 0x7d, 0x42, + 0xe0, 0xfe, 0x06, 0x04, 0x65, 0x34, 0x62, 0x1a, 0xf5, 0xa9, 0x07, 0x1a, 0x31, 0x25, 0xbd, 0x01, + 0xe1, 0x72, 0xad, 0xcd, 0x6f, 0x67, 0xf9, 0x41, 0xbf, 0x9d, 0xea, 0x18, 0x41, 0xa2, 0x4a, 0xe2, + 0x97, 0xa8, 0x12, 0xfe, 0x37, 0xa8, 0xfc, 0xd1, 0x6b, 0xac, 0x3a, 0x55, 0x8f, 0x08, 0x85, 0x16, + 0xcb, 0xe4, 0x8d, 0x10, 0x9f, 0x31, 0x60, 0xc6, 0xe1, 0x26, 0xcc, 0xc9, 0xd2, 0x61, 0xde, 0x51, + 0x3d, 0xe6, 0x1d, 0xd3, 0x63, 0x2e, 0x8d, 0xb3, 0x32, 0x75, 0x88, 0x3c, 0xd3, 0x8c, 0xf0, 0x9c, + 0x26, 0x88, 0x58, 0xdb, 0x6c, 0xcd, 0xd7, 0xf1, 0x49, 0x15, 0x5b, 0x47, 0x34, 0x74, 0x6f, 0x3e, + 0x7e, 0xc1, 0xe6, 0x7c, 0x1d, 0x05, 0x68, 0x31, 0xfb, 0x88, 0x0e, 0xc2, 0xe3, 0x06, 0x2c, 0x92, + 0x1a, 0x11, 0x22, 0x37, 0x61, 0x49, 0x8e, 0x09, 0x8b, 0x65, 0x26, 0x2c, 0xcc, 0x6e, 0xe6, 0xc0, + 0xb3, 0x32, 0x9b, 0xb0, 0xf6, 0xbc, 0xfe, 0x47, 0xc0, 0x9e, 0x8a, 0x6c, 0xb7, 0xc5, 0x65, 0x84, + 0xa4, 0xd1, 0xe2, 0x65, 0xcc, 0xe9, 0x73, 0x15, 0x03, 0x69, 0x4a, 0x4a, 0x30, 0x38, 0x38, 0x88, + 0x0b, 0xf7, 0xb5, 0x88, 0xbd, 0xa4, 0xc7, 0x82, 0x6c, 0x03, 0x07, 0x08, 0x3f, 0xdd, 0x86, 0xc8, + 0x73, 0xed, 0x10, 0x9f, 0x6f, 0x87, 0xe8, 0x6c, 0x1b, 0x96, 0x2a, 0x5a, 0x38, 0xf8, 0xc6, 0x7c, + 0x93, 0x2d, 0x28, 0xf5, 0x7d, 0xf1, 0x5f, 0x55, 0xb8, 0x03, 0xf5, 0x59, 0xad, 0xc8, 0x15, 0x08, + 0x20, 0x89, 0x3e, 0x89, 0x98, 0x7c, 0x23, 0x85, 0xb4, 0x62, 0xe5, 0x05, 0x33, 0x24, 0xf9, 0x16, + 0x44, 0x5f, 0xee, 0xc4, 0xda, 0x8b, 0x9f, 0x11, 0x41, 0xa1, 0x71, 0x4a, 0x33, 0xc2, 0x76, 0xdd, + 0xeb, 0xde, 0x3d, 0x75, 0x45, 0x90, 0x47, 0xab, 0x8e, 0x29, 0xea, 0x35, 0x9b, 0x61, 0x69, 0xd4, + 0x22, 0xe1, 0xb2, 0x86, 0x16, 0xec, 0xc0, 0x1a, 0x5a, 0x3c, 0x46, 0xd9, 0x85, 0x2d, 0x05, 0x3d, + 0x58, 0x7f, 0xa5, 0x13, 0xf1, 0xd7, 0x2c, 0xd8, 0x24, 0xab, 0x44, 0xa6, 0xff, 0x64, 0xbb, 0xdc, + 0xc7, 0xa7, 0x9d, 0x7e, 0x2b, 0xf1, 0x08, 0xe4, 0xf4, 0x1e, 0xeb, 0x0f, 0x24, 0xde, 0x30, 0x20, + 0xf6, 0x2a, 0x53, 0x63, 0xc1, 0x06, 0x0a, 0x89, 0xa5, 0x90, 0x84, 0xeb, 0xcd, 0xa8, 0x32, 0xf4, + 0xc2, 0xa4, 0x56, 0xe3, 0x8a, 0x50, 0x38, 0x44, 0xbf, 0x65, 0x7b, 0xaf, 0x80, 0x7a, 0x80, 0x47, + 0x20, 0x36, 0x8c, 0xb5, 0xcd, 0x56, 0x24, 0x15, 0x1a, 0xa9, 0xaa, 0x0e, 0xce, 0x13, 0x0b, 0x5b, + 0x71, 0xb7, 0xc2, 0x32, 0xac, 0xcd, 0xb3, 0xf4, 0x74, 0xb6, 0xc1, 0xed, 0xf4, 0xcf, 0xd2, 0x47, + 0xeb, 0xbc, 0xfd, 0x65, 0x4a, 0xd2, 0xfe, 0x09, 0xb2, 0x5a, 0x2c, 0xdc, 0x5c, 0xb1, 0x58, 0xfa, + 0xae, 0x13, 0x3b, 0x6e, 0xb6, 0x60, 0x5b, 0x41, 0x1b, 0x72, 0x1f, 0xb6, 0xfe, 0xd1, 0x19, 0x8f, + 0x41, 0x6c, 0x8e, 0x8c, 0x2a, 0x15, 0x58, 0x8e, 0x45, 0xf6, 0x2e, 0x7f, 0xd0, 0x82, 0xe4, 0xdb, + 0xfa, 0x61, 0x10, 0x6e, 0xe8, 0xe6, 0xcf, 0xf7, 0x6c, 0xe8, 0x9c, 0xab, 0x8e, 0xfb, 0xc9, 0x3a, + 0x9c, 0xbd, 0xb3, 0xbc, 0x13, 0xd0, 0xff, 0xfd, 0x3b, 0xde, 0x2a, 0x14, 0x90, 0xfb, 0xfa, 0x72, + 0x8b, 0x81, 0xf6, 0x7c, 0x9d, 0x47, 0xfb, 0xc8, 0x95, 0x22, 0x27, 0xc4, 0x5c, 0x53, 0x03, 0x65, + 0x48, 0xc8, 0x90, 0xa3, 0x13, 0xc5, 0xa7, 0x09, 0x99, 0xe8, 0xd1, 0x3e, 0x72, 0x35, 0x47, 0x9c, + 0x8a, 0xbe, 0x3e, 0xa7, 0x0a, 0x1b, 0x55, 0xd1, 0x45, 0xdb, 0xc7, 0x91, 0x91, 0xda, 0xdf, 0x56, + 0x1d, 0x8b, 0x1d, 0x75, 0x75, 0xb8, 0x1e, 0x1a, 0x6a, 0x73, 0x9c, 0x59, 0x25, 0xa7, 0x08, 0x99, + 0x4c, 0x3c, 0x31, 0x77, 0xa0, 0x81, 0xfe, 0x7e, 0xa8, 0xf3, 0xf2, 0x20, 0xe7, 0xf3, 0x99, 0x8a, + 0x1e, 0xda, 0x26, 0x9e, 0x8c, 0xc6, 0x5c, 0x81, 0xba, 0xb4, 0x5a, 0x14, 0x89, 0xc5, 0x36, 0xc7, + 0x21, 0x58, 0x4a, 0x55, 0x04, 0x92, 0xd1, 0x9a, 0xbb, 0x83, 0x4f, 0x36, 0x6e, 0xdc, 0x57, 0x9a, + 0xdf, 0x4b, 0xbc, 0x65, 0x4e, 0x50, 0x55, 0x61, 0xe1, 0xb0, 0xa3, 0x9c, 0x5e, 0x54, 0xa6, 0x13, + 0x6f, 0x9a, 0xbb, 0xcb, 0x89, 0xd7, 0xcd, 0xdd, 0x75, 0x6b, 0xac, 0x60, 0x7f, 0x5c, 0x20, 0xbd, + 0x61, 0x3f, 0x01, 0x9b, 0x99, 0x59, 0x96, 0x90, 0x4a, 0xbf, 0x59, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, +}; + +const BITMAP_OPAQUE save_part_xpm[1] = {{ png, sizeof( png ), "save_part_xpm" }}; + +//EOF diff --git a/bitmaps_png/cpp_26/search_tree.cpp b/bitmaps_png/cpp_26/search_tree.cpp new file mode 100644 index 0000000000..67ef1f8971 --- /dev/null +++ b/bitmaps_png/cpp_26/search_tree.cpp @@ -0,0 +1,36 @@ + +/* Do not modify this file, it was automatically generated by the + * PNG2cpp CMake script, using a *.png file as input. + */ + +#include + +static const unsigned char png[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x08, 0x04, 0x00, 0x00, 0x00, 0x03, 0x43, 0x84, + 0x45, 0x00, 0x00, 0x01, 0x32, 0x49, 0x44, 0x41, 0x54, 0x38, 0xcb, 0xed, 0x93, 0xbd, 0x4b, 0x42, + 0x61, 0x14, 0x87, 0x5f, 0xa2, 0x2e, 0xa5, 0x81, 0x15, 0x04, 0x0e, 0x19, 0xb7, 0xa1, 0x31, 0x5a, + 0x82, 0x40, 0x08, 0xca, 0xd1, 0x21, 0xb0, 0xa1, 0x2d, 0x72, 0x89, 0xa6, 0x94, 0x20, 0x5c, 0x4a, + 0x22, 0xa8, 0xa8, 0xa9, 0x8f, 0x5b, 0x38, 0x36, 0xc4, 0x45, 0x91, 0xe0, 0xd2, 0x90, 0xf4, 0x21, + 0x85, 0x20, 0x77, 0xc8, 0x20, 0x3a, 0xff, 0x4a, 0x10, 0xb8, 0xf8, 0xb4, 0xbc, 0x5c, 0x2e, 0xdc, + 0x04, 0x5d, 0x9a, 0xfc, 0x3d, 0xd3, 0x81, 0xf3, 0xbc, 0xe7, 0x70, 0xe0, 0x55, 0xaa, 0x97, 0x7f, + 0xcf, 0x8e, 0xf1, 0xd3, 0x1d, 0xfd, 0xa7, 0x4a, 0xe5, 0xd7, 0x5b, 0x75, 0xfc, 0x3c, 0x72, 0x4d, + 0xbd, 0x2d, 0x19, 0x42, 0x05, 0xa5, 0xf2, 0x1b, 0x2d, 0xc1, 0x8f, 0xcd, 0xb8, 0xaf, 0xba, 0x21, + 0xc9, 0x2c, 0x29, 0xaa, 0xba, 0xce, 0x75, 0x22, 0x5d, 0x70, 0x4c, 0x89, 0x55, 0xe2, 0x41, 0xe9, + 0x9e, 0x2c, 0x6b, 0x1c, 0xf1, 0x89, 0x60, 0x13, 0xa5, 0x44, 0x9a, 0x1c, 0xef, 0x9e, 0xfa, 0xc0, + 0x48, 0x50, 0xda, 0x24, 0xc3, 0x21, 0x53, 0x6c, 0x23, 0xd8, 0x84, 0x59, 0xe0, 0x80, 0x84, 0xf7, + 0xba, 0xb0, 0xcb, 0x7c, 0xbb, 0xf5, 0xf6, 0x58, 0x44, 0xb0, 0xe9, 0xa3, 0x86, 0xd0, 0x20, 0x84, + 0x83, 0x20, 0x9c, 0x10, 0xa3, 0x12, 0x94, 0x6e, 0x49, 0x31, 0x47, 0x8c, 0x38, 0x82, 0xed, 0xad, + 0x32, 0xcd, 0x39, 0xc2, 0x1b, 0x51, 0x9e, 0xbc, 0x99, 0x9e, 0x54, 0x21, 0x8c, 0x45, 0x83, 0x7d, + 0x2d, 0x0d, 0xeb, 0x06, 0x93, 0x02, 0x82, 0x43, 0xd6, 0x77, 0x18, 0x4f, 0xb2, 0x98, 0x44, 0x10, + 0x56, 0xb4, 0xa4, 0xb8, 0x43, 0x78, 0xc6, 0xe0, 0x05, 0xc1, 0xa5, 0xfc, 0x97, 0x54, 0x23, 0x42, + 0x92, 0x04, 0x4b, 0x5a, 0x32, 0x99, 0x61, 0x99, 0x09, 0xd2, 0x08, 0xc2, 0x16, 0x06, 0x5f, 0x41, + 0x49, 0x78, 0xe5, 0x8c, 0x22, 0x1f, 0x94, 0x11, 0x5c, 0x1c, 0x5c, 0x2e, 0x29, 0xea, 0xb6, 0x2a, + 0x56, 0x70, 0xd2, 0x60, 0x73, 0xf4, 0xbb, 0x73, 0x86, 0x9a, 0x03, 0x57, 0x4a, 0x45, 0x94, 0xd9, + 0x25, 0x63, 0xbd, 0x5f, 0xae, 0xf3, 0x0b, 0x33, 0xe6, 0xeb, 0xc7, 0x2a, 0x08, 0xcb, 0x0a, 0x00, + 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, +}; + +const BITMAP_OPAQUE search_tree_xpm[1] = {{ png, sizeof( png ), "search_tree_xpm" }}; + +//EOF diff --git a/bitmaps_png/sources/add_library.svg b/bitmaps_png/sources/add_library.svg new file mode 100644 index 0000000000..726b10cbe5 --- /dev/null +++ b/bitmaps_png/sources/add_library.svg @@ -0,0 +1,204 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bitmaps_png/sources/export_part.svg b/bitmaps_png/sources/export_part.svg new file mode 100644 index 0000000000..12195435f7 --- /dev/null +++ b/bitmaps_png/sources/export_part.svg @@ -0,0 +1,184 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bitmaps_png/sources/import_part.svg b/bitmaps_png/sources/import_part.svg new file mode 100644 index 0000000000..a88f04e7a7 --- /dev/null +++ b/bitmaps_png/sources/import_part.svg @@ -0,0 +1,176 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bitmaps_png/sources/new_library.svg b/bitmaps_png/sources/new_library.svg index fb6387c298..b5747eced9 100644 --- a/bitmaps_png/sources/new_library.svg +++ b/bitmaps_png/sources/new_library.svg @@ -13,7 +13,7 @@ width="26" height="26" id="svg2" - inkscape:version="0.91 r13725" + inkscape:version="0.92.2 5c3e80d, 2017-08-06" sodipodi:docname="new_library.svg"> @@ -36,15 +36,15 @@ guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" - inkscape:window-width="1366" - inkscape:window-height="717" + inkscape:window-width="1916" + inkscape:window-height="1176" id="namedview164" showgrid="true" inkscape:zoom="9.8333331" inkscape:cx="1.915385" inkscape:cy="10.576725" - inkscape:window-x="0" - inkscape:window-y="1080" + inkscape:window-x="1920" + inkscape:window-y="20" inkscape:window-maximized="1" inkscape:current-layer="svg2"> + + + - - - - - - - - - - - - + diff --git a/bitmaps_png/sources/save_library.svg b/bitmaps_png/sources/save_library.svg index 1cff983c23..fb6387c298 100644 --- a/bitmaps_png/sources/save_library.svg +++ b/bitmaps_png/sources/save_library.svg @@ -1,21 +1,22 @@ + + + inkscape:version="0.91 r13725" + sodipodi:docname="new_library.svg"> + id="metadata166"> @@ -35,367 +36,53 @@ guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" - inkscape:window-width="1920" - inkscape:window-height="1053" - id="namedview148" + inkscape:window-width="1366" + inkscape:window-height="717" + id="namedview164" showgrid="true" - inkscape:zoom="21.730769" - inkscape:cx="1.3115044" - inkscape:cy="12.907965" + inkscape:zoom="9.8333331" + inkscape:cx="1.915385" + inkscape:cy="10.576725" inkscape:window-x="0" - inkscape:window-y="0" + inkscape:window-y="1080" inkscape:window-maximized="1" - inkscape:current-layer="svg2" - inkscape:showpageshadow="false"> + inkscape:current-layer="svg2"> + id="grid4171" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + style="color-interpolation-filters:sRGB" + id="filter3945-3"> + id="feGaussianBlur12-6" /> + style="color-interpolation-filters:sRGB" + id="filter3941-7"> + id="feGaussianBlur9-5" /> + + + + + + + id="stop15-6" /> + id="stop17-2" /> - - - - + style="opacity:1;fill:#ffd42a;fill-opacity:1;fill-rule:nonzero;stroke:#d4aa00;stroke-width:1.03579581;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect4298" + width="6.0397334" + height="24.979227" + x="19.479198" + y="0.54951072" /> + + + + + + + + + transform="matrix(-1.1611535,0,0,-1.2412687,33.33417,18.289374)" + id="g33-2" + style="fill:#ffffff;stroke:#ffffff"> + id="path35-9" /> + id="path37-1" /> + + + + + + + id="path39-7" /> + id="path41-0" /> - - - - diff --git a/bitmaps_png/sources/save_part.svg b/bitmaps_png/sources/save_part.svg new file mode 100644 index 0000000000..7bd5a2e817 --- /dev/null +++ b/bitmaps_png/sources/save_part.svg @@ -0,0 +1,170 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bitmaps_png/sources/search_tree.svg b/bitmaps_png/sources/search_tree.svg new file mode 100644 index 0000000000..2f9a9f00ba --- /dev/null +++ b/bitmaps_png/sources/search_tree.svg @@ -0,0 +1,48 @@ + + + + + + + image/svg+xml + + + + + + + + ab? + + diff --git a/common/confirm.cpp b/common/confirm.cpp index 9c3ab3dfed..e5e0838906 100644 --- a/common/confirm.cpp +++ b/common/confirm.cpp @@ -34,6 +34,8 @@ #include #include +#include + class DIALOG_EXIT: public DIALOG_EXIT_BASE { @@ -175,3 +177,168 @@ int YesNoCancelDialog( wxWindow* aParent, return dlg.ShowModal(); } + + +int SelectSingleOption( wxWindow* aParent, const wxString& aTitle, const wxString& aMessage, const wxArrayString& aOptions ) +{ + int ret = -1; + wxDialog* dlg = new wxDialog( aParent, wxID_ANY, aTitle ); + + wxBoxSizer* boxSizer = new wxBoxSizer( wxVERTICAL ); + + if( !aMessage.IsEmpty() ) + boxSizer->Add( new wxStaticText( dlg, wxID_ANY, aMessage ), 0, wxEXPAND | wxALL, 5 ); + + std::vector radioButtons; + radioButtons.reserve( aOptions.Count() ); + + for( const wxString& option : aOptions ) + { + radioButtons.emplace_back( new wxRadioButton( dlg, wxID_ANY, _( option ) ) ); + boxSizer->Add( radioButtons.back(), 0, wxEXPAND | wxALL, 5 ); + } + + wxStdDialogButtonSizer* m_sdboxSizer = new wxStdDialogButtonSizer(); + m_sdboxSizer->AddButton( new wxButton( dlg, wxID_OK ) ); + m_sdboxSizer->AddButton( new wxButton( dlg, wxID_CANCEL ) ); + m_sdboxSizer->Realize(); + boxSizer->Add( m_sdboxSizer, 1, wxEXPAND | wxALL, 5 ); + + dlg->SetSizer( boxSizer ); + dlg->Layout(); + boxSizer->Fit( dlg ); + boxSizer->SetSizeHints( dlg ); + dlg->Centre( wxBOTH ); + + if( dlg->ShowModal() == wxID_OK ) + { + for( unsigned int i = 0; i < radioButtons.size(); ++i ) + { + if( radioButtons[i]->GetValue() ) + { + ret = i; + break; + } + } + } + else + { + ret = -1; + } + + dlg->Destroy(); + + return ret; +} + + +class DIALOG_MULTI_OPTIONS : public wxDialog +{ +public: + DIALOG_MULTI_OPTIONS( wxWindow* aParent, const wxString& aTitle, const wxString& aMessage, + const wxArrayString& aOptions ) + : wxDialog( aParent, wxID_ANY, aTitle ) + { + SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* boxSizer = new wxBoxSizer( wxVERTICAL ); + + if( !aMessage.IsEmpty() ) + boxSizer->Add( new wxStaticText( this, wxID_ANY, aMessage ), 0, wxEXPAND | wxALL, 5 ); + + m_checklist = new wxCheckListBox( this, wxID_ANY ); + + for( const wxString& option : aOptions ) + m_checklist->Append( option ); + + boxSizer->Add( m_checklist, 1, wxEXPAND | wxALL, 5 ); + + wxBoxSizer* btnSizer = new wxBoxSizer( wxHORIZONTAL ); + wxButton* selectAll = new wxButton( this, wxID_ANY, _( "Select All" ) ); + btnSizer->Add( selectAll, 1, wxEXPAND | wxALL, 5 ); + wxButton* unselectAll = new wxButton( this, wxID_ANY, _( "Unselect All" ) ); + btnSizer->Add( unselectAll, 1, wxEXPAND | wxALL, 5 ); + boxSizer->Add( btnSizer, 0, wxEXPAND | wxALL, 5 ); + + wxStdDialogButtonSizer* m_sdboxSizer = new wxStdDialogButtonSizer(); + m_sdboxSizer->AddButton( new wxButton( this, wxID_OK ) ); + m_sdboxSizer->AddButton( new wxButton( this, wxID_CANCEL ) ); + m_sdboxSizer->Realize(); + boxSizer->Add( m_sdboxSizer, 0, wxEXPAND | wxALL, 5 ); + + SetSizer( boxSizer ); + Layout(); + boxSizer->Fit( this ); + boxSizer->SetSizeHints( this ); + Centre( wxBOTH ); + + selectAll->Bind( wxEVT_COMMAND_BUTTON_CLICKED, &DIALOG_MULTI_OPTIONS::selectAll, this ); + unselectAll->Bind( wxEVT_COMMAND_BUTTON_CLICKED, &DIALOG_MULTI_OPTIONS::unselectAll, this ); + } + + std::vector GetSelection() const + { + std::vector ret; + + for( unsigned int i = 0; i < m_checklist->GetCount(); ++i ) + { + if( m_checklist->IsChecked( i ) ) + ret.push_back( i ); + } + + return ret; + } + + void SetCheckboxes( bool aValue ) + { + for( unsigned int i = 0; i < m_checklist->GetCount(); ++i ) + m_checklist->Check( i, aValue ); + } + +protected: + wxCheckListBox* m_checklist; + + void selectAll( wxCommandEvent& aEvent ) + { + SetCheckboxes( true ); + } + + void unselectAll( wxCommandEvent& aEvent ) + { + SetCheckboxes( false ); + } +}; + + +std::pair> SelectMultipleOptions( wxWindow* aParent, const wxString& aTitle, + const wxString& aMessage, const wxArrayString& aOptions, bool aDefaultState ) +{ + std::vector ret; + bool clickedOk; + DIALOG_MULTI_OPTIONS dlg( aParent, aTitle, aMessage, aOptions ); + dlg.SetCheckboxes( aDefaultState ); + + if( dlg.ShowModal() == wxID_OK ) + { + ret = dlg.GetSelection(); + clickedOk = true; + } + else + { + clickedOk = false; + } + + return std::make_pair( clickedOk, ret ); +} + + +std::pair> SelectMultipleOptions( wxWindow* aParent, const wxString& aTitle, + const wxString& aMessage, const std::vector& aOptions, bool aDefaultState ) +{ + wxArrayString array; + + for( const auto& option : aOptions ) + array.Add( option ); + + return SelectMultipleOptions( aParent, aTitle, aMessage, array, aDefaultState ); +} diff --git a/common/dialog_shim.cpp b/common/dialog_shim.cpp index 22d5515e52..5de406a70c 100644 --- a/common/dialog_shim.cpp +++ b/common/dialog_shim.cpp @@ -155,7 +155,9 @@ bool DIALOG_SHIM::Show( bool show ) // If showing, use previous position and size. if( show ) { +#ifndef __WINDOWS__ wxDialog::Raise(); // Needed on OS X and some other window managers (i.e. Unity) +#endif ret = wxDialog::Show( show ); // classname is key, returns a zeroed out default EDA_RECT if none existed before. diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index 1a52e7b0d3..a2e5924d3e 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -83,6 +83,7 @@ set( EESCHEMA_DLGS ) set( EESCHEMA_WIDGETS + widgets/cmp_tree_pane.cpp widgets/component_tree.cpp widgets/widget_eeschema_color_config.cpp widgets/pin_shape_combobox.cpp @@ -124,6 +125,7 @@ set( EESCHEMA_SRCS getpart.cpp cmp_tree_model.cpp cmp_tree_model_adapter.cpp + cmp_tree_model_adapter_base.cpp generate_alias_info.cpp hierarch.cpp highlight_connection.cpp @@ -142,6 +144,8 @@ set( EESCHEMA_SRCS lib_draw_item.cpp lib_export.cpp lib_field.cpp + lib_manager.cpp + lib_manager_adapter.cpp lib_pin.cpp lib_polyline.cpp lib_rectangle.cpp diff --git a/eeschema/block.cpp b/eeschema/block.cpp index 272d92a756..b6d0d7824c 100644 --- a/eeschema/block.cpp +++ b/eeschema/block.cpp @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include @@ -47,21 +47,11 @@ #include #include #include - -// Imported functions: -extern void SetSchItemParent( SCH_ITEM* Struct, SCH_SCREEN* Screen ); -extern void MoveItemsInList( PICKED_ITEMS_LIST& aItemsList, const wxPoint aMoveVector ); -extern void RotateListOfItems( PICKED_ITEMS_LIST& aItemsList, wxPoint& Center ); -extern void MirrorX( PICKED_ITEMS_LIST& aItemsList, wxPoint& aMirrorPoint ); -extern void MirrorY( PICKED_ITEMS_LIST& aItemsList, wxPoint& Center ); -extern void DuplicateItemsInList( SCH_SCREEN* screen, - PICKED_ITEMS_LIST& aItemsList, - const wxPoint aMoveVector ); +#include static void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase ); - int SCH_EDIT_FRAME::BlockCommand( EDA_KEY key ) { int cmd = BLOCK_IDLE; diff --git a/eeschema/block_libedit.cpp b/eeschema/block_libedit.cpp index 8445e2750f..2e8a7d2bd2 100644 --- a/eeschema/block_libedit.cpp +++ b/eeschema/block_libedit.cpp @@ -91,26 +91,27 @@ int LIB_EDIT_FRAME::BlockCommand( EDA_KEY key ) } -bool LIB_EDIT_FRAME::HandleBlockEnd( wxDC* DC ) +bool LIB_EDIT_FRAME::HandleBlockEnd( wxDC* aDC ) { int ItemCount = 0; bool nextCmd = false; + BLOCK_SELECTOR* block = &GetScreen()->m_BlockLocate; wxPoint pt; - if( GetScreen()->m_BlockLocate.GetCount() ) + if( block->GetCount() ) { - BLOCK_STATE_T state = GetScreen()->m_BlockLocate.GetState(); - BLOCK_COMMAND_T command = GetScreen()->m_BlockLocate.GetCommand(); - m_canvas->CallEndMouseCapture( DC ); - GetScreen()->m_BlockLocate.SetState( state ); - GetScreen()->m_BlockLocate.SetCommand( command ); + BLOCK_STATE_T state = block->GetState(); + BLOCK_COMMAND_T command = block->GetCommand(); + m_canvas->CallEndMouseCapture( aDC ); + block->SetState( state ); + block->SetCommand( command ); m_canvas->SetMouseCapture( DrawAndSizingBlockOutlines, AbortBlockCurrentCommand ); - SetCrossHairPosition( wxPoint( GetScreen()->m_BlockLocate.GetRight(), - GetScreen()->m_BlockLocate.GetBottom() ) ); + SetCrossHairPosition( wxPoint( block->GetRight(), + block->GetBottom() ) ); m_canvas->MoveCursorToCrossHair(); } - switch( GetScreen()->m_BlockLocate.GetCommand() ) + switch( block->GetCommand() ) { case BLOCK_IDLE: DisplayError( this, wxT( "Error in HandleBlockPLace" ) ); @@ -121,7 +122,7 @@ bool LIB_EDIT_FRAME::HandleBlockEnd( wxDC* DC ) case BLOCK_MOVE: // Move case BLOCK_DUPLICATE: // Duplicate if( GetCurPart() ) - ItemCount = GetCurPart()->SelectItems( GetScreen()->m_BlockLocate, + ItemCount = GetCurPart()->SelectItems( *block, m_unit, m_convert, m_editPinsPerPartOrConvert ); if( ItemCount ) @@ -130,12 +131,12 @@ bool LIB_EDIT_FRAME::HandleBlockEnd( wxDC* DC ) if( m_canvas->IsMouseCaptured() ) { - m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); + m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false ); m_canvas->SetMouseCaptureCallback( DrawMovingBlockOutlines ); - m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); + m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false ); } - GetScreen()->m_BlockLocate.SetState( STATE_BLOCK_MOVE ); + block->SetState( STATE_BLOCK_MOVE ); m_canvas->Refresh( true ); } break; @@ -143,12 +144,37 @@ bool LIB_EDIT_FRAME::HandleBlockEnd( wxDC* DC ) case BLOCK_PRESELECT_MOVE: // Move with preselection list nextCmd = true; m_canvas->SetMouseCaptureCallback( DrawMovingBlockOutlines ); - GetScreen()->m_BlockLocate.SetState( STATE_BLOCK_MOVE ); + block->SetState( STATE_BLOCK_MOVE ); + break; + + case BLOCK_COPY: // Save a copy of items in the clipboard buffer + case BLOCK_CUT: + if( GetCurPart() ) + ItemCount = GetCurPart()->SelectItems( *block, m_unit, m_convert, + m_editPinsPerPartOrConvert ); + + if( ItemCount ) + { + copySelectedItems(); + auto cmd = block->GetCommand(); + + if( cmd == BLOCK_COPY ) + { + GetCurPart()->ClearSelectedItems(); + block->ClearItemsList(); + } + else if( cmd == BLOCK_CUT ) + { + SaveCopyInUndoList( GetCurPart() ); + GetCurPart()->DeleteSelectedItems(); + OnModify(); + } + } break; case BLOCK_DELETE: // Delete if( GetCurPart() ) - ItemCount = GetCurPart()->SelectItems( GetScreen()->m_BlockLocate, + ItemCount = GetCurPart()->SelectItems( *block, m_unit, m_convert, m_editPinsPerPartOrConvert ); if( ItemCount ) @@ -161,8 +187,10 @@ bool LIB_EDIT_FRAME::HandleBlockEnd( wxDC* DC ) } break; - case BLOCK_COPY: // Save case BLOCK_PASTE: + wxFAIL; // should not happen + break; + case BLOCK_FLIP: break; @@ -170,20 +198,20 @@ bool LIB_EDIT_FRAME::HandleBlockEnd( wxDC* DC ) case BLOCK_MIRROR_X: case BLOCK_MIRROR_Y: if( GetCurPart() ) - ItemCount = GetCurPart()->SelectItems( GetScreen()->m_BlockLocate, + ItemCount = GetCurPart()->SelectItems( *block, m_unit, m_convert, m_editPinsPerPartOrConvert ); if( ItemCount ) SaveCopyInUndoList( GetCurPart() ); - pt = GetScreen()->m_BlockLocate.Centre(); + pt = block->Centre(); pt = GetNearestGridPosition( pt ); pt.y = -pt.y; if( GetCurPart() ) { OnModify(); - int block_cmd = GetScreen()->m_BlockLocate.GetCommand(); + int block_cmd = block->GetCommand(); if( block_cmd == BLOCK_MIRROR_Y) GetCurPart()->MirrorSelectedItemsH( pt ); @@ -196,7 +224,7 @@ bool LIB_EDIT_FRAME::HandleBlockEnd( wxDC* DC ) break; case BLOCK_ZOOM: // Window Zoom - Window_Zoom( GetScreen()->m_BlockLocate ); + Window_Zoom( *block ); break; case BLOCK_ABORT: @@ -207,17 +235,16 @@ bool LIB_EDIT_FRAME::HandleBlockEnd( wxDC* DC ) case BLOCK_DUPLICATE_AND_INCREMENT: // not used in Eeschema case BLOCK_MOVE_EXACT: // not used in Eeschema - case BLOCK_CUT: // not used in libedit break; } if( !nextCmd ) { - if( GetScreen()->m_BlockLocate.GetCommand() != BLOCK_SELECT_ITEMS_ONLY && GetCurPart() ) + if( block->GetCommand() != BLOCK_SELECT_ITEMS_ONLY && GetCurPart() ) GetCurPart()->ClearSelectedItems(); - GetScreen()->m_BlockLocate.SetState( STATE_NO_BLOCK ); - GetScreen()->m_BlockLocate.SetCommand( BLOCK_IDLE ); + block->SetState( STATE_NO_BLOCK ); + block->SetCommand( BLOCK_IDLE ); GetScreen()->SetCurItem( NULL ); m_canvas->EndMouseCapture( GetToolId(), m_canvas->GetCurrentCursor(), wxEmptyString, false ); @@ -230,6 +257,7 @@ bool LIB_EDIT_FRAME::HandleBlockEnd( wxDC* DC ) void LIB_EDIT_FRAME::HandleBlockPlace( wxDC* DC ) { + BLOCK_SELECTOR* block = &GetScreen()->m_BlockLocate; wxPoint pt; if( !m_canvas->IsMouseCaptured() ) @@ -237,9 +265,9 @@ void LIB_EDIT_FRAME::HandleBlockPlace( wxDC* DC ) DisplayError( this, wxT( "HandleBlockPLace : m_mouseCaptureCallback = NULL" ) ); } - GetScreen()->m_BlockLocate.SetState( STATE_BLOCK_STOP ); + block->SetState( STATE_BLOCK_STOP ); - switch( GetScreen()->m_BlockLocate.GetCommand() ) + switch( block->GetCommand() ) { case BLOCK_IDLE: break; @@ -248,12 +276,12 @@ void LIB_EDIT_FRAME::HandleBlockPlace( wxDC* DC ) case BLOCK_DRAG_ITEM: case BLOCK_MOVE: // Move case BLOCK_PRESELECT_MOVE: // Move with preselection list - GetScreen()->m_BlockLocate.ClearItemsList(); + block->ClearItemsList(); if( GetCurPart() ) SaveCopyInUndoList( GetCurPart() ); - pt = GetScreen()->m_BlockLocate.GetMoveVector(); + pt = block->GetMoveVector(); pt.y *= -1; if( GetCurPart() ) @@ -263,12 +291,12 @@ void LIB_EDIT_FRAME::HandleBlockPlace( wxDC* DC ) break; case BLOCK_DUPLICATE: // Duplicate - GetScreen()->m_BlockLocate.ClearItemsList(); + block->ClearItemsList(); if( GetCurPart() ) SaveCopyInUndoList( GetCurPart() ); - pt = GetScreen()->m_BlockLocate.GetMoveVector(); + pt = block->GetMoveVector(); pt.y = -pt.y; if( GetCurPart() ) @@ -277,7 +305,15 @@ void LIB_EDIT_FRAME::HandleBlockPlace( wxDC* DC ) break; case BLOCK_PASTE: // Paste (recopy the last block saved) - GetScreen()->m_BlockLocate.ClearItemsList(); + block->ClearItemsList(); + + if( GetCurPart() ) + SaveCopyInUndoList( GetCurPart() ); + + pt = block->GetMoveVector(); + pt.y = -pt.y; + + pasteClipboard( pt ); break; case BLOCK_ROTATE: // Invert by popup menu, from block move @@ -286,13 +322,13 @@ void LIB_EDIT_FRAME::HandleBlockPlace( wxDC* DC ) if( GetCurPart() ) SaveCopyInUndoList( GetCurPart() ); - pt = GetScreen()->m_BlockLocate.Centre(); + pt = block->Centre(); pt = GetNearestGridPosition( pt ); pt.y = -pt.y; if( GetCurPart() ) { - int block_cmd = GetScreen()->m_BlockLocate.GetCommand(); + int block_cmd = block->GetCommand(); if( block_cmd == BLOCK_MIRROR_Y) GetCurPart()->MirrorSelectedItemsH( pt ); @@ -314,14 +350,81 @@ void LIB_EDIT_FRAME::HandleBlockPlace( wxDC* DC ) OnModify(); - GetScreen()->m_BlockLocate.SetState( STATE_NO_BLOCK ); - GetScreen()->m_BlockLocate.SetCommand( BLOCK_IDLE ); + block->SetState( STATE_NO_BLOCK ); + block->SetCommand( BLOCK_IDLE ); GetScreen()->SetCurItem( NULL ); m_canvas->EndMouseCapture( GetToolId(), m_canvas->GetCurrentCursor(), wxEmptyString, false ); m_canvas->Refresh( true ); } +void LIB_EDIT_FRAME::InitBlockPasteInfos() +{ + BLOCK_SELECTOR& block = GetScreen()->m_BlockLocate; + + // Copy the clipboard contents to the screen block selector + // (only the copy, the new instances will be appended to the part once the items are placed) + block.GetItems().CopyList( m_clipboard.GetItems() ); + + // Set the pate reference point + block.SetLastCursorPosition( m_clipboard.GetLastCursorPosition() ); + m_canvas->SetMouseCaptureCallback( DrawMovingBlockOutlines ); +} + + +void LIB_EDIT_FRAME::copySelectedItems() +{ + LIB_PART* part = GetCurPart(); + + if( !part ) + return; + + m_clipboard.ClearListAndDeleteItems(); // delete previous saved list, if exists + m_clipboard.SetLastCursorPosition( GetScreen()->m_BlockLocate.GetEnd() ); // store the reference point + + for( LIB_ITEM& item : part->GetDrawItems() ) + { + // We *do not* copy fields because they are unique for the whole component + // so skip them (do not duplicate) if they are flagged selected. + if( item.Type() == LIB_FIELD_T ) + item.ClearFlags( SELECTED ); + + if( !item.IsSelected() ) + continue; + + // Do not clear the 'selected' flag. It is required to have items drawn when they are pasted. + LIB_ITEM* copy = (LIB_ITEM*) item.Clone(); + + // In list the wrapper is owner of the schematic item, we can use the UR_DELETED + // status for the picker because pickers with this status are owner of the picked item + // (or TODO ?: create a new status like UR_DUPLICATE) + ITEM_PICKER picker( copy, UR_DELETED ); + m_clipboard.PushItem( picker ); + } +} + + +void LIB_EDIT_FRAME::pasteClipboard( const wxPoint& aOffset ) +{ + LIB_PART* part = GetCurPart(); + + if( !part || m_clipboard.GetCount() == 0 ) + return; + + for( unsigned int i = 0; i < m_clipboard.GetCount(); i++ ) + { + // Append a copy to the current part, so the clipboard buffer might be pasted multiple times + LIB_ITEM* item = (LIB_ITEM*) m_clipboard.GetItem( i )->Clone(); + item->SetParent( part ); + item->SetSelected(); + part->AddDrawItem( item ); + } + + GetCurPart()->MoveSelectedItems( aOffset ); + OnModify(); +} + + /* * Traces the outline of the search block structures * The entire block follows the cursor @@ -329,9 +432,8 @@ void LIB_EDIT_FRAME::HandleBlockPlace( wxDC* DC ) void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase ) { - BLOCK_SELECTOR* block; BASE_SCREEN* screen = aPanel->GetScreen(); - block = &screen->m_BlockLocate; + BLOCK_SELECTOR* block = &screen->m_BlockLocate; LIB_EDIT_FRAME* parent = (LIB_EDIT_FRAME*) aPanel->GetParent(); wxASSERT( parent != NULL ); @@ -352,6 +454,12 @@ void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& { block->Draw( aPanel, aDC, block->GetMoveVector(), g_XorMode, block->GetColor() ); component->Draw( aPanel, aDC, block->GetMoveVector(), unit, convert, opts ); + + for( unsigned ii = 0; ii < block->GetCount(); ii++ ) + { + LIB_ITEM* libItem = (LIB_ITEM*) block->GetItem( ii ); + libItem->Draw( aPanel, aDC, block->GetMoveVector(), g_GhostColor, g_XorMode, nullptr, opts.transform ); + } } // Repaint new view @@ -360,5 +468,11 @@ void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& GRSetDrawMode( aDC, g_XorMode ); block->Draw( aPanel, aDC, block->GetMoveVector(), g_XorMode, block->GetColor() ); + for( unsigned ii = 0; ii < block->GetCount(); ii++ ) + { + LIB_ITEM* libItem = (LIB_ITEM*) block->GetItem( ii ); + libItem->Draw( aPanel, aDC, block->GetMoveVector(), g_GhostColor, g_XorMode, nullptr, opts.transform ); + } + component->Draw( aPanel, aDC, block->GetMoveVector(), unit, convert, opts ); } diff --git a/eeschema/class_libentry.cpp b/eeschema/class_libentry.cpp index 72d452ca04..b6f46f8c2d 100644 --- a/eeschema/class_libentry.cpp +++ b/eeschema/class_libentry.cpp @@ -175,13 +175,10 @@ struct null_deleter } }; - LIB_PART::LIB_PART( const wxString& aName, PART_LIB* aLibrary ) : EDA_ITEM( LIB_PART_T ), m_me( this, null_deleter() ) { - m_name = aName; - m_library = aLibrary; m_dateModified = 0; m_unitCount = 1; m_pinNameOffset = 40; @@ -190,21 +187,15 @@ LIB_PART::LIB_PART( const wxString& aName, PART_LIB* aLibrary ) : m_showPinNumbers = true; m_showPinNames = true; - m_libId.SetLibItemName( aName, false ); - - // Create the default alias if the name parameter is not empty. - if( !aName.IsEmpty() ) - m_aliases.push_back( new LIB_ALIAS( aName, this ) ); - // Add the MANDATORY_FIELDS in RAM only. These are assumed to be present // when the field editors are invoked. - LIB_FIELD* value = new LIB_FIELD( this, VALUE ); - value->SetText( aName ); - m_drawings[LIB_FIELD_T].push_back( value ); - + m_drawings[LIB_FIELD_T].push_back( new LIB_FIELD( this, VALUE ) ); m_drawings[LIB_FIELD_T].push_back( new LIB_FIELD( this, REFERENCE ) ); m_drawings[LIB_FIELD_T].push_back( new LIB_FIELD( this, FOOTPRINT ) ); m_drawings[LIB_FIELD_T].push_back( new LIB_FIELD( this, DATASHEET ) ); + + SetLib( aLibrary ); + SetName( aName ); } @@ -215,7 +206,6 @@ LIB_PART::LIB_PART( LIB_PART& aPart, PART_LIB* aLibrary ) : LIB_ITEM* newItem; m_library = aLibrary; - m_name = aPart.m_name; m_FootprintList = aPart.m_FootprintList; m_unitCount = aPart.m_unitCount; m_unitsLocked = aPart.m_unitsLocked; @@ -305,14 +295,21 @@ wxString LIB_PART::SubReference( int aUnit, bool aAddSeparator ) void LIB_PART::SetName( const wxString& aName ) { - m_name = aName; - GetValueField().SetText( aName ); + m_libId.SetLibItemName( aName, false ); // The LIB_ALIAS that is the LIB_PART name has to be created so create it. if( m_aliases.size() == 0 ) m_aliases.push_back( new LIB_ALIAS( aName, this ) ); else m_aliases[0]->SetName( aName ); + + LIB_FIELD& valueField = GetValueField(); + + // LIB_FIELD::SetText() calls LIB_PART::SetName(), + // the following if-clause is to break an infinite loop + if( valueField.GetText() != aName ) + valueField.SetText( aName ); + } @@ -897,23 +894,16 @@ bool LIB_PART::Load( LINE_READER& aLineReader, wxString& aErrorMsg ) m_showPinNames = ( drawname == 'N' ) ? false : true; // Copy part name and prefix. - LIB_FIELD& value = GetValueField(); - if( componentName[0] != '~' ) { - m_name = FROM_UTF8( componentName ); - value.SetText( m_name ); + SetName( FROM_UTF8( componentName ) ); } else { - m_name = FROM_UTF8( &componentName[1] ); - value.SetText( m_name ); - value.SetVisible( false ); + SetName( FROM_UTF8( &componentName[1] ) ); + GetValueField().SetVisible( false ); } - // Add the root alias to the alias list. - m_aliases.push_back( new LIB_ALIAS( m_name, this ) ); - LIB_FIELD& reference = GetReferenceField(); if( strcmp( prefix, "~" ) == 0 ) @@ -1111,7 +1101,7 @@ bool LIB_PART::LoadField( LINE_READER& aLineReader, wxString& aErrorMsg ) *fixedField = *field; if( field->GetId() == VALUE ) - m_name = field->GetText(); + SetName( field->GetText() ); delete field; } @@ -1671,6 +1661,15 @@ void LIB_PART::SetConversion( bool aSetConvert ) } +void LIB_PART::SetLib( PART_LIB* aLibrary ) +{ + m_library = aLibrary; + + if( aLibrary ) + m_libId.SetLibNickname( aLibrary->GetName() ); +} + + wxArrayString LIB_PART::GetAliasNames( bool aIncludeRoot ) const { wxArrayString names; @@ -1708,6 +1707,7 @@ void LIB_PART::SetAliases( const wxArrayString& aAliasList ) { wxCHECK_RET( !m_library, wxT( "Part aliases cannot be changed when they are owned by a library." ) ); + wxCHECK_RET( !aAliasList.IsEmpty(), wxT( "Alias list cannot be empty" ) ); if( aAliasList == GetAliasNames() ) return; @@ -1782,7 +1782,7 @@ LIB_ALIAS* LIB_PART::RemoveAlias( LIB_ALIAS* aAlias ) wxLogTrace( traceSchLibMem, wxT( "%s: part:'%s', alias:'%s', alias count %llu, reference count %ld." ), GetChars( wxString::FromAscii( __WXFUNCTION__ ) ), - GetChars( m_name ), + GetChars( GetName() ), GetChars( aAlias->GetName() ), (long long unsigned) m_aliases.size(), m_me.use_count() ); diff --git a/eeschema/class_libentry.h b/eeschema/class_libentry.h index 5decec9c5b..6c2f1ee1ed 100644 --- a/eeschema/class_libentry.h +++ b/eeschema/class_libentry.h @@ -89,8 +89,6 @@ class LIB_ALIAS : public EDA_ITEM */ LIB_PART* shared; - friend class LIB_PART; - protected: wxString name; wxString description; ///< documentation for info @@ -226,12 +224,7 @@ struct PART_DRAW_OPTIONS */ class LIB_PART : public EDA_ITEM { - friend class PART_LIB; - friend class LIB_ALIAS; - friend class SCH_LEGACY_PLUGIN_CACHE; - PART_SPTR m_me; ///< http://www.boost.org/doc/libs/1_55_0/libs/smart_ptr/sp_techniques.html#weak_without_shared - wxString m_name; LIB_ID m_libId; int m_pinNameOffset; ///< The offset in mils to draw the pin name. Set to 0 ///< to draw the pin name above the pin. @@ -258,7 +251,7 @@ class LIB_PART : public EDA_ITEM private: void deleteAllFields(); - // LIB_PART() { } // not legal + public: @@ -280,16 +273,15 @@ public: virtual void SetName( const wxString& aName ); - const wxString& GetName() const { return m_name; } + const wxString& GetName() const { return m_aliases[0]->GetName(); } const LIB_ID& GetLibId() const { return m_libId; } - void SetLibId( const LIB_ID& aLibId ) { m_libId = aLibId; } const wxString GetLibraryName(); PART_LIB* GetLib() { return m_library; } - void SetLib( PART_LIB* aLibrary ) { m_library = aLibrary; } + void SetLib( PART_LIB* aLibrary ); wxArrayString GetAliasNames( bool aIncludeRoot = true ) const; diff --git a/eeschema/class_library.cpp b/eeschema/class_library.cpp index 355dcf8a3a..8bf99133a4 100644 --- a/eeschema/class_library.cpp +++ b/eeschema/class_library.cpp @@ -146,7 +146,7 @@ void PART_LIB::EnableBuffering( bool aEnable ) } -void PART_LIB::GetAliasNames( wxArrayString& aNames ) +void PART_LIB::GetAliasNames( wxArrayString& aNames ) const { m_plugin->EnumerateSymbolLib( aNames, fileName.GetFullPath(), m_properties.get() ); @@ -154,7 +154,7 @@ void PART_LIB::GetAliasNames( wxArrayString& aNames ) } -void PART_LIB::GetAliases( std::vector& aAliases ) +void PART_LIB::GetAliases( std::vector& aAliases ) const { m_plugin->EnumerateSymbolLib( aAliases, fileName.GetFullPath(), m_properties.get() ); @@ -164,7 +164,7 @@ void PART_LIB::GetAliases( std::vector& aAliases ) } -void PART_LIB::GetEntryTypePowerNames( wxArrayString& aNames ) +void PART_LIB::GetEntryTypePowerNames( wxArrayString& aNames ) const { std::vector aliases; @@ -186,7 +186,7 @@ void PART_LIB::GetEntryTypePowerNames( wxArrayString& aNames ) } -LIB_ALIAS* PART_LIB::FindAlias( const wxString& aName ) +LIB_ALIAS* PART_LIB::FindAlias( const wxString& aName ) const { LIB_ALIAS* alias = m_plugin->LoadSymbol( fileName.GetFullPath(), aName, m_properties.get() ); @@ -194,13 +194,13 @@ LIB_ALIAS* PART_LIB::FindAlias( const wxString& aName ) // symbols. This allows the symbol library table conversion tool to determine the // correct library where the symbol was found. if( alias && alias->GetPart() && !alias->GetPart()->GetLib() ) - alias->GetPart()->SetLib( this ); + alias->GetPart()->SetLib( const_cast( this ) ); return alias; } -LIB_PART* PART_LIB::FindPart( const wxString& aName ) +LIB_PART* PART_LIB::FindPart( const wxString& aName ) const { LIB_ALIAS* alias = FindAlias( aName ); @@ -211,7 +211,7 @@ LIB_PART* PART_LIB::FindPart( const wxString& aName ) } -bool PART_LIB::HasPowerParts() +bool PART_LIB::HasPowerParts() const { // return true if at least one power part is found in lib std::vector aliases; diff --git a/eeschema/class_library.h b/eeschema/class_library.h index a4096950cc..3e13695e2d 100644 --- a/eeschema/class_library.h +++ b/eeschema/class_library.h @@ -401,21 +401,21 @@ public: * * @param aNames - String array to place entry names into. */ - void GetAliasNames( wxArrayString& aNames ); + void GetAliasNames( wxArrayString& aNames ) const; /** * Load a vector with all the entries in this library. * * @param aAliases - vector to receive the aliases. */ - void GetAliases( std::vector& aAliases ); + void GetAliases( std::vector& aAliases ) const; /** * Load a string array with the names of entries of type POWER in this library. * * @param aNames - String array to place entry names into. */ - void GetEntryTypePowerNames( wxArrayString& aNames ); + void GetEntryTypePowerNames( wxArrayString& aNames ) const; /** * Find #LIB_ALIAS by \a aName. @@ -423,7 +423,7 @@ public: * @param aName - Name of entry, case sensitive. * @return #LIB_ALIAS* if found. NULL if not found. */ - LIB_ALIAS* FindAlias( const wxString& aName ); + LIB_ALIAS* FindAlias( const wxString& aName ) const; /** * Find part by \a aName. @@ -434,7 +434,7 @@ public: * @param aName - Name of part, case sensitive. * @return LIB_PART* - part if found, else NULL. */ - LIB_PART* FindPart( const wxString& aName ); + LIB_PART* FindPart( const wxString& aName ) const; /** * Add \a aPart entry to library. @@ -481,14 +481,14 @@ public: * * @return wxString - Full library file name with path and extension. */ - wxString GetFullFileName() { return fileName.GetFullPath(); } + wxString GetFullFileName() const { return fileName.GetFullPath(); } /** * Function GetLogicalName * returns the logical name of the library. * @return wxString - The logical name of this library. */ - const wxString GetLogicalName() + const wxString GetLogicalName() const { /* for now is the filename without path or extension. @@ -518,7 +518,7 @@ public: * @return true if at least one power part is found in lib * Useful to select or list only libs containing power parts */ - bool HasPowerParts(); + bool HasPowerParts() const; }; diff --git a/eeschema/cmp_tree_model.cpp b/eeschema/cmp_tree_model.cpp index 994e4aa691..3329512164 100644 --- a/eeschema/cmp_tree_model.cpp +++ b/eeschema/cmp_tree_model.cpp @@ -105,6 +105,7 @@ int CMP_TREE_NODE::Compare( CMP_TREE_NODE const& aNode1, CMP_TREE_NODE const& aN CMP_TREE_NODE::CMP_TREE_NODE() : Parent( nullptr ), Type( INVALID ), + InTree( false ), IntrinsicRank( 0 ), Score( kLowestDefaultScore ), Unit( 0 ) @@ -177,6 +178,7 @@ CMP_TREE_NODE_LIB_ID::CMP_TREE_NODE_LIB_ID( CMP_TREE_NODE* aParent, LIB_ALIAS* a CMP_TREE_NODE_UNIT& CMP_TREE_NODE_LIB_ID::AddUnit( int aUnit ) { CMP_TREE_NODE_UNIT* unit = new CMP_TREE_NODE_UNIT( this, aUnit ); + unit->InTree = true; Children.push_back( std::unique_ptr( unit ) ); return *unit; } @@ -236,12 +238,14 @@ CMP_TREE_NODE_LIB::CMP_TREE_NODE_LIB( CMP_TREE_NODE* aParent, wxString const& aN Name = aName; MatchName = aName.Lower(); Parent = aParent; + LibId.SetLibNickname( aName ); } CMP_TREE_NODE_LIB_ID& CMP_TREE_NODE_LIB::AddAlias( LIB_ALIAS* aAlias ) { CMP_TREE_NODE_LIB_ID* alias = new CMP_TREE_NODE_LIB_ID( this, aAlias ); + alias->InTree = true; Children.push_back( std::unique_ptr( alias ) ); return *alias; } @@ -268,6 +272,7 @@ CMP_TREE_NODE_ROOT::CMP_TREE_NODE_ROOT() CMP_TREE_NODE_LIB& CMP_TREE_NODE_ROOT::AddLib( wxString const& aName ) { CMP_TREE_NODE_LIB* lib = new CMP_TREE_NODE_LIB( this, aName ); + lib->InTree = true; Children.push_back( std::unique_ptr( lib ) ); return *lib; } diff --git a/eeschema/cmp_tree_model.h b/eeschema/cmp_tree_model.h index ac130a7e58..0460f8a1f8 100644 --- a/eeschema/cmp_tree_model.h +++ b/eeschema/cmp_tree_model.h @@ -80,9 +80,12 @@ public: ROOT, LIB, LIBID, UNIT, INVALID }; - CMP_TREE_NODE* Parent; ///< Parent node or null - std::vector> Children; ///< List of child nodes - enum TYPE Type; ///< Node type + typedef std::vector> PTR_VECTOR; + + CMP_TREE_NODE* Parent; ///< Parent node or null + PTR_VECTOR Children; ///< List of child nodes + enum TYPE Type; ///< Node type + bool InTree; ///< Flag indicating whether the node is added to the tree /** * The rank of the item before any search terms are applied. This is diff --git a/eeschema/cmp_tree_model_adapter.cpp b/eeschema/cmp_tree_model_adapter.cpp index d9b8cd6add..01c973564c 100644 --- a/eeschema/cmp_tree_model_adapter.cpp +++ b/eeschema/cmp_tree_model_adapter.cpp @@ -26,51 +26,7 @@ #include #include -CMP_TREE_MODEL_ADAPTER::WIDTH_CACHE CMP_TREE_MODEL_ADAPTER::m_width_cache; - - -static const int kDataViewIndent = 20; - - -/** - * Convert CMP_TREE_NODE -> wxDataViewItem - */ -static wxDataViewItem ToItem( CMP_TREE_NODE const* aNode ) -{ - return wxDataViewItem( const_cast( static_cast( aNode ) ) ); -} - - -/** - * Convert wxDataViewItem -> CMP_TREE_NODE - */ -static CMP_TREE_NODE const* ToNode( wxDataViewItem aItem ) -{ - return static_cast( aItem.GetID() ); -} - - -/** - * Convert CMP_TREE_NODE's children to wxDataViewItemArray - */ -static unsigned int IntoArray( CMP_TREE_NODE const& aNode, wxDataViewItemArray& aChildren ) -{ - unsigned int n = 0; - - for( auto const& child: aNode.Children ) - { - if( child->Score > 0 ) - { - aChildren.Add( ToItem( &*child ) ); - ++n; - } - } - - return n; -} - - -CMP_TREE_MODEL_ADAPTER::PTR CMP_TREE_MODEL_ADAPTER::Create( SYMBOL_LIB_TABLE* aLibs ) +CMP_TREE_MODEL_ADAPTER_BASE::PTR CMP_TREE_MODEL_ADAPTER::Create( SYMBOL_LIB_TABLE* aLibs ) { auto adapter = new CMP_TREE_MODEL_ADAPTER( aLibs ); auto container = CMP_TREE_MODEL_ADAPTER::PTR( adapter ); @@ -79,13 +35,7 @@ CMP_TREE_MODEL_ADAPTER::PTR CMP_TREE_MODEL_ADAPTER::Create( SYMBOL_LIB_TABLE* aL CMP_TREE_MODEL_ADAPTER::CMP_TREE_MODEL_ADAPTER( SYMBOL_LIB_TABLE* aLibs ) - :m_filter( CMP_FILTER_NONE ), - m_show_units( true ), - m_libs( aLibs ), - m_preselect_unit( 0 ), - m_col_part( nullptr ), - m_col_desc( nullptr ), - m_widget( nullptr ) + : m_libs( aLibs ) {} @@ -93,28 +43,9 @@ CMP_TREE_MODEL_ADAPTER::~CMP_TREE_MODEL_ADAPTER() {} -void CMP_TREE_MODEL_ADAPTER::SetFilter( CMP_FILTER_TYPE aFilter ) -{ - m_filter = aFilter; -} - - -void CMP_TREE_MODEL_ADAPTER::ShowUnits( bool aShow ) -{ - m_show_units = aShow; -} - - -void CMP_TREE_MODEL_ADAPTER::SetPreselectNode( LIB_ID const& aLibId, int aUnit ) -{ - m_preselect_lib_id = aLibId; - m_preselect_unit = aUnit; -} - - void CMP_TREE_MODEL_ADAPTER::AddLibrary( wxString const& aLibNickname ) { - bool onlyPowerSymbols = ( m_filter == CMP_FILTER_POWER ); + bool onlyPowerSymbols = ( GetFilter() == CMP_FILTER_POWER ); wxArrayString aliases; @@ -135,26 +66,6 @@ void CMP_TREE_MODEL_ADAPTER::AddLibrary( wxString const& aLibNickname ) } -void CMP_TREE_MODEL_ADAPTER::AddLibrariesWithProgress( const std::vector& aNicknames, EDA_DRAW_FRAME* aParent ) -{ - auto* prg = new wxProgressDialog( - _( "Loading symbol libraries" ), - wxEmptyString, - aNicknames.size(), - aParent ); - - unsigned int ii = 0; - - for( auto nickname : aNicknames ) - { - prg->Update( ii++, wxString::Format( _( "Loading library '%s'" ), nickname ) ); - AddLibrary( nickname ); - } - - prg->Destroy(); -} - - void CMP_TREE_MODEL_ADAPTER::AddAliasList( wxString const& aNodeName, wxArrayString const& aAliasNameList ) @@ -182,312 +93,3 @@ void CMP_TREE_MODEL_ADAPTER::AddAliasList( AddAliasList( aNodeName, alias_list ); } - - -void CMP_TREE_MODEL_ADAPTER::AddAliasList( - wxString const& aNodeName, - std::vector const& aAliasList ) -{ - auto& lib_node = m_tree.AddLib( aNodeName ); - - for( auto a: aAliasList ) - { - lib_node.AddAlias( a ); - } - - lib_node.AssignIntrinsicRanks(); - m_tree.AssignIntrinsicRanks(); -} - - -void CMP_TREE_MODEL_ADAPTER::UpdateSearchString( wxString const& aSearch ) -{ - m_tree.ResetScore(); - - wxStringTokenizer tokenizer( aSearch ); - - while( tokenizer.HasMoreTokens() ) - { - const wxString term = tokenizer.GetNextToken().Lower(); - EDA_COMBINED_MATCHER matcher( term ); - - m_tree.UpdateScore( matcher ); - } - - m_tree.SortNodes(); - Cleared(); - AttachTo( m_widget ); - - ShowResults() || ShowPreselect() || ShowSingleLibrary(); -} - - -void CMP_TREE_MODEL_ADAPTER::AttachTo( wxDataViewCtrl* aDataViewCtrl ) -{ - m_widget = aDataViewCtrl; - aDataViewCtrl->Freeze(); - aDataViewCtrl->SetIndent( kDataViewIndent ); - aDataViewCtrl->AssociateModel( this ); - aDataViewCtrl->ClearColumns(); - - wxString part_head = _( "Part" ); - wxString desc_head = _( "Desc" ); - - m_col_part = aDataViewCtrl->AppendTextColumn( part_head, 0, wxDATAVIEW_CELL_INERT, - ColWidth( m_tree, 0, part_head ) ); - m_col_desc = aDataViewCtrl->AppendTextColumn( desc_head, 1, wxDATAVIEW_CELL_INERT, - ColWidth( m_tree, 1, desc_head ) ); - aDataViewCtrl->Thaw(); -} - - -LIB_ID CMP_TREE_MODEL_ADAPTER::GetAliasFor( wxDataViewItem aSelection ) const -{ - auto node = ToNode( aSelection ); - - LIB_ID emptyId; - - if( !node ) - return emptyId; - - return node->LibId; -} - - -int CMP_TREE_MODEL_ADAPTER::GetUnitFor( wxDataViewItem aSelection ) const -{ - auto node = ToNode( aSelection ); - return node ? node->Unit : 0; -} - - -int CMP_TREE_MODEL_ADAPTER::GetComponentsCount() const -{ - int n = 0; - - for( auto& lib: m_tree.Children ) - { - for( auto& alias: lib->Children ) - { - (void) alias; - ++n; - } - } - - return n; -} - - -bool CMP_TREE_MODEL_ADAPTER::HasContainerColumns( wxDataViewItem const& aItem ) const -{ - return IsContainer( aItem ); -} - - -bool CMP_TREE_MODEL_ADAPTER::IsContainer( wxDataViewItem const& aItem ) const -{ - auto node = ToNode( aItem ); - return node ? node->Children.size() : true; -} - - -wxDataViewItem CMP_TREE_MODEL_ADAPTER::GetParent( wxDataViewItem const& aItem ) const -{ - auto node = ToNode( aItem ); - auto parent = node ? node->Parent : nullptr; - - // wxDataViewModel has no root node, but rather top-level elements have - // an invalid (null) parent. - if( !node || !parent || parent->Type == CMP_TREE_NODE::TYPE::ROOT ) - { - return ToItem( nullptr ); - } - else - { - return ToItem( parent ); - } -} - - -unsigned int CMP_TREE_MODEL_ADAPTER::GetChildren( - wxDataViewItem const& aItem, - wxDataViewItemArray& aChildren ) const -{ - auto node = ( aItem.IsOk() ? ToNode( aItem ) : &m_tree ); - - if( node->Type != CMP_TREE_NODE::TYPE::LIBID || m_show_units ) - return IntoArray( *node, aChildren ); - else - return 0; -} - - -void CMP_TREE_MODEL_ADAPTER::GetValue( - wxVariant& aVariant, - wxDataViewItem const& aItem, - unsigned int aCol ) const -{ - auto node = ToNode( aItem ); - wxASSERT( node ); - - switch( aCol ) - { - case 0: - aVariant = node->Name; - break; - case 1: - aVariant = node->Desc; - break; - default: - wxFAIL_MSG( "Invalid column ID!" ); - } -} - - -bool CMP_TREE_MODEL_ADAPTER::GetAttr( - wxDataViewItem const& aItem, - unsigned int aCol, - wxDataViewItemAttr& aAttr ) const -{ - auto node = ToNode( aItem ); - wxASSERT( node ); - - if( node->Type != CMP_TREE_NODE::LIBID ) - { - // Currently only aliases are formatted at all - return false; - } - - if( !node->IsRoot && aCol == 0 ) - { - // Names of non-root aliases are italicized - aAttr.SetItalic( true ); - return true; - } - else - { - return false; - } -} - - -int CMP_TREE_MODEL_ADAPTER::ColWidth( CMP_TREE_NODE& aTree, int aCol, wxString const& aHeading ) -{ - const int indent = aCol ? 0 : kDataViewIndent; - - int min_width = WidthFor( aHeading, aCol ); - int width = std::max( aTree.Score > 0 ? WidthFor( aTree, aCol ) : 0, min_width ); - - if( aTree.Score > 0 ) - { - for( auto& node: aTree.Children ) - { - width = std::max( width, ColWidth( *node, aCol, aHeading ) + indent ); - } - } - - return width; -} - - -int CMP_TREE_MODEL_ADAPTER::WidthFor( CMP_TREE_NODE& aNode, int aCol ) -{ - auto result = m_width_cache.find( aNode.Name ); - - if( result != m_width_cache.end() ) - { - return result->second[aCol]; - } - else - { - int wname = m_widget->GetTextExtent( aNode.Name ).x + kDataViewIndent; - int wdesc = m_widget->GetTextExtent( aNode.Desc ).x; - - auto& val = m_width_cache[aNode.Name]; - val.push_back( wname ); - val.push_back( wdesc ); - return val[aCol]; - } -} - - -int CMP_TREE_MODEL_ADAPTER::WidthFor( wxString const& aHeading, int aCol ) -{ - static std::vector widths; - - for( int i = (int) widths.size(); i <= aCol; ++i ) - { - widths.push_back( 0 ); - } - - if( widths[aCol] == 0 ) - { - widths[aCol] = m_widget->GetTextExtent( aHeading ).x; - } - - return widths[aCol]; -} - - -bool CMP_TREE_MODEL_ADAPTER::FindAndExpand( - CMP_TREE_NODE& aNode, - std::function aFunc ) -{ - for( auto& node: aNode.Children ) - { - if( aFunc( &*node ) ) - { - auto item = wxDataViewItem( - const_cast( static_cast( &*node ) ) ); - m_widget->ExpandAncestors( item ); - m_widget->EnsureVisible( item ); - m_widget->Select( item ); - return true; - } - else if( FindAndExpand( *node, aFunc ) ) - { - return true; - } - } - - return false; -} - - -bool CMP_TREE_MODEL_ADAPTER::ShowResults() -{ - return FindAndExpand( m_tree, - []( CMP_TREE_NODE const* n ) - { - return n->Type == CMP_TREE_NODE::TYPE::LIBID && n->Score > 1; - } ); -} - - -bool CMP_TREE_MODEL_ADAPTER::ShowPreselect() -{ - if( !m_preselect_lib_id.IsValid() ) - return false; - - return FindAndExpand( m_tree, - [&]( CMP_TREE_NODE const* n ) - { - if( n->Type == CMP_TREE_NODE::LIBID && ( n->Children.empty() || !m_preselect_unit ) ) - return m_preselect_lib_id == n->LibId; - else if( n->Type == CMP_TREE_NODE::UNIT && m_preselect_unit ) - return m_preselect_lib_id == n->Parent->LibId && m_preselect_unit == n->Unit; - else - return false; - } ); -} - - -bool CMP_TREE_MODEL_ADAPTER::ShowSingleLibrary() -{ - return FindAndExpand( m_tree, - []( CMP_TREE_NODE const* n ) - { - return n->Type == CMP_TREE_NODE::TYPE::LIBID && - n->Parent->Parent->Children.size() == 1; - } ); -} diff --git a/eeschema/cmp_tree_model_adapter.h b/eeschema/cmp_tree_model_adapter.h index 06f6c68e11..17c033370c 100644 --- a/eeschema/cmp_tree_model_adapter.h +++ b/eeschema/cmp_tree_model_adapter.h @@ -22,84 +22,18 @@ #ifndef _CMP_TREE_MODEL_ADAPTER_H #define _CMP_TREE_MODEL_ADAPTER_H -#include - -#include -#include - -#include -#include -#include -#include +#include class SYMBOL_LIB_TABLE; - -/** - * Adapter class in the component selector Model-View-Adapter (mediated MVC) - * architecture. The other pieces are in: - * - * - Model: CMP_TREE_NODE and descendants in eeschema/cmp_tree_model.h - * - View: - * - DIALOG_CHOOSE_COMPONENT in eeschema/dialogs/dialog_choose_component.h - * - wxDataViewCtrl - * - * This adapter presents the interface specified by wxDataViewModel to the - * wxDataViewCtrl: - * - * +---+ +------------------+ - * +---+ Generates | A | | VIEW | - * | M | from libs | D | wxDataViewModel |------------------| - * | O | <---------- | A | <------------------> | wxDataViewCtrl | - * | D | | P | |------------------| - * | E | <---------> | T | <------------------- | wxTextCtrl | - * | L | UpdateScore | E | UpdateSearchString() |------------------| - * +---+ | R | | | - * +---+ +------------------+ - * - * Because this adapter is a wxDataViewModel, it is reference-counted by - * wxObject. To ensure this interface is used correctly, the constructor - * is private; CMP_TREE_MODEL_ADAPTER should be created by the static - * factory method CMP_TREE_MODEL_ADAPTER::Create(). - * - * Quick summary of methods used to drive this class: - * - * - `SetFilter()` - set whether the view is restricted to power parts - * - `ShowUnits()` - set whether units are displayed - * - `SetPreselectNode()` - set a node to highlight when not searching - * - `AddLibrary()` - populate the model with all aliases in a library - * - `AddAliasList()` - populate the model with a specific list of aliases - * - * Quick summary of methods used by the View: - * - * - `UpdateSearchString()` - pass in the user's search text - * - `AttachTo()` - pass in the wxDataViewCtrl - * - `GetAliasFor()` - get the LIB_ALIAS* for a selected item - * - `GetUnitFor()` - get the unit for a selected item - * - `GetComponentsCount()` - count the aliases loaded - * - * Methods implemented as part of wxDataViewModel: - * - * - `HasContainerColumns()` - whether a parent item has more than one column - * - `IsContainer()` - whether an item is a parent - * - `GetParent()` - return the parent of an item, or invalid if root - * - `GetChildren()` - get the children of an item - * - `GetColumnCount()` - get the number of columns in the view - * - `GetColumnType()` - get the data type shown in each column - * - `GetValue()` - get the data shown in a cell - * - `SetValue()` - edit the data in a cell (does nothing) - * - `GetAttr()` - get any per-item formatting - * - `Compare()` - compare two rows, for sorting - * - `HasDefaultCompare()` - whether sorted by default - */ -class CMP_TREE_MODEL_ADAPTER: public wxDataViewModel +class CMP_TREE_MODEL_ADAPTER: public CMP_TREE_MODEL_ADAPTER_BASE { public: /** * Reference-counting container for a pointer to CMP_TREE_MODEL_ADAPTER. */ - typedef wxObjectDataPtr PTR; + //typedef wxObjectDataPtr PTR; /** * Destructor. Do NOT delete this class manually; it is reference-counted @@ -115,57 +49,13 @@ public: */ static PTR Create( SYMBOL_LIB_TABLE* aLibs ); - /** - * This enum allows a selective filtering of components to list - */ - enum CMP_FILTER_TYPE - { - CMP_FILTER_NONE, ///< no filtering - CMP_FILTER_POWER, ///< list components flagged PWR - }; - - /** - * Set the component filter type. Must be set before adding libraries - * - * @param aFilter if CMP_FILTER_POWER, only power parts are loaded - */ - void SetFilter( CMP_FILTER_TYPE aFilter ); - - /** - * Whether or not to show units. May be set at any time; updates at the next - * UpdateSearchString() - * - * @param aShow if true, units are displayed - */ - void ShowUnits( bool aShow ); - - /** - * Set the component name to be selected if there are no search results. - * May be set at any time; updates at the next UpdateSearchString(). - * - * @param aLibId symbol #LIB_ID to be selected - * @param aUnit unit to be selected, if > 0 (0 selects the alias itself) - */ - void SetPreselectNode( LIB_ID const& aLibId, int aUnit ); - /** * Add all the components and their aliases in this library. To be called * in the setup phase. * * @param aLibNickname reference to a symbol library nickname */ - void AddLibrary( wxString const& aLibNickname ); - - - /** - * Add all the libraries in a SYMBOL_LIB_TABLE to the model, - * displaying a progress dialog attached to the parent frame - * - * @param aNicknames is the list of library nicknames - * @param aParent is the parent window to display the progress dialog - */ - void AddLibrariesWithProgress( const std::vector& aNicknames, EDA_DRAW_FRAME* aParent ); - + void AddLibrary( wxString const& aLibNickname ) override; /** * Add the given list of components, by name. To be called in the setup @@ -176,60 +66,9 @@ public: */ void AddAliasList( wxString const& aNodeName, - wxArrayString const& aAliasNameList ); - - /** - * Add the given list of components by alias. To be called in the setup - * phase. - * - * @param aNodeName the parent node the components will appear under - * @param aAliasList list of aliases - */ - void AddAliasList( - wxString const& aNodeName, - std::vector const& aAliasList ); - - /** - * Set the search string provided by the user. - * - * @param aSearch full, unprocessed search text - */ - void UpdateSearchString( wxString const& aSearch ); - - /** - * Attach to a wxDataViewCtrl and initialize it. This will set up columns - * and associate the model via the adapter. - * - * @param aDataViewCtrl the view component in the dialog - */ - void AttachTo( wxDataViewCtrl* aDataViewCtrl ); - - /** - * Return the alias for the given item. - * - * @param aSelection item from the wxDataViewCtrl - * (see wxDataViewCtrl::GetSelection()) - * - * @return alias, or nullptr if none is selected - */ - LIB_ID GetAliasFor( wxDataViewItem aSelection ) const; - - /** - * Return the unit for the given item. - * - * @param aSelection item from the wxDataViewCtrl - * (see wxDataViewCtrl::GetSelection()) - * - * @return Unit, or zero if the alias itself is selected. Return valid is - * invalid if GetAliasFor() returns nullptr. - */ - int GetUnitFor( wxDataViewItem aSelection ) const; - - /** - * Return the number of components loaded in the tree. - */ - int GetComponentsCount() const; + wxArrayString const& aAliasNameList ) override; + using CMP_TREE_MODEL_ADAPTER_BASE::AddAliasList; protected: /** @@ -237,143 +76,8 @@ protected: */ CMP_TREE_MODEL_ADAPTER( SYMBOL_LIB_TABLE* aLibs ); - /** - * Check whether a container has columns too - */ - virtual bool HasContainerColumns( wxDataViewItem const& aItem ) const override; - - /** - * Check whether an item can have children. - */ - virtual bool IsContainer( wxDataViewItem const& aItem ) const override; - - /** - * Get the parent of an item. - * - * @param aItem item to get the parent of - * @return parent of aItem, or an invalid wxDataViewItem if parent is root - */ - virtual wxDataViewItem GetParent( wxDataViewItem const& aItem ) const override; - - /** - * Populate a list of all the children of an item - * - * @return number of children - */ - virtual unsigned int GetChildren( - wxDataViewItem const& aItem, - wxDataViewItemArray& aChildren ) const override; - - /** - * Return the number of columns in the model - */ - virtual unsigned int GetColumnCount() const override { return 2; } - - /** - * Return the type of data stored in the column - * - * @return type of data as indicated by wxVariant::GetType() - */ - virtual wxString GetColumnType( unsigned int aCol ) const override { return "string"; } - - /** - * Get the value of an item. - * - * @param aVariant wxVariant to receive the data - * @param aItem item whose data will be placed into aVariant - * @param aCol column number of the data - */ - virtual void GetValue( - wxVariant& aVariant, - wxDataViewItem const& aItem, - unsigned int aCol ) const override; - - /** - * Set the value of an item. Does nothing - this model doesn't support - * editing. - */ - virtual bool SetValue( - wxVariant const& aVariant, - wxDataViewItem const& aItem, - unsigned int aCol ) override { return false; } - - /** - * Get any formatting for an item. - * - * @param aItem item to get formatting for - * @param aCol column number of interest - * @param aAttr receiver for attributes - * @return true iff the item has non-default attributes - */ - virtual bool GetAttr( - wxDataViewItem const& aItem, - unsigned int aCol, - wxDataViewItemAttr& aAttr ) const override; - private: - CMP_FILTER_TYPE m_filter; - bool m_show_units; SYMBOL_LIB_TABLE* m_libs; - LIB_ID m_preselect_lib_id; - int m_preselect_unit; - - CMP_TREE_NODE_ROOT m_tree; - - wxDataViewColumn* m_col_part; - wxDataViewColumn* m_col_desc; - wxDataViewCtrl* m_widget; - - WX_DECLARE_STRING_HASH_MAP( std::vector, WIDTH_CACHE ); - - static WIDTH_CACHE m_width_cache; - - /** - * Compute the width required for the given column of a node and its - * children. - * - * @param aTree - root node of the tree - * @param aCol - column number - * @param aHeading - heading text, to set the minimum width - */ - int ColWidth( CMP_TREE_NODE& aTree, int aCol, wxString const& aHeading ); - - /** - * Return the width required to display a single row's aCol text. - * This is cached for efficiency as it's very slow on some platforms - * (*cough* macOS) - */ - int WidthFor( CMP_TREE_NODE& aNode, int aCol ); - - /** - * Return the width required to display a column's heading. This is - * cached by column number for the same reason as the width per cell. - */ - int WidthFor( wxString const& aHeading, int aCol ); - - /** - * Find any results worth highlighting and expand them, according to given - * criteria (f(CMP_TREE_NODE const*) -> bool) - * - * @return whether a node was expanded - */ - bool FindAndExpand( - CMP_TREE_NODE& aNode, - std::function aFunc ); - - /** - * Find and expand successful search results - */ - bool ShowResults(); - - /** - * Find and expand preselected node - */ - bool ShowPreselect(); - - /** - * Find and expand a library if there is only one - */ - bool ShowSingleLibrary(); }; #endif // _CMP_TREE_MODEL_ADAPTER_H diff --git a/eeschema/cmp_tree_model_adapter_base.cpp b/eeschema/cmp_tree_model_adapter_base.cpp new file mode 100644 index 0000000000..29b78c5fa0 --- /dev/null +++ b/eeschema/cmp_tree_model_adapter_base.cpp @@ -0,0 +1,520 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2017 Chris Pavlina + * Copyright (C) 2014 Henner Zeller + * Copyright (C) 2014-2017 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 3 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, see . + */ + +#include + +#include + +#include +#include + + +CMP_TREE_MODEL_ADAPTER_BASE::WIDTH_CACHE CMP_TREE_MODEL_ADAPTER_BASE::m_width_cache; + + +static const int kDataViewIndent = 20; + + +/** + * Convert CMP_TREE_NODE -> wxDataViewItem + */ +wxDataViewItem CMP_TREE_MODEL_ADAPTER_BASE::ToItem( CMP_TREE_NODE const* aNode ) +{ + return wxDataViewItem( const_cast( static_cast( aNode ) ) ); +} + + +/** + * Convert wxDataViewItem -> CMP_TREE_NODE + */ +CMP_TREE_NODE const* CMP_TREE_MODEL_ADAPTER_BASE::ToNode( wxDataViewItem aItem ) +{ + return static_cast( aItem.GetID() ); +} + + +/** + * Convert CMP_TREE_NODE's children to wxDataViewItemArray + */ +unsigned int CMP_TREE_MODEL_ADAPTER_BASE::IntoArray( + CMP_TREE_NODE const& aNode, wxDataViewItemArray& aChildren ) +{ + unsigned int n = 0; + + for( auto const& child: aNode.Children ) + { + if( child->Score > 0 && child->InTree ) + { + aChildren.Add( ToItem( &*child ) ); + ++n; + } + } + + return n; +} + + +CMP_TREE_MODEL_ADAPTER_BASE::CMP_TREE_MODEL_ADAPTER_BASE() + :m_filter( CMP_FILTER_NONE ), + m_show_units( true ), + m_preselect_unit( 0 ), + m_col_part( nullptr ), + m_col_desc( nullptr ), + m_widget( nullptr ) +{} + + +CMP_TREE_MODEL_ADAPTER_BASE::~CMP_TREE_MODEL_ADAPTER_BASE() +{} + + +void CMP_TREE_MODEL_ADAPTER_BASE::SetFilter( CMP_FILTER_TYPE aFilter ) +{ + m_filter = aFilter; +} + + +void CMP_TREE_MODEL_ADAPTER_BASE::ShowUnits( bool aShow ) +{ + m_show_units = aShow; +} + + +void CMP_TREE_MODEL_ADAPTER_BASE::SetPreselectNode( LIB_ID const& aLibId, int aUnit ) +{ + m_preselect_lib_id = aLibId; + m_preselect_unit = aUnit; +} + + +void CMP_TREE_MODEL_ADAPTER_BASE::AddLibrariesWithProgress( + const std::vector& aNicknames, wxWindow* aParent ) +{ + auto* prg = new wxProgressDialog( + _( "Loading symbol libraries" ), + wxEmptyString, + aNicknames.size(), + aParent ); + + unsigned int ii = 0; + + for( auto nickname : aNicknames ) + { + prg->Update( ii++, wxString::Format( _( "Loading library '%s'" ), nickname ) ); + AddLibrary( nickname ); + } + + prg->Destroy(); +} + + +void CMP_TREE_MODEL_ADAPTER_BASE::AddAliasList( + wxString const& aNodeName, + std::vector const& aAliasList ) +{ + auto& lib_node = m_tree.AddLib( aNodeName ); + + for( auto a: aAliasList ) + { + lib_node.AddAlias( a ); + } + + lib_node.AssignIntrinsicRanks(); + m_tree.AssignIntrinsicRanks(); +} + + +void CMP_TREE_MODEL_ADAPTER_BASE::UpdateSearchString( wxString const& aSearch ) +{ + m_widget->Freeze(); + m_tree.ResetScore(); + + wxStringTokenizer tokenizer( aSearch ); + + while( tokenizer.HasMoreTokens() ) + { + const wxString term = tokenizer.GetNextToken().Lower(); + EDA_COMBINED_MATCHER matcher( term ); + + m_tree.UpdateScore( matcher ); + } + + filterContents(); + ShowResults() || ShowPreselect() || ShowSingleLibrary(); + m_widget->Thaw(); +} + + +void CMP_TREE_MODEL_ADAPTER_BASE::AttachTo( wxDataViewCtrl* aDataViewCtrl ) +{ + m_widget = aDataViewCtrl; + aDataViewCtrl->Freeze(); + aDataViewCtrl->SetIndent( kDataViewIndent ); + aDataViewCtrl->AssociateModel( this ); + aDataViewCtrl->ClearColumns(); + + wxString part_head = _( "Part" ); + wxString desc_head = _( "Desc" ); + + m_col_part = aDataViewCtrl->AppendTextColumn( part_head, 0, wxDATAVIEW_CELL_INERT, + ColWidth( m_tree, 0, part_head ) ); + m_col_desc = aDataViewCtrl->AppendTextColumn( desc_head, 1, wxDATAVIEW_CELL_INERT, + ColWidth( m_tree, 1, desc_head ) ); + m_col_part->SetSortOrder( 0 ); + aDataViewCtrl->Thaw(); +} + + +LIB_ID CMP_TREE_MODEL_ADAPTER_BASE::GetAliasFor( const wxDataViewItem& aSelection ) const +{ + auto node = ToNode( aSelection ); + + LIB_ID emptyId; + + if( !node ) + return emptyId; + + return node->LibId; +} + + +int CMP_TREE_MODEL_ADAPTER_BASE::GetUnitFor( const wxDataViewItem& aSelection ) const +{ + auto node = ToNode( aSelection ); + return node ? node->Unit : 0; +} + + +CMP_TREE_NODE::TYPE CMP_TREE_MODEL_ADAPTER_BASE::GetTypeFor( const wxDataViewItem& aSelection ) const +{ + auto node = ToNode( aSelection ); + return node ? node->Type : CMP_TREE_NODE::INVALID; +} + + +int CMP_TREE_MODEL_ADAPTER_BASE::GetComponentsCount() const +{ + int n = 0; + + for( auto& lib: m_tree.Children ) + { + for( auto& alias: lib->Children ) + { + (void) alias; + ++n; + } + } + + return n; +} + + +wxDataViewItem CMP_TREE_MODEL_ADAPTER_BASE::FindItem( const LIB_ID& aLibId ) +{ + for( auto& lib: m_tree.Children ) + { + if( lib->Name != aLibId.GetLibNickname() ) + continue; + + // if part name is not specified, return the library node + if( aLibId.GetLibItemName() == "" ) + return ToItem( lib.get() ); + + for( auto& alias: lib->Children ) + { + if( alias->Name == aLibId.GetLibItemName() ) + return ToItem( alias.get() ); + } + + break; // could not find the part in the requested library + } + + return wxDataViewItem(); +} + + +unsigned int CMP_TREE_MODEL_ADAPTER_BASE::GetChildren( + wxDataViewItem const& aItem, + wxDataViewItemArray& aChildren ) const +{ + auto node = ( aItem.IsOk() ? ToNode( aItem ) : &m_tree ); + + if( node->Type != CMP_TREE_NODE::TYPE::LIBID + || ( m_show_units && node->Type == CMP_TREE_NODE::TYPE::LIBID ) ) + return IntoArray( *node, aChildren ); + else + return 0; +} + + +bool CMP_TREE_MODEL_ADAPTER_BASE::HasContainerColumns( wxDataViewItem const& aItem ) const +{ + return IsContainer( aItem ); +} + + +bool CMP_TREE_MODEL_ADAPTER_BASE::IsContainer( wxDataViewItem const& aItem ) const +{ + auto node = ToNode( aItem ); + return node ? node->Children.size() : true; +} + + +wxDataViewItem CMP_TREE_MODEL_ADAPTER_BASE::GetParent( wxDataViewItem const& aItem ) const +{ + auto node = ToNode( aItem ); + auto parent = node ? node->Parent : nullptr; + + // wxDataViewModel has no root node, but rather top-level elements have + // an invalid (null) parent. + if( !node || !parent || parent->Type == CMP_TREE_NODE::TYPE::ROOT ) + { + return ToItem( nullptr ); + } + else + { + return ToItem( parent ); + } +} + + +void CMP_TREE_MODEL_ADAPTER_BASE::GetValue( + wxVariant& aVariant, + wxDataViewItem const& aItem, + unsigned int aCol ) const +{ + auto node = ToNode( aItem ); + wxASSERT( node ); + + switch( aCol ) + { + default: // column == -1 is used for default Compare function + case 0: + aVariant = node->Name; + break; + case 1: + aVariant = node->Desc; + break; + } +} + + +bool CMP_TREE_MODEL_ADAPTER_BASE::GetAttr( + wxDataViewItem const& aItem, + unsigned int aCol, + wxDataViewItemAttr& aAttr ) const +{ + auto node = ToNode( aItem ); + wxASSERT( node ); + + if( node->Type != CMP_TREE_NODE::LIBID ) + { + // Currently only aliases are formatted at all + return false; + } + + if( !node->IsRoot && aCol == 0 ) + { + // Names of non-root aliases are italicized + aAttr.SetItalic( true ); + return true; + } + else + { + return false; + } +} + + +int CMP_TREE_MODEL_ADAPTER_BASE::ColWidth( CMP_TREE_NODE& aTree, int aCol, wxString const& aHeading ) +{ + const int indent = aCol ? 0 : kDataViewIndent; + + int min_width = WidthFor( aHeading, aCol ); + int width = std::max( aTree.Score > 0 ? WidthFor( aTree, aCol ) : 0, min_width ); + + if( aTree.Score > 0 ) + { + for( auto& node: aTree.Children ) + { + width = std::max( width, ColWidth( *node, aCol, aHeading ) + indent ); + } + } + + return width; +} + + +int CMP_TREE_MODEL_ADAPTER_BASE::WidthFor( CMP_TREE_NODE& aNode, int aCol ) +{ + auto result = m_width_cache.find( aNode.Name ); + + if( result != m_width_cache.end() ) + { + return result->second[aCol]; + } + else + { + int wname = m_widget->GetTextExtent( aNode.Name ).x + kDataViewIndent; + int wdesc = m_widget->GetTextExtent( aNode.Desc ).x; + + auto& val = m_width_cache[aNode.Name]; + val.push_back( wname ); + val.push_back( wdesc ); + return val[aCol]; + } +} + + +int CMP_TREE_MODEL_ADAPTER_BASE::WidthFor( wxString const& aHeading, int aCol ) +{ + static std::vector widths; + + for( int i = (int) widths.size(); i <= aCol; ++i ) + { + widths.push_back( 0 ); + } + + if( widths[aCol] == 0 ) + { + widths[aCol] = m_widget->GetTextExtent( aHeading ).x; + } + + return widths[aCol]; +} + + +bool CMP_TREE_MODEL_ADAPTER_BASE::FindAndExpand( + CMP_TREE_NODE& aNode, + std::function aFunc ) +{ + for( auto& node: aNode.Children ) + { + if( aFunc( &*node ) ) + { + auto item = wxDataViewItem( + const_cast( static_cast( &*node ) ) ); + m_widget->ExpandAncestors( item ); + m_widget->EnsureVisible( item ); + m_widget->Select( item ); + return true; + } + else if( FindAndExpand( *node, aFunc ) ) + { + return true; + } + } + + return false; +} + + +bool CMP_TREE_MODEL_ADAPTER_BASE::ShowResults() +{ + return FindAndExpand( m_tree, + []( CMP_TREE_NODE const* n ) + { + return n->Type == CMP_TREE_NODE::TYPE::LIBID && n->Score > 1; + } ); +} + + +bool CMP_TREE_MODEL_ADAPTER_BASE::ShowPreselect() +{ + if( !m_preselect_lib_id.IsValid() ) + return false; + + return FindAndExpand( m_tree, + [&]( CMP_TREE_NODE const* n ) + { + if( n->Type == CMP_TREE_NODE::LIBID && ( n->Children.empty() || !m_preselect_unit ) ) + return m_preselect_lib_id == n->LibId; + else if( n->Type == CMP_TREE_NODE::UNIT && m_preselect_unit ) + return m_preselect_lib_id == n->Parent->LibId && m_preselect_unit == n->Unit; + else + return false; + } ); +} + + +bool CMP_TREE_MODEL_ADAPTER_BASE::ShowSingleLibrary() +{ + return FindAndExpand( m_tree, + []( CMP_TREE_NODE const* n ) + { + return n->Type == CMP_TREE_NODE::TYPE::LIBID && + n->Parent->Parent->Children.size() == 1; + } ); +} + + +void CMP_TREE_MODEL_ADAPTER_BASE::filterContents() +{ + // Rebuild the tree using only the filtered nodes + for( auto& lib : m_tree.Children ) + { + lib->InTree = false; + + for( auto& alias : lib->Children ) + { + alias->InTree = false; + + for( auto& unit : lib->Children ) + unit->InTree = false; + } + } + + m_tree.SortNodes(); + Cleared(); + + for( auto& lib : m_tree.Children ) + { + if( lib->Score <= 0 ) + continue; + + wxDataViewItem libItem = ToItem( lib.get() ); + + for( auto& alias : lib->Children ) + { + if( !lib->InTree ) + { + lib->InTree = true; + ItemAdded( wxDataViewItem( nullptr ), libItem ); + } + + if( alias->Score > 0 ) + { + alias->InTree = true; + ItemAdded( libItem, ToItem( alias.get() ) ); + wxDataViewItem aliasItem = ToItem( alias.get() ); + + if( !m_show_units ) + continue; + + for( auto& unit : alias->Children ) + { + unit->InTree = true; + ItemAdded( aliasItem, ToItem( unit.get() ) ); + } + } + } + } +} diff --git a/eeschema/cmp_tree_model_adapter_base.h b/eeschema/cmp_tree_model_adapter_base.h new file mode 100644 index 0000000000..66d2b9285f --- /dev/null +++ b/eeschema/cmp_tree_model_adapter_base.h @@ -0,0 +1,398 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2017 Chris Pavlina + * Copyright (C) 2014 Henner Zeller + * Copyright (C) 2014-2017 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 3 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, see . + */ + +#ifndef _CMP_TREE_MODEL_ADAPTER_BASE_H +#define _CMP_TREE_MODEL_ADAPTER_BASE_H + +#include + +#include + +#include +#include +#include +#include + + +/** + * Adapter class in the component selector Model-View-Adapter (mediated MVC) + * architecture. The other pieces are in: + * + * - Model: CMP_TREE_NODE and descendants in eeschema/cmp_tree_model.h + * - View: + * - DIALOG_CHOOSE_COMPONENT in eeschema/dialogs/dialog_choose_component.h + * - wxDataViewCtrl + * + * This adapter presents the interface specified by wxDataViewModel to the + * wxDataViewCtrl: + * + * +---+ +------------------+ + * +---+ Generates | A | | VIEW | + * | M | from libs | D | wxDataViewModel |------------------| + * | O | <---------- | A | <------------------> | wxDataViewCtrl | + * | D | | P | |------------------| + * | E | <---------> | T | <------------------- | wxTextCtrl | + * | L | UpdateScore | E | UpdateSearchString() |------------------| + * +---+ | R | | | + * +---+ +------------------+ + * + * Because this adapter is a wxDataViewModel, it is reference-counted by + * wxObject. To ensure this interface is used correctly, the constructor + * is private; CMP_TREE_MODEL_ADAPTER should be created by the static + * factory method CMP_TREE_MODEL_ADAPTER::Create(). + * + * Quick summary of methods used to drive this class: + * + * - `SetFilter()` - set whether the view is restricted to power parts + * - `ShowUnits()` - set whether units are displayed + * - `SetPreselectNode()` - set a node to highlight when not searching + * - `AddLibrary()` - populate the model with all aliases in a library + * - `AddAliasList()` - populate the model with a specific list of aliases + * + * Quick summary of methods used by the View: + * + * - `UpdateSearchString()` - pass in the user's search text + * - `AttachTo()` - pass in the wxDataViewCtrl + * - `GetAliasFor()` - get the LIB_ALIAS* for a selected item + * - `GetUnitFor()` - get the unit for a selected item + * - `GetComponentsCount()` - count the aliases loaded + * + * Methods implemented as part of wxDataViewModel: + * + * - `HasContainerColumns()` - whether a parent item has more than one column + * - `IsContainer()` - whether an item is a parent + * - `GetParent()` - return the parent of an item, or invalid if root + * - `GetChildren()` - get the children of an item + * - `GetColumnCount()` - get the number of columns in the view + * - `GetColumnType()` - get the data type shown in each column + * - `GetValue()` - get the data shown in a cell + * - `SetValue()` - edit the data in a cell (does nothing) + * - `GetAttr()` - get any per-item formatting + * - `Compare()` - compare two rows, for sorting + * - `HasDefaultCompare()` - whether sorted by default + */ +class CMP_TREE_MODEL_ADAPTER_BASE: public wxDataViewModel +{ +public: + + /** + * Reference-counting container for a pointer to CMP_TREE_MODEL_ADAPTER_BASE. + */ + typedef wxObjectDataPtr PTR; + + /** + * Destructor. Do NOT delete this class manually; it is reference-counted + * by wxObject. + */ + ~CMP_TREE_MODEL_ADAPTER_BASE(); + + /** + * This enum allows a selective filtering of components to list + */ + enum CMP_FILTER_TYPE + { + CMP_FILTER_NONE, ///< no filtering + CMP_FILTER_POWER, ///< list components flagged PWR + }; + + /** + * Set the component filter type. Must be set before adding libraries + * + * @param aFilter if CMP_FILTER_POWER, only power parts are loaded + */ + void SetFilter( CMP_FILTER_TYPE aFilter ); + + /** + * Return the active filter. + */ + CMP_FILTER_TYPE GetFilter() const { return m_filter; } + + /** + * Whether or not to show units. May be set at any time; updates at the next + * UpdateSearchString() + * + * @param aShow if true, units are displayed + */ + void ShowUnits( bool aShow ); + + /** + * Set the component name to be selected if there are no search results. + * May be set at any time; updates at the next UpdateSearchString(). + * + * @param aLibId symbol #LIB_ID to be selected + * @param aUnit unit to be selected, if > 0 (0 selects the alias itself) + */ + void SetPreselectNode( LIB_ID const& aLibId, int aUnit ); + + /** + * Add all the components and their aliases in this library. To be called + * in the setup phase. + * + * @param aLibNickname reference to a symbol library nickname + */ + virtual void AddLibrary( wxString const& aLibNickname ) = 0; + + /** + * Add all the libraries in a SYMBOL_LIB_TABLE to the model, + * displaying a progress dialog attached to the parent frame + * + * @param aNicknames is the list of library nicknames + * @param aParent is the parent window to display the progress dialog + */ + void AddLibrariesWithProgress( const std::vector& aNicknames, + wxWindow* aParent ); + + /** + * Add the given list of components, by name. To be called in the setup + * phase. + * + * @param aNodeName the parent node the components will appear under + * @param aAliasNameList list of alias names + */ + virtual void AddAliasList( + wxString const& aNodeName, + wxArrayString const& aAliasNameList ) = 0; + + /** + * Add the given list of components by alias. To be called in the setup + * phase. + * + * @param aNodeName the parent node the components will appear under + * @param aAliasList list of aliases + */ + void AddAliasList( + wxString const& aNodeName, + std::vector const& aAliasList ); + + /** + * Set the search string provided by the user. + * + * @param aSearch full, unprocessed search text + */ + void UpdateSearchString( wxString const& aSearch ); + + /** + * Attach to a wxDataViewCtrl and initialize it. This will set up columns + * and associate the model via the adapter. + * + * @param aDataViewCtrl the view component in the dialog + */ + void AttachTo( wxDataViewCtrl* aDataViewCtrl ); + + /** + * Return the alias for the given item. + * + * @param aSelection item from the wxDataViewCtrl + * (see wxDataViewCtrl::GetSelection()) + * + * @return alias, or nullptr if none is selected + */ + LIB_ID GetAliasFor( const wxDataViewItem& aSelection ) const; + + /** + * Return the unit for the given item. + * + * @param aSelection item from the wxDataViewCtrl + * (see wxDataViewCtrl::GetSelection()) + * + * @return Unit, or zero if the alias itself is selected. Return valid is + * invalid if GetAliasFor() returns nullptr. + */ + int GetUnitFor( const wxDataViewItem& aSelection ) const; + + /** + * Return node type for the given item. + * + * @param aSelection item from the wxDataViewCtrl + * (see wxDataViewCtrl::GetSelection()) + * + * @return Type of the selected node, might be INVALID. + */ + CMP_TREE_NODE::TYPE GetTypeFor( const wxDataViewItem& aSelection ) const; + + /** + * Return the number of components loaded in the tree. + */ + int GetComponentsCount() const; + + /** + * Returns tree item corresponding to part. + * + * @param aLibId specifies the part and library name to be searched for. + * @return Tree data item representing the part. Might be invalid if nothings was found. + */ + wxDataViewItem FindItem( const LIB_ID& aLibId ); + + /** + * Populate a list of all the children of an item + * + * @return number of children + */ + virtual unsigned int GetChildren( + wxDataViewItem const& aItem, + wxDataViewItemArray& aChildren ) const override; + +protected: + static wxDataViewItem ToItem( CMP_TREE_NODE const* aNode ); + static CMP_TREE_NODE const* ToNode( wxDataViewItem aItem ); + static unsigned int IntoArray( CMP_TREE_NODE const& aNode, wxDataViewItemArray& aChildren ); + + CMP_TREE_NODE_ROOT m_tree; + + /** + * Constructor + */ + CMP_TREE_MODEL_ADAPTER_BASE(); + + /** + * Check whether a container has columns too + */ + virtual bool HasContainerColumns( wxDataViewItem const& aItem ) const override; + + /** + * Check whether an item can have children. + */ + virtual bool IsContainer( wxDataViewItem const& aItem ) const override; + + /** + * Get the parent of an item. + * + * @param aItem item to get the parent of + * @return parent of aItem, or an invalid wxDataViewItem if parent is root + */ + virtual wxDataViewItem GetParent( wxDataViewItem const& aItem ) const override; + + /** + * Return the number of columns in the model + */ + virtual unsigned int GetColumnCount() const override { return 2; } + + /** + * Return the type of data stored in the column + * + * @return type of data as indicated by wxVariant::GetType() + */ + virtual wxString GetColumnType( unsigned int aCol ) const override { return "string"; } + + /** + * Get the value of an item. + * + * @param aVariant wxVariant to receive the data + * @param aItem item whose data will be placed into aVariant + * @param aCol column number of the data + */ + virtual void GetValue( + wxVariant& aVariant, + wxDataViewItem const& aItem, + unsigned int aCol ) const override; + + /** + * Set the value of an item. Does nothing - this model doesn't support + * editing. + */ + virtual bool SetValue( + wxVariant const& aVariant, + wxDataViewItem const& aItem, + unsigned int aCol ) override { return false; } + + /** + * Get any formatting for an item. + * + * @param aItem item to get formatting for + * @param aCol column number of interest + * @param aAttr receiver for attributes + * @return true iff the item has non-default attributes + */ + virtual bool GetAttr( + wxDataViewItem const& aItem, + unsigned int aCol, + wxDataViewItemAttr& aAttr ) const override; + +private: + CMP_FILTER_TYPE m_filter; + bool m_show_units; + LIB_ID m_preselect_lib_id; + int m_preselect_unit; + + wxDataViewColumn* m_col_part; + wxDataViewColumn* m_col_desc; + wxDataViewCtrl* m_widget; + + WX_DECLARE_STRING_HASH_MAP( std::vector, WIDTH_CACHE ); + + static WIDTH_CACHE m_width_cache; + + /** + * Compute the width required for the given column of a node and its + * children. + * + * @param aTree - root node of the tree + * @param aCol - column number + * @param aHeading - heading text, to set the minimum width + */ + int ColWidth( CMP_TREE_NODE& aTree, int aCol, wxString const& aHeading ); + + /** + * Return the width required to display a single row's aCol text. + * This is cached for efficiency as it's very slow on some platforms + * (*cough* macOS) + */ + int WidthFor( CMP_TREE_NODE& aNode, int aCol ); + + /** + * Return the width required to display a column's heading. This is + * cached by column number for the same reason as the width per cell. + */ + int WidthFor( wxString const& aHeading, int aCol ); + + /** + * Find any results worth highlighting and expand them, according to given + * criteria (f(CMP_TREE_NODE const*) -> bool) + * + * @return whether a node was expanded + */ + bool FindAndExpand( + CMP_TREE_NODE& aNode, + std::function aFunc ); + + /** + * Find and expand successful search results + */ + bool ShowResults(); + + /** + * Find and expand preselected node + */ + bool ShowPreselect(); + + /** + * Find and expand a library if there is only one + */ + bool ShowSingleLibrary(); + + /** + * Filters the items shown in the view according to the score. + */ + void filterContents(); +}; + +#endif // _CMP_TREE_MODEL_ADAPTER_BASE_H + diff --git a/eeschema/eeredraw.cpp b/eeschema/eeredraw.cpp index c2c25b96ee..ddcc6910d0 100644 --- a/eeschema/eeredraw.cpp +++ b/eeschema/eeredraw.cpp @@ -34,7 +34,7 @@ #include -void DrawDanglingSymbol( EDA_DRAW_PANEL* panel, wxDC* DC, const wxPoint& pos, COLOR4D Color ) +void DrawDanglingSymbol( EDA_DRAW_PANEL* panel, wxDC* DC, const wxPoint& pos, const COLOR4D& Color ) { BASE_SCREEN* screen = panel->GetScreen(); diff --git a/eeschema/eeschema_config.cpp b/eeschema/eeschema_config.cpp index c81973bd31..7e4a1c0c34 100644 --- a/eeschema/eeschema_config.cpp +++ b/eeschema/eeschema_config.cpp @@ -460,8 +460,6 @@ static const wxString RepeatStepYEntry = "RepeatStepY"; static const wxString RepeatLabelIncrementEntry = "RepeatLabelIncrement"; // Library editor wxConfig entry names. -static const wxChar lastLibExportPathEntry[] = wxT( "LastLibraryExportPath" ); -static const wxChar lastLibImportPathEntry[] = wxT( "LastLibraryImportPath" ); static const wxChar defaultPinNumSizeEntry[] = wxT( "LibeditPinNumSize" ); static const wxChar defaultPinNameSizeEntry[] = wxT( "LibeditPinNameSize" ); static const wxChar DefaultPinLengthEntry[] = wxT( "DefaultPinLength" ); diff --git a/eeschema/eeschema_id.h b/eeschema/eeschema_id.h index 93ec30f06d..c641323b7a 100644 --- a/eeschema/eeschema_id.h +++ b/eeschema/eeschema_id.h @@ -185,22 +185,36 @@ enum id_eeschema_frm /* Library editor main menubar IDs. */ ID_LIBEDIT_DIMENSIONS, - /* Library editor horizontal toolbar IDs. */ - ID_LIBEDIT_SAVE_CURRENT_PART, - ID_LIBEDIT_SELECT_PART, - ID_LIBEDIT_SELECT_CURRENT_LIB, - ID_LIBEDIT_SAVE_CURRENT_LIB, + /* Library editor: library edit events */ + ID_LIBEDIT_NEW_LIBRARY, + ID_LIBEDIT_ADD_LIBRARY, + ID_LIBEDIT_SAVE_LIBRARY, + ID_LIBEDIT_SAVE_LIBRARY_AS, + ID_LIBEDIT_SAVE_ALL_LIBS, + ID_LIBEDIT_REVERT_LIBRARY, + + /* Library editor: part edit events */ ID_LIBEDIT_NEW_PART, - ID_LIBEDIT_NEW_PART_FROM_EXISTING, - ID_LIBEDIT_GET_FRAME_EDIT_PART, - ID_LIBEDIT_GET_FRAME_EDIT_FIELDS, - ID_LIBEDIT_DELETE_PART, + ID_LIBEDIT_EDIT_PART, + ID_LIBEDIT_IMPORT_PART, + ID_LIBEDIT_EXPORT_PART, + ID_LIBEDIT_SAVE_PART, + ID_LIBEDIT_REVERT_PART, + ID_LIBEDIT_REMOVE_PART, + ID_LIBEDIT_CUT_PART, + ID_LIBEDIT_COPY_PART, + ID_LIBEDIT_PASTE_PART, + ID_LIBEDIT_DUPLICATE_PART, + + /* Library editor horizontal toolbar IDs. */ ID_DE_MORGAN_NORMAL_BUTT, ID_DE_MORGAN_CONVERT_BUTT, ID_LIBEDIT_EDIT_PIN_BY_PIN, ID_LIBEDIT_EDIT_PIN_BY_TABLE, ID_LIBEDIT_VIEW_DOC, ID_LIBEDIT_CHECK_PART, + ID_LIBEDIT_GET_FRAME_EDIT_PART, + ID_LIBEDIT_GET_FRAME_EDIT_FIELDS, ID_LIBEDIT_SELECT_PART_NUMBER, ID_LIBEDIT_SELECT_ALIAS, @@ -240,9 +254,9 @@ enum id_eeschema_frm /* Library editor toolbar options IDs */ ID_LIBEDIT_SHOW_ELECTRICAL_TYPE, + ID_LIBEDIT_SHOW_HIDE_SEARCH_TREE, /* Library editor menubar IDs */ - ID_LIBEDIT_SAVE_CURRENT_LIB_AS, ID_LIBEDIT_GEN_PNG_FILE, ID_LIBEDIT_GEN_SVG_FILE, @@ -273,7 +287,6 @@ enum id_eeschema_frm ID_SIM_SHOW, ID_END_EESCHEMA_ID_LIST - }; diff --git a/eeschema/hotkeys.cpp b/eeschema/hotkeys.cpp index fa442d5c3e..f0d62a642d 100644 --- a/eeschema/hotkeys.cpp +++ b/eeschema/hotkeys.cpp @@ -213,13 +213,13 @@ static EDA_HOTKEY HkFindNextDrcMarker( _HKI( "Find Next DRC Marker" ), HK_FIND_N static EDA_HOTKEY HkZoomSelection( _HKI( "Zoom to Selection" ), HK_ZOOM_SELECTION, '@', ID_ZOOM_SELECTION ); // Special keys for library editor: -static EDA_HOTKEY HkLoadPart( _HKI( "Load Component" ), HK_LIBEDIT_LOAD_PART, 'L' + GR_KB_CTRL ); static EDA_HOTKEY HkCreatePin( _HKI( "Create Pin" ), HK_LIBEDIT_CREATE_PIN, 'P' ); static EDA_HOTKEY HkInsertPin( _HKI( "Repeat Pin" ), HK_REPEAT_LAST, WXK_INSERT ); static EDA_HOTKEY HkMoveLibItem( _HKI( "Move Library Item" ), HK_LIBEDIT_MOVE_GRAPHIC_ITEM, 'M' ); // Load/save files -static EDA_HOTKEY HkSaveLib( _HKI( "Save Library" ), HK_SAVE_LIB, 'S' + GR_KB_CTRL ); +static EDA_HOTKEY HkSaveLib( _HKI( "Save Library" ), HK_SAVE_LIB, 'S' + GR_KB_CTRL + GR_KB_ALT, ID_LIBEDIT_SAVE_LIBRARY ); +static EDA_HOTKEY HkSavePart( _HKI( "Save Part" ), HK_SAVE_PART, 'S' + GR_KB_CTRL, ID_LIBEDIT_SAVE_PART ); static EDA_HOTKEY HkSaveSchematic( _HKI( "Save Schematic" ), HK_SAVE_SCH, 'S' + GR_KB_CTRL ); static EDA_HOTKEY HkLoadSchematic( _HKI( "Load Schematic" ), HK_LOAD_SCH, 'L' + GR_KB_CTRL ); @@ -321,12 +321,15 @@ static EDA_HOTKEY* schematic_Hotkey_List[] = static EDA_HOTKEY* libEdit_Hotkey_List[] = { &HkSaveLib, - &HkLoadPart, + &HkSavePart, &HkCreatePin, &HkInsertPin, &HkMoveLibItem, &HkMirrorX, &HkMirrorY, + &HkCopyBlock, + &HkPasteBlock, + &HkCutBlock, NULL }; @@ -703,6 +706,9 @@ bool LIB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, case HK_ZOOM_REDRAW: case HK_ZOOM_CENTER: case HK_ZOOM_AUTO: + case HK_PASTE_BLOCK: + case HK_COPY_BLOCK: + case HK_CUT_BLOCK: cmd.SetId( hotKey->m_IdMenuEvent ); GetEventHandler()->ProcessEvent( cmd ); break; @@ -777,10 +783,6 @@ bool LIB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, } break; - case HK_LIBEDIT_LOAD_PART: - LoadOneLibraryPart( cmd ); - break; - case HK_LIBEDIT_CREATE_PIN: if( ! itemInEdit ) { diff --git a/eeschema/hotkeys.h b/eeschema/hotkeys.h index c173e95c89..01bee90442 100644 --- a/eeschema/hotkeys.h +++ b/eeschema/hotkeys.h @@ -45,7 +45,6 @@ enum hotkey_id_commnand { HK_COPY_BLOCK, HK_PASTE_BLOCK, HK_CUT_BLOCK, - HK_LIBEDIT_LOAD_PART, HK_LIBEDIT_CREATE_PIN, HK_DELETE_PIN, HK_ROTATE, @@ -76,6 +75,7 @@ enum hotkey_id_commnand { HK_ADD_GRAPHIC_POLYLINE, HK_ADD_NOCONN_FLAG, HK_SAVE_LIB, + HK_SAVE_PART, HK_SAVE_SCH, HK_LOAD_SCH, HK_LEFT_CLICK, diff --git a/eeschema/lib_export.cpp b/eeschema/lib_export.cpp index 90f19aca05..d1939e1a54 100644 --- a/eeschema/lib_export.cpp +++ b/eeschema/lib_export.cpp @@ -37,17 +37,25 @@ #include #include #include +#include +#include #include -extern int ExportPartId; - - void LIB_EDIT_FRAME::OnImportPart( wxCommandEvent& event ) { wxString msg; m_lastDrawItem = NULL; + wxString libName = getTargetLib(); + + if( !m_libMgr->LibraryExists( libName ) ) + { + libName = SelectLibraryFromList(); + + if( !m_libMgr->LibraryExists( libName ) ) + return; + } wxFileDialog dlg( this, _( "Import Symbol" ), m_mruPath, wxEmptyString, SchematicLibraryFileWildcard(), @@ -56,13 +64,13 @@ void LIB_EDIT_FRAME::OnImportPart( wxCommandEvent& event ) if( dlg.ShowModal() == wxID_CANCEL ) return; - wxFileName fn = dlg.GetPath(); - + wxFileName fn = dlg.GetPath(); m_mruPath = fn.GetPath(); wxArrayString symbols; SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_LEGACY ) ); + // TODO dialog to select the part to be imported if there is more than one try { pi->EnumerateSymbolLib( symbols, fn.GetFullPath() ); @@ -81,27 +89,25 @@ void LIB_EDIT_FRAME::OnImportPart( wxCommandEvent& event ) return; } - LIB_ALIAS* entry = pi->LoadSymbol( fn.GetFullPath(), symbols[0] ); + wxString symbolName = symbols[0]; + LIB_ALIAS* entry = pi->LoadSymbol( fn.GetFullPath(), symbolName ); - if( LoadOneLibraryPartAux( entry, fn.GetFullPath() ) ) + if( m_libMgr->PartExists( symbols[0], libName ) ) { - DisplayLibInfos(); - GetScreen()->ClearUndoRedoList(); - Zoom_Automatique( false ); - - // This effectively adds a new symbol to the library. Set the modified flag so the - // save library toolbar button and menu entry are enabled. - OnModify(); + msg.Printf( _( "Symbol '%s' already exists in library '%s'." ), symbolName, libName ); + DisplayError( this, msg ); + return; } + + m_libMgr->UpdatePart( entry->GetPart(), libName ); + loadPart( symbolName, libName, 1 ); } void LIB_EDIT_FRAME::OnExportPart( wxCommandEvent& event ) { - wxString msg, title; - bool createLib = ( event.GetId() == ExportPartId ) ? false : true; - - LIB_PART* part = GetCurPart(); + wxString msg, title; + LIB_PART* part = getTargetPart(); if( !part ) { @@ -114,9 +120,7 @@ void LIB_EDIT_FRAME::OnExportPart( wxCommandEvent& event ) fn.SetName( part->GetName().Lower() ); fn.SetExt( SchematicLibraryFileExtension ); - title = createLib ? _( "New Symbol Library" ) : _( "Export Symbol" ); - - wxFileDialog dlg( this, title, m_mruPath, fn.GetFullName(), + wxFileDialog dlg( this, _( "Export Symbol" ), m_mruPath, fn.GetFullName(), SchematicLibraryFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); if( dlg.ShowModal() == wxID_CANCEL ) @@ -179,12 +183,6 @@ void LIB_EDIT_FRAME::OnExportPart( wxCommandEvent& event ) } m_mruPath = fn.GetPath(); - - /// @todo Give the user a choice to add the new library to the symbol library table. - DisplayInfoMessage( this, _( "This library will not be available until it is added to the " - "symbol library table." ) ); - - GetScreen()->ClrModify(); m_drawItem = m_lastDrawItem = NULL; msg.Printf( _( "Symbol '%s' saved in library '%s'" ), part->GetName(), fn.GetFullPath() ); diff --git a/eeschema/lib_manager.cpp b/eeschema/lib_manager.cpp new file mode 100644 index 0000000000..072e71f248 --- /dev/null +++ b/eeschema/lib_manager.cpp @@ -0,0 +1,761 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2017 CERN + * @author Maciej Suminski + * + * 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 3 + * 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: + * https://www.gnu.org/licenses/gpl-3.0.html + * or you may search the http://www.gnu.org website for the version 3 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 + +#include +#include +#include +#include +#include + + +LIB_MANAGER::LIB_MANAGER( LIB_EDIT_FRAME& aFrame ) + : m_frame( aFrame ), m_symbolTable( aFrame.Prj().SchSymbolLibTable() ) +{ + m_adapter = LIB_MANAGER_ADAPTER::Create( this ); + m_adapter->ShowUnits( false ); +} + + +void LIB_MANAGER::Sync( bool aForce ) +{ + int libTableHash = m_symbolTable->GetModifyHash(); + + if( aForce || m_syncHash != libTableHash ) + { + getAdapter()->Sync( aForce ); + m_syncHash = libTableHash; + } +} + + +int LIB_MANAGER::GetHash() const +{ + int hash = m_symbolTable->GetModifyHash(); + + for( const auto& libBuf : m_libs ) + hash += libBuf.second.GetHash(); + + return hash; +} + + +int LIB_MANAGER::GetLibraryHash( const wxString& aLibrary ) const +{ + const auto libBufIt = m_libs.find( aLibrary ); + + if( libBufIt != m_libs.end() ) + return libBufIt->second.GetHash(); + + auto row = m_symbolTable->FindRow( aLibrary ); + + // return -1 if library does not exist or 0 if not modified + return row ? std::hash{}( aLibrary.ToStdString() + row->GetFullURI( true ).ToStdString() ) : -1; +} + + +wxArrayString LIB_MANAGER::GetLibraryNames() const +{ + wxArrayString res; + + for( const auto& libName : m_symbolTable->GetLogicalLibs() ) + res.Add( libName ); + + return res; +} + + +bool LIB_MANAGER::FlushAll() +{ + bool result = true; + + for( auto& libBuf : m_libs ) + result &= FlushLibrary( libBuf.first ); + + return result; +} + + +bool LIB_MANAGER::FlushLibrary( const wxString& aLibrary ) +{ + auto it = m_libs.find( aLibrary ); + + if( it == m_libs.end() ) // no changes to flush + return true; + + LIB_BUFFER& libBuf = it->second; + wxArrayString aliases; + + try { + m_symbolTable->EnumerateSymbolLib( aLibrary, aliases ); + + // TODO probably this could be implemented more efficiently + for( const auto& alias : aliases ) + m_symbolTable->DeleteAlias( aLibrary, alias ); + } catch( IO_ERROR& e) {} + + // Assume all libraries are successfully saved + bool res = true; + + for( const auto& partBuf : libBuf.GetBuffers() ) + { + if( !libBuf.SaveBuffer( partBuf, m_symbolTable ) ) + { + // Something went wrong but try to save other libraries + res = false; + } + } + + if( res ) + libBuf.ClearDeletedBuffer(); + + return res; +} + + +bool LIB_MANAGER::SaveLibrary( const wxString& aLibrary, const wxString& aFileName ) +{ + wxCHECK( LibraryExists( aLibrary ), false ); + wxFileName fn( aFileName ); + wxCHECK( !fn.FileExists() || fn.IsFileWritable(), false ); + SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_LEGACY ) ); + bool res = true; // assume all libraries are successfully saved + + auto it = m_libs.find( aLibrary ); + + if( it != m_libs.end() ) + { + // Handle buffered library + LIB_BUFFER& libBuf = it->second; + + const auto& partBuffers = libBuf.GetBuffers(); + + for( const auto& partBuf : partBuffers ) + { + if( !libBuf.SaveBuffer( partBuf, &*pi, true ) ) + { + // Something went wrong, but try to save other libraries + res = false; + } + } + + // clear the deleted parts buffer only if data is saved to the original file + auto row = m_symbolTable->FindRow( aLibrary ); + + if( res && row && row->GetFullURI( true ) == aFileName ) + libBuf.ClearDeletedBuffer(); + } + else + { + // Handle original library + PROPERTIES properties; + properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" ); + + for( auto part : getOriginalParts( aLibrary ) ) + pi->SaveSymbol( aLibrary, new LIB_PART( *part ), &properties ); + } + + pi->SaveLibrary( aFileName ); + return res; +} + + +bool LIB_MANAGER::IsLibraryModified( const wxString& aLibrary ) const +{ + wxCHECK( LibraryExists( aLibrary ), false ); + auto it = m_libs.find( aLibrary ); + return it != m_libs.end() ? it->second.IsModified() : false; +} + + +bool LIB_MANAGER::IsPartModified( const wxString& aAlias, const wxString& aLibrary ) const +{ + wxCHECK( LibraryExists( aLibrary ), false ); + auto libIt = m_libs.find( aLibrary ); + + if( libIt == m_libs.end() ) + return false; + + const LIB_BUFFER& buf = libIt->second; + auto partBuf = buf.GetBuffer( aAlias ); + return partBuf ? partBuf->IsModified() : false; +} + + +bool LIB_MANAGER::ClearLibraryModified( const wxString& aLibrary ) const +{ + auto libIt = m_libs.find( aLibrary ); + + if( libIt == m_libs.end() ) + return false; + + for( auto& partBuf : libIt->second.GetBuffers() ) + { + SCH_SCREEN* screen = partBuf->GetScreen(); + + if( screen ) + screen->ClrModify(); + } + + return true; +} + + +bool LIB_MANAGER::ClearPartModified( const wxString& aAlias, const wxString& aLibrary ) const +{ + auto libI = m_libs.find( aLibrary ); + + if( libI == m_libs.end() ) + return false; + + auto partBuf = libI->second.GetBuffer( aAlias ); + wxCHECK( partBuf, false ); + + partBuf->GetScreen()->ClrModify(); + return true; +} + + +bool LIB_MANAGER::IsLibraryReadOnly( const wxString& aLibrary ) const +{ + wxCHECK( LibraryExists( aLibrary ), true ); + wxFileName fn( m_symbolTable->GetFullURI( aLibrary ) ); + return ( fn.FileExists() && !fn.IsFileWritable() ) || !fn.IsDirWritable(); +} + + +wxArrayString LIB_MANAGER::GetAliasNames( const wxString& aLibrary ) const +{ + wxArrayString names; + wxCHECK( LibraryExists( aLibrary ), names ); + + auto it = m_libs.find( aLibrary ); + + if( it == m_libs.end() ) + { + try { + m_symbolTable->EnumerateSymbolLib( aLibrary, names ); + } catch( IO_ERROR& e ) {} + } + else + { + names = it->second.GetAliasNames(); + } + + return names; +} + + +std::list LIB_MANAGER::GetAliases( const wxString& aLibrary ) const +{ + std::list ret; + wxCHECK( LibraryExists( aLibrary ), ret ); + + auto libIt = m_libs.find( aLibrary ); + + if( libIt != m_libs.end() ) + { + for( auto& partBuf : libIt->second.GetBuffers() ) + { + for( unsigned int i = 0; i < partBuf->GetPart()->GetAliasCount(); ++i ) + ret.push_back( partBuf->GetPart()->GetAlias( i ) ); + } + } + else + { + wxArrayString symbols; + + try { + m_symbolTable->EnumerateSymbolLib( aLibrary, symbols ); + + for( const auto& symbol : symbols ) + ret.push_back( m_symbolTable->LoadSymbol( aLibrary, symbol ) ); + } catch( IO_ERROR& e ) {} + } + + return ret; +} + + +LIB_PART* LIB_MANAGER::GetBufferedPart( const wxString& aAlias, const wxString& aLibrary ) +{ + wxCHECK( LibraryExists( aLibrary ), nullptr ); + + // try the library buffers first + LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary ); + LIB_PART* bufferedPart = libBuf.GetPart( aAlias ); + + if( !bufferedPart ) // no buffer part found + { + // create a copy of the part + try { + LIB_ALIAS* alias = m_symbolTable->LoadSymbol( aLibrary, aAlias ); + wxCHECK( alias, nullptr ); + bufferedPart = new LIB_PART( *alias->GetPart(), nullptr ); + libBuf.CreateBuffer( bufferedPart, new SCH_SCREEN( &m_frame.Kiway() ) ); + } catch( IO_ERROR& e ) {} + } + + return bufferedPart; +} + + +SCH_SCREEN* LIB_MANAGER::GetScreen( const wxString& aAlias, const wxString& aLibrary ) +{ + wxCHECK( LibraryExists( aLibrary ), nullptr ); + wxCHECK( !aAlias.IsEmpty(), nullptr ); + auto it = m_libs.find( aLibrary ); + wxCHECK( it != m_libs.end(), nullptr ); + + LIB_BUFFER& buf = it->second; + auto partBuf = buf.GetBuffer( aAlias ); + return partBuf ? partBuf->GetScreen() : nullptr; +} + + +bool LIB_MANAGER::UpdatePart( LIB_PART* aPart, const wxString& aLibrary, wxString aOldName ) +{ + wxCHECK( LibraryExists( aLibrary ), false ); + wxCHECK( aPart, false ); + const wxString partName = aOldName.IsEmpty() ? aPart->GetName() : aOldName; + LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary ); + auto partBuf = libBuf.GetBuffer( partName ); + LIB_PART* partCopy = new LIB_PART( *aPart, nullptr ); + + if( partBuf ) + { + libBuf.UpdateBuffer( partBuf, partCopy ); + } + else // New entry + { + SCH_SCREEN* screen = new SCH_SCREEN( &m_frame.Kiway() ); + libBuf.CreateBuffer( partCopy, screen ); + screen->SetModify(); + } + + getAdapter()->UpdateLibrary( aLibrary ); + + return true; +} + + +bool LIB_MANAGER::FlushPart( const wxString& aAlias, const wxString& aLibrary ) +{ + auto it = m_libs.find( aLibrary ); + + if( it == m_libs.end() ) // no items to flush + return true; + + auto partBuf = it->second.GetBuffer( aAlias ); + wxCHECK( partBuf, false ); + + return it->second.SaveBuffer( partBuf, m_symbolTable ); +} + + +bool LIB_MANAGER::RevertPart( const wxString& aAlias, const wxString& aLibrary ) +{ + auto it = m_libs.find( aLibrary ); + + if( it == m_libs.end() ) // no items to flush + return true; + + auto partBuf = it->second.GetBuffer( aAlias ); + wxCHECK( partBuf, false ); + partBuf->SetPart( new LIB_PART( *partBuf->GetOriginal() ) ); + + return true; +} + + +bool LIB_MANAGER::RevertLibrary( const wxString& aLibrary ) +{ + auto it = m_libs.find( aLibrary ); + + if( it == m_libs.end() ) // nothing to reverse + return false; + + m_libs.erase( it ); + getAdapter()->UpdateLibrary( aLibrary ); + + return true; +} + + +bool LIB_MANAGER::RemovePart( const wxString& aAlias, const wxString& aLibrary ) +{ + LIB_BUFFER& libBuf = getLibraryBuffer( aLibrary ); + auto partBuf = libBuf.GetBuffer( aAlias ); + wxCHECK( partBuf, false ); + + bool res = libBuf.DeleteBuffer( partBuf ); + getAdapter()->UpdateLibrary( aLibrary ); + + return res; +} + + +LIB_ALIAS* LIB_MANAGER::GetAlias( const wxString& aAlias, const wxString& aLibrary ) const +{ + // Try the library buffers first + auto libIt = m_libs.find( aLibrary ); + + if( libIt != m_libs.end() ) + { + LIB_PART* part = libIt->second.GetPart( aAlias ); + + if( part ) + return part->GetAlias( aAlias ); + } + + // Get the original part + LIB_ALIAS* alias = nullptr; + + try { + alias = m_symbolTable->LoadSymbol( aLibrary, aAlias ); + } catch( IO_ERROR& e ) {} + + return alias; +} + + +bool LIB_MANAGER::PartExists( const wxString& aAlias, const wxString& aLibrary ) const +{ + auto libBufIt = m_libs.find( aLibrary ); + LIB_ALIAS* alias = nullptr; + + if( libBufIt != m_libs.end() ) + return !!libBufIt->second.GetBuffer( aAlias ); + + try { + alias = m_symbolTable->LoadSymbol( aLibrary, aAlias ); + } catch( IO_ERROR& e ) {} + + return alias != nullptr; +} + + +bool LIB_MANAGER::LibraryExists( const wxString& aLibrary ) const +{ + if( aLibrary.IsEmpty() ) + return false; + + if( m_libs.count( aLibrary ) > 0 ) + return true; + + return m_symbolTable->HasLibrary( aLibrary ); +} + + +wxString LIB_MANAGER::ValidateName( const wxString& aName ) +{ + wxString name( aName ); + name.Replace( " ", "_" ); + return name; +} + + +wxString LIB_MANAGER::GetUniqueLibraryName() const +{ + wxString name = "New_Library"; + + if( !LibraryExists( name ) ) + return name; + + name += "_"; + + for( unsigned int i = 0; i < std::numeric_limits::max(); ++i ) + { + if( !LibraryExists( name + wxString::Format( "%u", i ) ) ) + return name + wxString::Format( "%u", i ); + } + + wxFAIL; + return wxEmptyString; +} + + +wxString LIB_MANAGER::GetUniqueComponentName( const wxString& aLibrary ) const +{ + wxString name = "New_Component"; + + if( !PartExists( name, aLibrary ) ) + return name; + + name += "_"; + + for( unsigned int i = 0; i < std::numeric_limits::max(); ++i ) + { + if( !PartExists( name + wxString::Format( "%u", i ), aLibrary ) ) + return name + wxString::Format( "%u", i ); + } + + wxFAIL; + return wxEmptyString; +} + + +wxString LIB_MANAGER::getLibraryName( const wxString& aFilePath ) +{ + wxFileName fn( aFilePath ); + return fn.GetName(); +} + + +bool LIB_MANAGER::addLibrary( const wxString& aFilePath, bool aCreate ) +{ + wxString libName = getLibraryName( aFilePath ); + wxCHECK( !LibraryExists( libName ), false ); // either create or add an existing one + + // Select the target library table (global/project) + SYMBOL_LIB_TABLE* libTable = m_frame.SelectSymLibTable(); + wxCHECK( libTable, false ); + + SYMBOL_LIB_TABLE_ROW* libRow = new SYMBOL_LIB_TABLE_ROW( libName, aFilePath, + SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_LEGACY ) ); + libTable->InsertRow( libRow ); + + if( aCreate ) + libTable->CreateSymbolLib( libName ); + + getAdapter()->AddLibrary( libName ); + + return true; +} + + +std::set LIB_MANAGER::getOriginalParts( const wxString& aLibrary ) +{ + std::set parts; + wxCHECK( LibraryExists( aLibrary ), parts ); + + try { + wxArrayString aliases; + m_symbolTable->EnumerateSymbolLib( aLibrary, aliases ); + + for( const auto& aliasName : aliases ) + { + LIB_ALIAS* alias = m_symbolTable->LoadSymbol( aLibrary, aliasName ); + parts.insert( alias->GetPart() ); + } + } catch( IO_ERROR& e ) {} + + return parts; +} + + +LIB_MANAGER::LIB_BUFFER& LIB_MANAGER::getLibraryBuffer( const wxString& aLibrary ) +{ + auto it = m_libs.find( aLibrary ); + + if( it != m_libs.end() ) + return it->second; + + auto ret = m_libs.emplace( aLibrary, LIB_BUFFER( aLibrary ) ); + LIB_BUFFER& buf = ret.first->second; + + for( auto part : getOriginalParts( aLibrary ) ) + buf.CreateBuffer( new LIB_PART( *part, nullptr ), new SCH_SCREEN( &m_frame.Kiway() ) ); + + return buf; +} + + +LIB_MANAGER::PART_BUFFER::PART_BUFFER( LIB_PART* aPart, SCH_SCREEN* aScreen ) + : m_screen( aScreen ), m_part( aPart ) +{ + m_original = new LIB_PART( *aPart ); +} + + +LIB_MANAGER::PART_BUFFER::~PART_BUFFER() +{ + delete m_screen; + delete m_part; + delete m_original; +} + + +void LIB_MANAGER::PART_BUFFER::SetPart( LIB_PART* aPart ) +{ + wxCHECK( m_part != aPart, /* void */ ); + wxASSERT( aPart ); + delete m_part; + m_part = aPart; +} + + +void LIB_MANAGER::PART_BUFFER::SetOriginal( LIB_PART* aPart ) +{ + wxCHECK( m_original != aPart, /* void */ ); + wxASSERT( aPart ); + delete m_original; + m_original = aPart; +} + + +bool LIB_MANAGER::PART_BUFFER::IsModified() const +{ + return m_screen && m_screen->IsModify(); +} + + +wxArrayString LIB_MANAGER::LIB_BUFFER::GetAliasNames() const +{ + wxArrayString ret; + + for( const auto& alias : m_aliases ) + ret.push_back( alias.first ); + + return ret; +} + + +bool LIB_MANAGER::LIB_BUFFER::CreateBuffer( LIB_PART* aCopy, SCH_SCREEN* aScreen ) +{ + wxASSERT( m_aliases.count( aCopy->GetName() ) == 0 ); // only for new parts + wxASSERT( aCopy->GetLib() == nullptr ); + auto partBuf = std::make_shared( aCopy, aScreen ); + m_parts.push_back( partBuf ); + addAliases( partBuf ); + + // Set the parent library name, + // otherwise it is empty as no library has been given as the owner during object construction + LIB_ID& libId = (LIB_ID&) aCopy->GetLibId(); + libId.SetLibNickname( m_libName ); + ++m_hash; + + return true; +} + + +bool LIB_MANAGER::LIB_BUFFER::UpdateBuffer( LIB_MANAGER::PART_BUFFER::PTR aPartBuf, LIB_PART* aCopy ) +{ + bool ret = true; + + ret &= removeAliases( aPartBuf ); + aPartBuf->SetPart( aCopy ); + ret &= addAliases( aPartBuf ); + ++m_hash; + + return ret; +} + + +bool LIB_MANAGER::LIB_BUFFER::DeleteBuffer( LIB_MANAGER::PART_BUFFER::PTR aPartBuf ) +{ + auto partBufIt = std::find( m_parts.begin(), m_parts.end(), aPartBuf ); + wxCHECK( partBufIt != m_parts.end(), false ); + m_deleted.emplace_back( *partBufIt ); + m_parts.erase( partBufIt ); + ++m_hash; + + return removeAliases( aPartBuf ); +} + + +bool LIB_MANAGER::LIB_BUFFER::SaveBuffer( LIB_MANAGER::PART_BUFFER::PTR aPartBuf, + SYMBOL_LIB_TABLE* aLibTable ) +{ + wxCHECK( aPartBuf, false ); + LIB_PART* part = aPartBuf->GetPart(); + wxCHECK( part, false ); + wxCHECK( aLibTable->SaveSymbol( m_libName, new LIB_PART( *part ) ) == SYMBOL_LIB_TABLE::SAVE_OK, false ); + + aPartBuf->SetOriginal( new LIB_PART( *part ) ); + ++m_hash; + return true; +} + + +bool LIB_MANAGER::LIB_BUFFER::SaveBuffer( LIB_MANAGER::PART_BUFFER::PTR aPartBuf, + SCH_PLUGIN* aPlugin, bool aBuffer ) +{ + wxCHECK( aPartBuf, false ); + LIB_PART* part = aPartBuf->GetPart(); + wxCHECK( part, false ); + + // set properties to prevent save file on every symbol save + PROPERTIES properties; + properties.emplace( SCH_LEGACY_PLUGIN::PropBuffering, "" ); + + // TODO there is no way to check if symbol has been successfully saved + aPlugin->SaveSymbol( m_libName, new LIB_PART( *part ), aBuffer ? &properties : nullptr ); + aPartBuf->SetOriginal( new LIB_PART( *part ) ); + ++m_hash; + return true; +} + + +bool LIB_MANAGER::LIB_BUFFER::addAliases( PART_BUFFER::PTR aPartBuf ) +{ + LIB_PART* part = aPartBuf->GetPart(); + wxCHECK( part, false ); + bool ret = true; // Assume everything is ok + + for( unsigned int i = 0; i < part->GetAliasCount(); ++i ) + { + bool newAlias; + std::tie( std::ignore, newAlias ) = m_aliases.emplace( part->GetAlias( i )->GetName(), aPartBuf ); + + if( !newAlias ) // Overwrite check + { + wxFAIL; + ret = false; + } + } + + return ret; +} + + +bool LIB_MANAGER::LIB_BUFFER::removeAliases( PART_BUFFER::PTR aPartBuf ) +{ + LIB_PART* part = aPartBuf->GetPart(); + wxCHECK( part, false ); + bool ret = true; // Assume everything is ok + + for( unsigned int i = 0; i < part->GetAliasCount(); ++i ) + { + auto aliasIt = m_aliases.find( part->GetAlias( i )->GetName() ); + + if( aliasIt == m_aliases.end() ) + { + wxFAIL; + ret = false; + continue; + } + + // Be sure the alias belongs to the assigned owner + wxASSERT( aliasIt->second.lock() == aPartBuf ); + + m_aliases.erase( aliasIt ); + } + + return ret; +} diff --git a/eeschema/lib_manager.h b/eeschema/lib_manager.h new file mode 100644 index 0000000000..2b82eda263 --- /dev/null +++ b/eeschema/lib_manager.h @@ -0,0 +1,430 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2017 CERN + * @author Maciej Suminski + * + * 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 3 + * 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: + * https://www.gnu.org/licenses/gpl-3.0.html + * or you may search the http://www.gnu.org website for the version 3 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef LIB_MANAGER_H +#define LIB_MANAGER_H + +#include +#include +#include +#include +#include +#include +#include + +class LIB_ALIAS; +class LIB_PART; +class LIB_BUFFER; +class PART_LIB; +class SCH_SCREEN; +class SCH_PLUGIN; +class LIB_EDIT_FRAME; +class SYMBOL_LIB_TABLE; + +/** + * Class to handle modifications to the symbol libraries. + */ +class LIB_MANAGER +{ +public: + LIB_MANAGER( LIB_EDIT_FRAME& aFrame ); + + /** + * Updates the LIB_MANAGER data to synchronize with Symbol Library Table. + */ + void Sync( bool aForce = false ); + + int GetHash() const; + + /** + * Retruns a library hash value to determine if it has changed. + * + * For buffered libraries, it returns a number corresponding to the number + * of modifications. For original libraries, hash is computed basing on the + * library URI. Returns -1 when the requested library does not exist. + */ + int GetLibraryHash( const wxString& aLibrary ) const; + + /** + * Returns the array of library names. + */ + wxArrayString GetLibraryNames() const; + + /** + * Returns a set containing all part names for a specific library. + */ + wxArrayString GetAliasNames( const wxString& aLibrary ) const; + + std::list GetAliases( const wxString& aLibrary ) const; + + /** + * Creates an empty library and adds it to the library table. The library file is created. + */ + bool CreateLibrary( const wxString& aFilePath ) + { + return addLibrary( aFilePath, true ); + } + + /** + * Adds an existing library. The library is added to the library table as well. + */ + bool AddLibrary( const wxString& aFilePath ) + { + return addLibrary( aFilePath, false ); + } + + /** + * Updates the part buffer with a new version of the part. + * The library buffer creates a copy of the part. + * It is required to save the library to use the updated part in the schematic editor. + */ + bool UpdatePart( LIB_PART* aPart, const wxString& aLibrary, wxString aOldName = wxEmptyString ); + + /** + * Removes the part from the part buffer. + * It is required to save the library to have the part removed in the schematic editor. + */ + bool RemovePart( const wxString& aName, const wxString& aLibrary ); + + /** + * Returns either an alias of a working LIB_PART copy, or alias of the original part if there + * is no working copy. + */ + LIB_ALIAS* GetAlias( const wxString& aAlias, const wxString& aLibrary ) const; + + /** + * Returns the part copy from the buffer. In case it does not exist yet, the copy is created. + * LIB_MANAGER retains the ownership. + */ + LIB_PART* GetBufferedPart( const wxString& aAlias, const wxString& aLibrary ); + + /** + * Returns the screen used to edit a specific part. LIB_MANAGER retains the ownership. + */ + SCH_SCREEN* GetScreen( const wxString& aAlias, const wxString& aLibrary ); + + /** + * Returns true if part with a specific alias exists in library (either original one or buffered). + */ + bool PartExists( const wxString& aAlias, const wxString& aLibrary ) const; + + /** + * Returns true if library exists. + */ + bool LibraryExists( const wxString& aLibrary ) const; + + /** + * Returns true if library has unsaved modifications. + */ + bool IsLibraryModified( const wxString& aLibrary ) const; + + /** + * Returns true if part has unsaved modifications. + */ + bool IsPartModified( const wxString& aAlias, const wxString& aLibrary ) const; + + /** + * Clears the modified flag for all parts in a library. + */ + bool ClearLibraryModified( const wxString& aLibrary ) const; + + /** + * Clears the modified flag for a part. + */ + bool ClearPartModified( const wxString& aAlias, const wxString& aLibrary ) const; + + /** + * Returns true if the library is stored in a read-only file. + * @return True on success, false otherwise. + */ + bool IsLibraryReadOnly( const wxString& aLibrary ) const; + + /** + * Saves part changes to the library copy used by the schematic editor. Not it is not + * necessarily saved to the file. + * @return True on success, false otherwise. + */ + bool FlushPart( const wxString& aAlias, const wxString& aLibrary ); + + /** + * Saves changes to the library copy used by the schematic editor. Note it is not + * necessarily saved to the file. + * @param aLibrary is the library name. + * @return True on success, false otherwise. + */ + bool FlushLibrary( const wxString& aLibrary ); + + /** + * Saves library to a file, including unsaved changes. + * @param aLibrary is the library name. + * @param aFileName is the target file name. + * @return True on success, false otherwise. + */ + bool SaveLibrary( const wxString& aLibrary, const wxString& aFileName ); + + /** + * Saves all changes to libraries. + * @return True if all changes have been flushed successfully, false otherwise. + */ + bool FlushAll(); + + /** + * Reverts unsaved changes for a particular part. + * @return True on success, false otherwise. + */ + bool RevertPart( const wxString& aAlias, const wxString& aLibrary ); + + /** + * Reverts unsaved changes for a particular library. + * @return True on success, false otherwise. + */ + bool RevertLibrary( const wxString& aLibrary ); + + /** + * Replaces all characters considered illegal in library/part names with underscores. + */ + static wxString ValidateName( const wxString& aName ); + + /** + * Returns a library name that is not currently in use. + * Used for generating names for new libraries. + */ + wxString GetUniqueLibraryName() const; + + /** + * Returns a component name that is not stored in a library. + * Used for generating names for new components. + */ + wxString GetUniqueComponentName( const wxString& aLibrary ) const; + + /** + * Returns the adapter object that provides the stored data. + */ + CMP_TREE_MODEL_ADAPTER_BASE::PTR& GetAdapter() { return m_adapter; } + + /** + * Returns the currently modified library name. + */ + const wxString& GetCurrentLib() const + { + return m_currentLib; + } + + /** + * Sets the currently modified library name. + */ + void SetCurrentLib( const wxString& aLibrary ) + { + m_currentLib = aLibrary; + } + + /** + * Returns the currently modified part name. + */ + const wxString& GetCurrentPart() const + { + return m_currentPart; + } + + /** + * Sets the currently modified part name. + */ + void SetCurrentPart( const wxString& aPart ) + { + m_currentPart = aPart; + } + + /** + * Returns the current library and part name as LIB_ID. + */ + LIB_ID GetCurrentLibId() const + { + return LIB_ID( m_currentLib, m_currentPart ); + } + +private: + ///> Parent frame + LIB_EDIT_FRAME& m_frame; + + ///> Extracts library name basing on the file name + static wxString getLibraryName( const wxString& aFilePath ); + + ///> Helper function to add either existing or create new library + bool addLibrary( const wxString& aFilePath, bool aCreate ); + + SYMBOL_LIB_TABLE* m_symbolTable; + + ///> Class to store a working copy of a LIB_PART object and editor context. + class PART_BUFFER + { + public: + PART_BUFFER( LIB_PART* aPart = nullptr, SCH_SCREEN* aScreen = nullptr ); + ~PART_BUFFER(); + + LIB_PART* GetPart() const { return m_part; } + void SetPart( LIB_PART* aPart ); + + LIB_PART* GetOriginal() const { return m_original; } + void SetOriginal( LIB_PART* aPart ); + + bool IsModified() const; + SCH_SCREEN* GetScreen() const { return m_screen; } + + typedef std::shared_ptr PTR; + typedef std::weak_ptr WEAK_PTR; + + private: + SCH_SCREEN* m_screen; + + ///> Working copy + LIB_PART* m_part; + + ///> Initial state of the part + LIB_PART* m_original; + }; + + + ///> Class to store a working copy of a library + class LIB_BUFFER + { + public: + LIB_BUFFER( const wxString& aLibrary ) + : m_libName( aLibrary ), m_hash( 1 ) + { + } + + bool IsModified() const + { + if( !m_deleted.empty() ) + return true; + + for( const auto& partBuf : m_parts ) + { + if( partBuf->IsModified() ) + return true; + } + + return false; + } + + int GetHash() const + { + return m_hash; + } + + ///> Returns all alias names for stored parts + wxArrayString GetAliasNames() const; + + ///> Returns the working copy of a LIB_PART object with specified alias + LIB_PART* GetPart( const wxString& aAlias ) const + { + auto buf = GetBuffer( aAlias ); + return buf ? buf->GetPart() : nullptr; + } + + ///> Creates a new buffer to store a part. LIB_BUFFER takes ownership of aCopy. + bool CreateBuffer( LIB_PART* aCopy, SCH_SCREEN* aScreen ); + + ///> Updates the stored part. LIB_BUFFER takes ownership of aCopy. + bool UpdateBuffer( PART_BUFFER::PTR aPartBuf, LIB_PART* aCopy ); + + bool DeleteBuffer( PART_BUFFER::PTR aPartBuf ); + + void ClearDeletedBuffer() + { + m_deleted.clear(); + } + + ///> Saves stored modifications to Symbol Lib Table. It may result in saving the symbol + ///> to disk as well, depending on the row properties. + bool SaveBuffer( PART_BUFFER::PTR aPartBuf, SYMBOL_LIB_TABLE* aLibTable ); + + ///> Saves stored modificatiosn using a plugin. aBuffer decides whether the changes + ///> should be cached or stored directly to the disk (for SCH_LEGACY_PLUGIN). + bool SaveBuffer( PART_BUFFER::PTR aPartBuf, SCH_PLUGIN* aPlugin, bool aBuffer ); + + ///> Returns a part buffer with LIB_PART holding a particular alias + PART_BUFFER::PTR GetBuffer( const wxString& aAlias ) const + { + auto it = m_aliases.find( aAlias ); + return it != m_aliases.end() ? it->second.lock() : PART_BUFFER::PTR( nullptr ); + } + + ///> Returns all buffered parts + const std::deque& GetBuffers() const + { + return m_parts; + } + + ///> Returns all aliases of buffered parts + const std::map& GetAliases() const + { + return m_aliases; + } + + private: + ///> Creates alias entries for a particular part buffer + bool addAliases( PART_BUFFER::PTR aPartBuf ); + + ///> Removes alias entries for a particular part buffer + bool removeAliases( PART_BUFFER::PTR aPartBuf ); + + std::map m_aliases; + std::deque m_parts; + + ///> Buffer to keep deleted parts until the library is saved + std::deque m_deleted; + + /// Buffered library name + const wxString m_libName; + + int m_hash; + + friend class PART_BUFFER; + }; + + ///> Returns a set of LIB_PART objects belonging to the original library + std::set getOriginalParts( const wxString& aLibrary ); + + ///> Returns an existing library buffer or creates one to using + ///> Symbol Library Table to get the original data. + LIB_BUFFER& getLibraryBuffer( const wxString& aLibrary ); + + ///> The library buffers + std::map m_libs; + + ///> Symbol Lib Table hash value returned during the last synchronization + int m_syncHash; + + ///> Currently modified part + wxString m_currentLib; + + ///> Currently modified library + wxString m_currentPart; + + LIB_MANAGER_ADAPTER::PTR m_adapter; + LIB_MANAGER_ADAPTER* getAdapter() { return static_cast( m_adapter.get() ); } +}; + +#endif /* LIB_MANAGER_H */ diff --git a/eeschema/lib_manager_adapter.cpp b/eeschema/lib_manager_adapter.cpp new file mode 100644 index 0000000000..7dca13b50a --- /dev/null +++ b/eeschema/lib_manager_adapter.cpp @@ -0,0 +1,253 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2017 CERN + * @author Maciej Suminski + * + * 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 3 + * 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: + * https://www.gnu.org/licenses/gpl-3.0.html + * or you may search the http://www.gnu.org website for the version 3 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include + + +CMP_TREE_MODEL_ADAPTER_BASE::PTR LIB_MANAGER_ADAPTER::Create( LIB_MANAGER* aLibMgr ) +{ + auto adapter = new LIB_MANAGER_ADAPTER( aLibMgr ); + auto container = CMP_TREE_MODEL_ADAPTER_BASE::PTR( adapter ); + return container; +} + + +void LIB_MANAGER_ADAPTER::AddLibrary( const wxString& aLibNickname ) +{ + auto& lib_node = m_tree.AddLib( aLibNickname ); + ItemAdded( wxDataViewItem( nullptr ), ToItem( &lib_node ) ); + updateLibrary( lib_node ); + finishUpdate(); +} + + +void LIB_MANAGER_ADAPTER::RemoveLibrary( const wxString& aLibNickname ) +{ + auto it = std::find_if( m_tree.Children.begin(), m_tree.Children.end(), + [&] ( std::unique_ptr& node ) { return node->Name == aLibNickname; } ); + + if( it != m_tree.Children.end() ) + deleteLibrary( it ); +} + + +void LIB_MANAGER_ADAPTER::UpdateLibrary( const wxString& aLibraryName ) +{ + CMP_TREE_NODE* node = findLibrary( aLibraryName ); + + if( !node ) + return; + + updateLibrary( *(CMP_TREE_NODE_LIB*) node ); + finishUpdate(); +} + + +void LIB_MANAGER_ADAPTER::AddAliasList( const wxString& aNodeName, + const wxArrayString& aAliasNameList ) +{ + wxASSERT( false ); // TODO +} + + +bool LIB_MANAGER_ADAPTER::IsContainer( const wxDataViewItem& aItem ) const +{ + const CMP_TREE_NODE* node = ToNode( aItem ); + return node ? node->Type == CMP_TREE_NODE::LIB : true; +} + + +void LIB_MANAGER_ADAPTER::Sync( bool aForce ) +{ + wxBusyCursor cursor; + int libMgrHash = m_libMgr->GetHash(); + + if( !aForce && m_lastSyncHash == libMgrHash ) + return; + + m_lastSyncHash = libMgrHash; + + // Process already stored libraries + for( auto it = m_tree.Children.begin(); it != m_tree.Children.end(); /* iteration inside */ ) + { + const wxString& name = it->get()->Name; + + if( !m_libMgr->LibraryExists( name ) ) + { + it = deleteLibrary( it ); + continue; + } + else if( m_libMgr->GetLibraryHash( name ) != m_libHashes[name] ) + { + updateLibrary( *(CMP_TREE_NODE_LIB*) it->get() ); + } + + ++it; + } + + // Look for new libraries + for( const auto& libName : m_libMgr->GetLibraryNames() ) + { + if( m_libHashes.count( libName ) == 0 ) + AddLibrary( libName ); + } + + finishUpdate(); +} + + +void LIB_MANAGER_ADAPTER::updateLibrary( CMP_TREE_NODE_LIB& aLibNode ) +{ + if( m_libHashes.count( aLibNode.Name ) == 0 ) + { + // add a new library + wxDataViewItem parent = ToItem( &aLibNode ); + + for( auto alias : m_libMgr->GetAliases( aLibNode.Name ) ) + { + auto& aliasNode = aLibNode.AddAlias( alias ); + ItemAdded( parent, ToItem( &aliasNode ) ); + } + } + else + { + // update an existing libary + std::list aliases = m_libMgr->GetAliases( aLibNode.Name ); + wxDataViewItem parent = ToItem( &aLibNode ); + + // remove the common part from the aliases list + //for( const auto& node : aLibNode.Children ) + for( auto nodeIt = aLibNode.Children.begin(); nodeIt != aLibNode.Children.end(); /**/ ) + { + auto aliasIt = std::find_if( aliases.begin(), aliases.end(), + [&] ( const LIB_ALIAS* a ) { + return a->GetName() == (*nodeIt)->Name; + } ); + + if( aliasIt != aliases.end() ) + { + // alias exists both in the component tree and the library manager, + // no need to update + aliases.erase( aliasIt ); + ++nodeIt; + } + else + { + // node does not exist in the library manager, remove the corresponding node + ItemDeleted( parent, ToItem( nodeIt->get() ) ); + nodeIt = aLibNode.Children.erase( nodeIt ); + } + } + + // now the aliases list contains only new aliases that need to be added to the tree + for( auto alias : aliases ) + { + auto& aliasNode = aLibNode.AddAlias( alias ); + ItemAdded( parent, ToItem( &aliasNode ) ); + } + } + + aLibNode.AssignIntrinsicRanks(); + m_libHashes[aLibNode.Name] = m_libMgr->GetLibraryHash( aLibNode.Name ); +} + + +CMP_TREE_NODE::PTR_VECTOR::iterator LIB_MANAGER_ADAPTER::deleteLibrary( + CMP_TREE_NODE::PTR_VECTOR::iterator& aLibNodeIt ) +{ + CMP_TREE_NODE* node = aLibNodeIt->get(); + ItemDeleted( wxDataViewItem( nullptr ), ToItem( node ) ); + m_libHashes.erase( node->Name ); + auto it = m_tree.Children.erase( aLibNodeIt ); + return it; +} + + +void LIB_MANAGER_ADAPTER::finishUpdate() +{ + m_tree.AssignIntrinsicRanks(); +} + + +CMP_TREE_NODE* LIB_MANAGER_ADAPTER::findLibrary( const wxString& aLibNickName ) +{ + for( auto& lib : m_tree.Children ) + { + if( lib->Name == aLibNickName ) + return lib.get(); + } + + return nullptr; +} + + +bool LIB_MANAGER_ADAPTER::GetAttr( wxDataViewItem const& aItem, unsigned int aCol, + wxDataViewItemAttr& aAttr ) const +{ + // change attributes only for the name field + if( aCol != 0 ) + return false; + + auto node = ToNode( aItem ); + wxCHECK( node, false ); + + switch( node->Type ) + { + case CMP_TREE_NODE::LIB: + // mark modified libs with bold font + aAttr.SetBold( m_libMgr->IsLibraryModified( node->Name ) ); + + // mark current library with inverted colors + if( node->Name == m_libMgr->GetCurrentLib() ) + aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) ); + + break; + + case CMP_TREE_NODE::LIBID: + // mark modified part with bold font + aAttr.SetBold( m_libMgr->IsPartModified( node->Name, node->Parent->Name ) ); + + // mark aliases with italic font + aAttr.SetItalic( !node->IsRoot ); + + // mark current library with inverted colors + if( node->LibId == m_libMgr->GetCurrentLibId() ) + aAttr.SetColour( wxSystemSettings::GetColour( wxSYS_COLOUR_HIGHLIGHT ) ); + + break; + + default: + return false; + } + + return true; +} + + +LIB_MANAGER_ADAPTER::LIB_MANAGER_ADAPTER( LIB_MANAGER* aLibMgr ) + : m_libMgr( aLibMgr ), m_lastSyncHash( -1 ) +{ +} diff --git a/eeschema/lib_manager_adapter.h b/eeschema/lib_manager_adapter.h new file mode 100644 index 0000000000..1485773f26 --- /dev/null +++ b/eeschema/lib_manager_adapter.h @@ -0,0 +1,74 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2017 CERN + * @author Maciej Suminski + * + * 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 3 + * 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: + * https://www.gnu.org/licenses/gpl-3.0.html + * or you may search the http://www.gnu.org website for the version 3 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef LIB_MANAGER_ADAPTER_H +#define LIB_MANAGER_ADAPTER_H + +#include +#include + +class LIB_MANAGER; + +class LIB_MANAGER_ADAPTER : public CMP_TREE_MODEL_ADAPTER_BASE +{ +public: + static PTR Create( LIB_MANAGER* aLibs ); + + void AddLibrary( const wxString& aLibNickname ) override; + + void RemoveLibrary( const wxString& aLibNickname ); + + void AddAliasList( const wxString& aNodeName, const wxArrayString& aAliasNameList ) override; + + bool IsContainer( const wxDataViewItem& aItem ) const override; + + void UpdateLibrary( const wxString& aLibraryName ); + + void Sync( bool aForce = false ); + +protected: + void updateLibrary( CMP_TREE_NODE_LIB& aLibNode ); + + CMP_TREE_NODE::PTR_VECTOR::iterator deleteLibrary( + CMP_TREE_NODE::PTR_VECTOR::iterator& aLibNodeIt ); + + void finishUpdate(); + + CMP_TREE_NODE* findLibrary( const wxString& aLibNickName ); + + bool GetAttr( wxDataViewItem const& aItem, unsigned int aCol, + wxDataViewItemAttr& aAttr ) const override; + + LIB_MANAGER_ADAPTER( LIB_MANAGER* aLibMgr ); + + LIB_MANAGER* m_libMgr; + + ///> Hashes to decide whether a library needs an update + std::map m_libHashes; + + ///> LIB_MANAGER hash value returned in the last synchronization + int m_lastSyncHash; +}; + +#endif /* LIB_MANAGER_ADAPTER_H */ diff --git a/eeschema/libedit.cpp b/eeschema/libedit.cpp index 853e34d150..ee779a7bdd 100644 --- a/eeschema/libedit.cpp +++ b/eeschema/libedit.cpp @@ -46,6 +46,9 @@ #include #include #include +#include +#include +#include #include #include @@ -64,7 +67,7 @@ void LIB_EDIT_FRAME::DisplayLibInfos() title += lib + " (" + fileName + ")"; - if( !wxFileName::IsFileWritable( fileName ) ) + if( wxFileName::FileExists( fileName ) && !wxFileName::IsFileWritable( fileName ) ) title += " " + _( "[Read Only]" ); } else @@ -140,54 +143,6 @@ bool LIB_EDIT_FRAME::LoadComponentFromCurrentLib( const wxString& aAliasName, in } -void LIB_EDIT_FRAME::LoadOneLibraryPart( wxCommandEvent& event ) -{ - m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor() ); - - if( GetScreen()->IsModify() - && !IsOK( this, _( "The current symbol is not saved.\n\nDiscard current changes?" ) ) ) - return; - - wxString lib = GetCurLib(); - - // No current lib, ask user for the library to use. - if( lib.empty() ) - { - SelectActiveLibrary(); - - lib = GetCurLib(); - - if( lib.empty() ) - return; - } - - // Get the name of the current part to preselect it - LIB_PART* current_part = GetCurPart(); - LIB_ID id; - - if( current_part ) - id = current_part->GetLibId(); - - SCH_BASE_FRAME::HISTORY_LIST dummyHistoryList; - SCHLIB_FILTER filter; - filter.LoadFrom( lib ); - auto sel = SelectComponentFromLibrary( &filter, dummyHistoryList, true, 0, 0, &id, false ); - - if( sel.LibId.GetLibItemName().empty() ) - return; - - GetScreen()->ClrModify(); - m_lastDrawItem = m_drawItem = NULL; - - // Delete previous library symbol, if any - SetCurPart( NULL ); - m_aliasName.Empty(); - - // Load the new library symbol - LoadComponentFromCurrentLib( sel.LibId.GetLibItemName(), sel.Unit, sel.Convert ); -} - - bool LIB_EDIT_FRAME::LoadOneLibraryPartAux( LIB_ALIAS* aEntry, const wxString& aLibrary ) { wxString msg, rootName; @@ -201,25 +156,19 @@ bool LIB_EDIT_FRAME::LoadOneLibraryPartAux( LIB_ALIAS* aEntry, const wxString& a return false; } - wxString cmpName = m_aliasName = aEntry->GetName(); - - LIB_PART* lib_part = aEntry->GetPart(); - - wxASSERT( lib_part ); - - LIB_PART* part = new LIB_PART( *lib_part ); // clone it and own it. - SetCurPart( part ); m_aliasName = aEntry->GetName(); + LIB_PART* lib_part = m_libMgr->GetBufferedPart( m_aliasName, aLibrary ); + wxASSERT( lib_part ); + SetScreen( m_libMgr->GetScreen( lib_part->GetName(), aLibrary ) ); + SetCurPart( new LIB_PART( *lib_part ) ); + SetCurLib( aLibrary ); + m_unit = 1; m_convert = 1; + SetShowDeMorgan( GetCurPart()->HasConversion() ); - m_showDeMorgan = false; - - if( part->HasConversion() ) - m_showDeMorgan = true; - - GetScreen()->ClrModify(); + Zoom_Automatique( false ); DisplayLibInfos(); UpdateAliasSelectList(); UpdatePartSelectList(); @@ -227,6 +176,7 @@ bool LIB_EDIT_FRAME::LoadOneLibraryPartAux( LIB_ALIAS* aEntry, const wxString& a // Display the document information based on the entry selected just in // case the entry is an alias. DisplayCmpDoc(); + Refresh(); return true; } @@ -282,13 +232,268 @@ void LIB_EDIT_FRAME::RedrawActiveWindow( wxDC* DC, bool EraseBg ) } -void LIB_EDIT_FRAME::OnSaveActiveLibrary( wxCommandEvent& event ) +void LIB_EDIT_FRAME::OnSaveLibrary( wxCommandEvent& event ) { - SaveActiveLibrary( event.GetId() == ID_LIBEDIT_SAVE_CURRENT_LIB_AS ); + saveLibrary( getTargetLib(), event.GetId() == ID_LIBEDIT_SAVE_LIBRARY_AS ); + m_treePane->Refresh(); } -bool LIB_EDIT_FRAME::SaveActiveLibrary( bool newFile ) +void LIB_EDIT_FRAME::OnSaveAllLibraries( wxCommandEvent& event ) +{ + saveAllLibraries(); +} + + +void LIB_EDIT_FRAME::OnRevertLibrary( wxCommandEvent& aEvent ) +{ + wxString libName = getTargetLib(); + bool currentLib = ( libName == GetCurLib() ); + + // Save the current part name/unit to reload after revert + wxString alias = m_aliasName; + int unit = m_unit; + + if( !IsOK( this, _( "The revert operation cannot be undone!\n\nRevert changes?" ) ) ) + return; + + if( currentLib ) + emptyScreen(); + + m_libMgr->RevertLibrary( libName ); + + if( currentLib && m_libMgr->PartExists( alias, libName ) ) + loadPart( alias, libName, unit ); +} + + +void LIB_EDIT_FRAME::OnCreateNewPart( wxCommandEvent& event ) +{ + m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor() ); + m_drawItem = NULL; + wxString lib = getTargetLib(); + + if( !m_libMgr->LibraryExists( lib ) ) + { + lib = SelectLibraryFromList(); + + if( !m_libMgr->LibraryExists( lib ) ) + return; + } + + DIALOG_LIB_NEW_COMPONENT dlg( this ); + dlg.SetMinSize( dlg.GetSize() ); + + if( dlg.ShowModal() == wxID_CANCEL ) + return; + + if( dlg.GetName().IsEmpty() ) + { + wxMessageBox( _( "This new symbol has no name and cannot be created." ) ); + return; + } + + wxString name = dlg.GetName(); + name.Replace( " ", "_" ); + + // Test if there is a component with this name already. + if( !lib.empty() && m_libMgr->PartExists( name, lib ) ) + { + wxString msg = wxString::Format( _( "Symbol '%s' already exists in library '%s'" ), + name, lib ); + DisplayError( this, msg ); + return; + } + + LIB_PART new_part( name ); // do not create part on the heap, it will be buffered soon + m_aliasName = name; + new_part.GetReferenceField().SetText( dlg.GetReference() ); + new_part.SetUnitCount( dlg.GetUnitCount() ); + + // Initialize new_part.m_TextInside member: + // if 0, pin text is outside the body (on the pin) + // if > 0, pin text is inside the body + new_part.SetConversion( dlg.GetAlternateBodyStyle() ); + SetShowDeMorgan( dlg.GetAlternateBodyStyle() ); + + if( dlg.GetPinNameInside() ) + { + new_part.SetPinNameOffset( dlg.GetPinTextPosition() ); + + if( new_part.GetPinNameOffset() == 0 ) + new_part.SetPinNameOffset( 1 ); + } + else + { + new_part.SetPinNameOffset( 0 ); + } + + ( dlg.GetPowerSymbol() ) ? new_part.SetPower() : new_part.SetNormal(); + new_part.SetShowPinNumbers( dlg.GetShowPinNumber() ); + new_part.SetShowPinNames( dlg.GetShowPinName() ); + new_part.LockUnits( dlg.GetLockItems() ); + + if( dlg.GetUnitCount() < 2 ) + new_part.LockUnits( false ); + + m_libMgr->UpdatePart( &new_part, lib ); + loadPart( name, lib, 1 ); +} + + +void LIB_EDIT_FRAME::OnEditPart( wxCommandEvent& aEvent ) +{ + int unit = 0; + LIB_ID partId = m_treePane->GetCmpTree()->GetSelectedLibId( &unit ); + loadPart( partId.GetLibItemName(), partId.GetLibNickname(), unit ); +} + + +void LIB_EDIT_FRAME::OnSavePart( wxCommandEvent& aEvent ) +{ + LIB_ID libId = getTargetLibId(); + + if( m_libMgr->FlushPart( libId.GetLibItemName(), libId.GetLibNickname() ) ) + m_libMgr->ClearPartModified( libId.GetLibItemName(), libId.GetLibNickname() ); + + m_treePane->Refresh(); +} + + +void LIB_EDIT_FRAME::OnRemovePart( wxCommandEvent& aEvent ) +{ + LIB_ID libId = getTargetLibId(); + + if( m_libMgr->IsPartModified( libId.GetLibItemName(), libId.GetLibNickname() ) + && !IsOK( this, _( wxString::Format( "Component %s has been modified\n" + "Do you want to remove it from the library?", libId.GetLibItemName().c_str() ) ) ) ) + { + return; + } + + if( isCurrentPart( libId ) ) + emptyScreen(); + + m_libMgr->RemovePart( libId.GetLibItemName(), libId.GetLibNickname() ); +} + + +void LIB_EDIT_FRAME::OnCopyCutPart( wxCommandEvent& aEvent ) +{ + int unit = 0; + LIB_ID partId = m_treePane->GetCmpTree()->GetSelectedLibId( &unit ); + LIB_PART* part = m_libMgr->GetBufferedPart( partId.GetLibItemName(), partId.GetLibNickname() ); + + if( !part ) + return; + + LIB_ID libId = getTargetLibId(); + m_copiedPart.reset( new LIB_PART( *part ) ); + + if( aEvent.GetId() == ID_LIBEDIT_CUT_PART ) + { + if( isCurrentPart( libId ) ) + emptyScreen(); + + m_libMgr->RemovePart( libId.GetLibItemName(), libId.GetLibNickname() ); + } +} + + +void LIB_EDIT_FRAME::OnPasteDuplicatePart( wxCommandEvent& aEvent ) +{ + int unit = 0; + LIB_ID libId = m_treePane->GetCmpTree()->GetSelectedLibId( &unit ); + wxString lib = libId.GetLibNickname(); + + if( !m_libMgr->LibraryExists( lib ) ) + return; + + LIB_PART* srcPart = nullptr; + + if( aEvent.GetId() == ID_LIBEDIT_DUPLICATE_PART ) + srcPart = m_libMgr->GetBufferedPart( libId.GetLibItemName(), lib ); + else if( aEvent.GetId() == ID_LIBEDIT_PASTE_PART ) + srcPart = m_copiedPart.get(); + else + wxFAIL; + + if( !srcPart ) + return; + + LIB_PART newPart( *srcPart ); + fixDuplicateAliases( &newPart, lib ); + m_libMgr->UpdatePart( &newPart, lib ); + m_treePane->GetCmpTree()->SelectLibId( LIB_ID( lib, newPart.GetName() ) ); +} + + +void LIB_EDIT_FRAME::fixDuplicateAliases( LIB_PART* aPart, const wxString& aLibrary ) +{ + wxString newName; + + for( unsigned int i = 0; i < aPart->GetAliasCount(); ++i ) + { + LIB_ALIAS* alias = aPart->GetAlias( i ); + int sfx = 0; + newName = alias->GetName(); + + while( m_libMgr->PartExists( newName, aLibrary ) ) + { + wxString suffix = ( sfx == 0 ) ? wxT( " (copy)" ) + : wxString::Format( _( " (copy %d)" ), sfx ); + newName = alias->GetName() + suffix; + ++sfx; + } + + if( i == 0 ) + aPart->SetName( newName ); + else + alias->SetName( newName ); + } +} + + +void LIB_EDIT_FRAME::OnRevertPart( wxCommandEvent& aEvent ) +{ + LIB_ID libId = getTargetLibId(); + bool currentPart = isCurrentPart( libId ); + int unit = m_unit; + + if( currentPart ) + emptyScreen(); + + if( m_libMgr->RevertPart( libId.GetLibItemName(), libId.GetLibNickname() ) ) + m_libMgr->ClearPartModified( libId.GetLibItemName(), libId.GetLibNickname() ); + + if( currentPart && m_libMgr->PartExists( libId.GetLibItemName(), libId.GetLibNickname() ) ) + loadPart( libId.GetLibItemName(), libId.GetLibNickname(), unit ); +} + + +void LIB_EDIT_FRAME::loadPart( const wxString& aAlias, const wxString& aLibrary, int aUnit ) +{ + wxCHECK( m_libMgr->PartExists( aAlias, aLibrary ), /* void */ ); + LIB_PART* part = m_libMgr->GetBufferedPart( aAlias, aLibrary ); + LIB_ALIAS* alias = part ? part->GetAlias( aAlias ) : nullptr; + + if( !alias ) + { + wxString msg = wxString::Format( _( "Part name '%s' not found in library '%s'" ), + GetChars( aAlias ), GetChars( aLibrary ) ); + DisplayError( this, msg ); + return; + } + + m_lastDrawItem = m_drawItem = nullptr; + m_aliasName = aAlias; + m_unit = ( aUnit <= part->GetUnitCount() ? aUnit : 1 ); + + LoadOneLibraryPartAux( alias, aLibrary ); +} + + +bool LIB_EDIT_FRAME::saveLibrary( const wxString& aLibrary, bool aNewFile ) { wxFileName fn; wxString msg; @@ -296,20 +501,15 @@ bool LIB_EDIT_FRAME::SaveActiveLibrary( bool newFile ) m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor() ); - wxString lib = GetCurLib(); - - if( !newFile && ( lib.empty() || !prj.SchSymbolLibTable()->HasLibrary( lib ) ) ) + if( !aNewFile && ( aLibrary.empty() || !prj.SchSymbolLibTable()->HasLibrary( aLibrary ) ) ) { DisplayError( this, _( "No library specified." ) ); return false; } - if( GetScreen()->IsModify() && !IsOK( this, _( "Include current symbol changes?" ) ) ) - return false; - - if( newFile ) + if( aNewFile ) { - SEARCH_STACK* search = prj.SchSearchS(); + SEARCH_STACK* search = prj.SchSearchS(); // Get a new name for the library wxString default_path = prj.GetRString( PROJECT::SCH_LIB_PATH ); @@ -317,8 +517,11 @@ bool LIB_EDIT_FRAME::SaveActiveLibrary( bool newFile ) if( !default_path ) default_path = search->LastVisitedPath(); - wxFileDialog dlg( this, _( "Symbol Library Name" ), default_path, - wxEmptyString, SchematicLibraryFileWildcard(), + fn.SetName( aLibrary ); + fn.SetExt( SchematicLibraryFileExtension ); + + wxFileDialog dlg( this, wxString::Format( _( "Save Library '%s' As..." ), aLibrary ), + default_path, fn.GetFullName(), SchematicLibraryFileWildcard(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); if( dlg.ShowModal() == wxID_CANCEL ) @@ -330,17 +533,10 @@ bool LIB_EDIT_FRAME::SaveActiveLibrary( bool newFile ) // file name so add it here. if( fn.GetExt().IsEmpty() ) fn.SetExt( SchematicLibraryFileExtension ); - - prj.SetRString( PROJECT::SCH_LIB_PATH, fn.GetPath() ); } else { - fn = prj.SchSymbolLibTable()->GetFullURI( lib ); - - msg.Printf( _( "Modify symbol library file '%s' ?" ), fn.GetFullPath() ); - - if( !IsOK( this, msg ) ) - return false; + fn = prj.SchSymbolLibTable()->GetFullURI( aLibrary ); } // Verify the user has write privileges before attempting to save the library file. @@ -349,92 +545,29 @@ bool LIB_EDIT_FRAME::SaveActiveLibrary( bool newFile ) ClearMsgPanel(); - wxFileName libFileName = fn; - wxFileName backupFileName = fn; - // Copy .lib file to .bak. - if( libFileName.FileExists() ) - { - backupFileName.SetExt( "bak" ); - - if( backupFileName.FileExists() ) - wxRemoveFile( backupFileName.GetFullPath() ); - - if( !wxCopyFile( libFileName.GetFullPath(), backupFileName.GetFullPath() ) ) - { - libFileName.MakeAbsolute(); - msg.Printf( _( "Failed to rename old symbol library to file '%s'" ), - backupFileName.GetFullPath() ); - DisplayError( this, msg ); - return false; - } - } - - wxFileName docFileName = libFileName; + if( !backupFile( fn, "bak" ) ) + return false; + wxFileName docFileName = fn; docFileName.SetExt( DOC_EXT ); // Copy .dcm file to .bck. - if( docFileName.FileExists() ) + if( !backupFile( docFileName, "bck" ) ) + return false; + + if( !m_libMgr->SaveLibrary( aLibrary, fn.GetFullPath() ) ) { - backupFileName.SetExt( "bck" ); - - if( backupFileName.FileExists() ) - wxRemoveFile( backupFileName.GetFullPath() ); - - if( !wxCopyFile( docFileName.GetFullPath(), backupFileName.GetFullPath() ) ) - { - msg.Printf( _( "Failed to save old library document to file '%s'" ), - backupFileName.GetFullPath() ); - DisplayError( this, msg ); - return false; - } + msg.Printf( _( "Failed to save changes to symbol library file '%s'" ), + fn.GetFullPath() ); + DisplayErrorMessage( this, _( "Error saving library" ), msg ); + return false; } - // Copy the library and document files to the new destination library files. - if( newFile ) - { - wxFileName src = prj.SchSymbolLibTable()->GetFullURI( GetCurLib() ); + if( !aNewFile ) + m_libMgr->ClearLibraryModified( aLibrary ); - if( !wxCopyFile( src.GetFullPath(), libFileName.GetFullPath() ) ) - { - msg.Printf( _( "Failed to copy symbol library file '%s'" ), libFileName.GetFullPath() ); - DisplayError( this, msg ); - return false; - } - - src.SetExt( DOC_EXT ); - - if( !wxCopyFile( src.GetFullPath(), docFileName.GetFullPath() ) ) - { - msg.Printf( _( "Failed to copy symbol library document file '%s'" ), - docFileName.GetFullPath() ); - DisplayError( this, msg ); - return false; - } - } - - // Update symbol changes in library. - if( GetScreen()->IsModify() ) - { - SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_LEGACY ) ); - - try - { - pi->SaveSymbol( fn.GetFullPath(), new LIB_PART( *GetCurPart() ) ); - } - catch( const IO_ERROR& ioe ) - { - msg.Printf( _( "Failed to save changes to symbol library file '%s'" ), - libFileName.GetFullPath() ); - DisplayErrorMessage( this, msg, ioe.What() ); - return false; - } - - GetScreen()->ClrModify(); - } - - msg.Printf( _( "Symbol library file '%s' saved" ), libFileName.GetFullPath() ); + msg.Printf( _( "Symbol library file '%s' saved" ), fn.GetFullPath() ); wxString msg1; msg1.Printf( _( "Symbol library documentation file '%s' saved" ), docFileName.GetFullPath() ); AppendMsgPanel( msg, msg1, BLUE ); @@ -446,6 +579,47 @@ bool LIB_EDIT_FRAME::SaveActiveLibrary( bool newFile ) } +bool LIB_EDIT_FRAME::saveAllLibraries() +{ + wxArrayString unsavedLibraries; + // There are two stages: first try to save libraries to the original files. + // In case of problems, ask the user to save them in a new location. + bool firstRun = true; + bool allSaved = false; + + while( !allSaved ) + { + allSaved = true; + unsavedLibraries.Empty(); + + for( const auto& lib : m_libMgr->GetLibraryNames() ) + { + if( m_libMgr->IsLibraryModified( lib ) ) + unsavedLibraries.Add( lib ); + } + + if( !unsavedLibraries.IsEmpty() ) + { + auto res = SelectMultipleOptions( this, _( "Save Libraries" ), + firstRun ? _( "Select libraries to save before closing" ) + : _( "Some libraries could not be saved to their original files.\n\n" + "Do you want to save them to a new file?" ), + unsavedLibraries, true ); + + if( !res.first ) + return false; // dialog has been cancelled + + for( auto libIndex : res.second ) + allSaved &= saveLibrary( unsavedLibraries[libIndex], !firstRun ); + + firstRun = false; + } + } + + return true; +} + + void LIB_EDIT_FRAME::DisplayCmpDoc() { LIB_ALIAS* alias; @@ -493,197 +667,3 @@ void LIB_EDIT_FRAME::DisplayCmpDoc() AppendMsgPanel( _( "Key words" ), alias->GetKeyWords(), DARKDARKGRAY ); AppendMsgPanel( _( "Datasheet" ), alias->GetDocFileName(), DARKDARKGRAY ); } - - -void LIB_EDIT_FRAME::DeleteOnePart( wxCommandEvent& event ) -{ - wxString cmp_name; - wxArrayString nameList; - wxString msg; - - m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor() ); - - m_lastDrawItem = NULL; - m_drawItem = NULL; - - LIB_PART *part = GetCurPart(); - wxString lib = GetCurLib(); - - if( lib.empty() ) - { - SelectActiveLibrary(); - - lib = GetCurLib(); - - if( !lib ) - { - DisplayError( this, _( "Please select a symbol library." ) ); - return; - } - } - - auto adapter( CMP_TREE_MODEL_ADAPTER::Create( Prj().SchSymbolLibTable() ) ); - - wxString name = part ? part->GetName() : wxString( wxEmptyString ); - adapter->SetPreselectNode( name, /* aUnit */ 0 ); - adapter->ShowUnits( false ); - adapter->AddLibrary( lib ); - - wxString dialogTitle; - dialogTitle.Printf( _( "Delete Symbol (%u items loaded)" ), adapter->GetComponentsCount() ); - - DIALOG_CHOOSE_COMPONENT dlg( this, dialogTitle, adapter, m_convert, false ); - - if( dlg.ShowQuasiModal() == wxID_CANCEL ) - { - return; - } - - LIB_ID id; - - id = dlg.GetSelectedLibId(); - - if( !id.IsValid() ) - return; - - LIB_ALIAS* alias = Prj().SchSymbolLibTable()->LoadSymbol( id ); - - if( !alias ) - return; - - msg.Printf( _( "Delete symbol '%s' from library '%s'?" ), - id.GetLibItemName().wx_str(), id.GetLibNickname().wx_str() ); - - if( !IsOK( this, msg ) ) - return; - - part = GetCurPart(); - - if( !part || !part->HasAlias( id.GetLibItemName() ) ) - { - Prj().SchSymbolLibTable()->DeleteAlias( id.GetLibNickname(), id.GetLibItemName() ); - m_canvas->Refresh(); - return; - } - - // If deleting the current entry or removing one of the aliases for - // the current entry, sync the changes in the current entry as well. - - if( GetScreen()->IsModify() && !IsOK( this, _( - "The symbol being deleted has been modified." - " All changes will be lost. Discard changes?" ) ) ) - { - return; - } - - try - { - Prj().SchSymbolLibTable()->DeleteAlias( id.GetLibNickname(), id.GetLibItemName() ); - } - catch( ... /* IO_ERROR ioe */ ) - { - msg.Printf( _( "Error occurred deleting symbol '%s' from library '%s'" ), - id.GetLibItemName().wx_str(), id.GetLibNickname().wx_str() ); - DisplayError( this, msg ); - return; - } - - SetCurPart( NULL ); // delete CurPart - m_aliasName.Empty(); - m_canvas->Refresh(); -} - - -void LIB_EDIT_FRAME::CreateNewLibraryPart( wxCommandEvent& event ) -{ - wxString name; - - if( GetCurPart() && GetScreen()->IsModify() && !IsOK( this, _( - "All changes to the current symbol will be lost!\n\n" - "Clear the current symbol from the screen?" ) ) ) - { - return; - } - - m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor() ); - - m_drawItem = NULL; - - DIALOG_LIB_NEW_COMPONENT dlg( this ); - - dlg.SetMinSize( dlg.GetSize() ); - - if( dlg.ShowModal() == wxID_CANCEL ) - return; - - if( dlg.GetName().IsEmpty() ) - { - wxMessageBox( _( "This new symbol has no name and cannot be created." ) ); - return; - } - - name = dlg.GetName(); - name.Replace( " ", "_" ); - - wxString lib = GetCurLib(); - - // Test if there a component with this name already. - if( !lib.empty() && Prj().SchSymbolLibTable()->LoadSymbol( lib, name ) != NULL ) - { - wxString msg = wxString::Format( _( "Symbol '%s' already exists in library '%s'" ), - name, lib ); - DisplayError( this, msg ); - return; - } - - LIB_PART* new_part = new LIB_PART( name ); - - SetCurPart( new_part ); - m_aliasName = new_part->GetName(); - - new_part->GetReferenceField().SetText( dlg.GetReference() ); - new_part->SetUnitCount( dlg.GetUnitCount() ); - - // Initialize new_part->m_TextInside member: - // if 0, pin text is outside the body (on the pin) - // if > 0, pin text is inside the body - new_part->SetConversion( dlg.GetAlternateBodyStyle() ); - SetShowDeMorgan( dlg.GetAlternateBodyStyle() ); - - if( dlg.GetPinNameInside() ) - { - new_part->SetPinNameOffset( dlg.GetPinTextPosition() ); - - if( new_part->GetPinNameOffset() == 0 ) - new_part->SetPinNameOffset( 1 ); - } - else - { - new_part->SetPinNameOffset( 0 ); - } - - ( dlg.GetPowerSymbol() ) ? new_part->SetPower() : new_part->SetNormal(); - new_part->SetShowPinNumbers( dlg.GetShowPinNumber() ); - new_part->SetShowPinNames( dlg.GetShowPinName() ); - new_part->LockUnits( dlg.GetLockItems() ); - - if( dlg.GetUnitCount() < 2 ) - new_part->LockUnits( false ); - - m_unit = 1; - m_convert = 1; - - DisplayLibInfos(); - DisplayCmpDoc(); - UpdateAliasSelectList(); - UpdatePartSelectList(); - - m_editPinsPerPartOrConvert = new_part->UnitsLocked() ? true : false; - m_lastDrawItem = NULL; - - GetScreen()->ClearUndoRedoList(); - OnModify(); - - m_canvas->Refresh(); - m_mainToolBar->Refresh(); -} diff --git a/eeschema/libedit_onrightclick.cpp b/eeschema/libedit_onrightclick.cpp index 3e6870e000..68388c4727 100644 --- a/eeschema/libedit_onrightclick.cpp +++ b/eeschema/libedit_onrightclick.cpp @@ -337,7 +337,14 @@ void AddMenusForBlock( wxMenu* PopMenu, LIB_EDIT_FRAME* frame ) { AddMenuItem( PopMenu, ID_POPUP_SELECT_ITEMS_BLOCK, _( "Select Items" ), KiBitmap( green_xpm ) ); - AddMenuItem( PopMenu, ID_POPUP_DUPLICATE_BLOCK, _( "Duplicate Block" ), KiBitmap( duplicate_xpm ) ); + msg = AddHotkeyName( _( "Cut Block" ), g_Schematic_Hokeys_Descr, + HK_CUT_BLOCK ); + AddMenuItem( PopMenu, wxID_CUT, msg, KiBitmap( cut_xpm ) ); + msg = AddHotkeyName( _( "Copy Block" ), g_Schematic_Hokeys_Descr, + HK_COPY_BLOCK ); + AddMenuItem( PopMenu, wxID_COPY, msg, KiBitmap( copy_xpm ) ); + AddMenuItem( PopMenu, ID_POPUP_DUPLICATE_BLOCK, _( "Duplicate Block" ), + KiBitmap( duplicate_xpm ) ); msg = AddHotkeyName( _( "Flip Block Horizonal" ), g_Libedit_Hokeys_Descr, HK_MIRROR_Y ); AddMenuItem( PopMenu, ID_POPUP_MIRROR_Y_BLOCK, msg, KiBitmap( mirror_h_xpm ) ); diff --git a/eeschema/libedit_undo_redo.cpp b/eeschema/libedit_undo_redo.cpp index 2774569c9d..1f340259ef 100644 --- a/eeschema/libedit_undo_redo.cpp +++ b/eeschema/libedit_undo_redo.cpp @@ -107,6 +107,8 @@ void LIB_EDIT_FRAME::GetComponentFromUndoList( wxCommandEvent& event ) delete lastcmd; part = (LIB_PART*) wrapper.GetItem(); + printf("RestoreCopy [%p]\n", part); + // Do not delete the previous part by calling SetCurPart( part ), // which calls delete . // is now put in redo list and is owned by this list. diff --git a/eeschema/libeditframe.cpp b/eeschema/libeditframe.cpp index cecce6b8f6..93a927c464 100644 --- a/eeschema/libeditframe.cpp +++ b/eeschema/libeditframe.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -44,6 +45,10 @@ #include #include #include + +#include +#include +#include #include #include @@ -53,17 +58,11 @@ #include #include +#include + #include -/* This method guarantees unique IDs for the library this run of Eeschema - * which prevents ID conflicts and eliminates the need to recompile every - * source file in the project when adding IDs to include/id.h. */ -int ExportPartId = ::wxNewId(); -int ImportPartId = ::wxNewId(); -int CreateNewLibAndSavePartId = ::wxNewId(); - - wxString LIB_EDIT_FRAME:: m_aliasName; int LIB_EDIT_FRAME:: m_unit = 1; int LIB_EDIT_FRAME:: m_convert = 1; @@ -88,15 +87,32 @@ BEGIN_EVENT_TABLE( LIB_EDIT_FRAME, EDA_DRAW_FRAME ) EVT_SIZE( LIB_EDIT_FRAME::OnSize ) EVT_ACTIVATE( LIB_EDIT_FRAME::OnActivate ) - // Main horizontal toolbar. - EVT_TOOL( ID_LIBEDIT_SAVE_CURRENT_LIB, LIB_EDIT_FRAME::OnSaveActiveLibrary ) - EVT_TOOL( ID_LIBEDIT_SELECT_CURRENT_LIB, LIB_EDIT_FRAME::Process_Special_Functions ) - EVT_TOOL( ID_LIBEDIT_DELETE_PART, LIB_EDIT_FRAME::DeleteOnePart ) - EVT_TOOL( ID_TO_LIBVIEW, LIB_EDIT_FRAME::OnOpenLibraryViewer ) - EVT_TOOL( ID_LIBEDIT_NEW_PART, LIB_EDIT_FRAME::CreateNewLibraryPart ) - EVT_TOOL( ID_LIBEDIT_NEW_PART_FROM_EXISTING, LIB_EDIT_FRAME::OnCreateNewPartFromExisting ) + // Library actions + EVT_TOOL( ID_LIBEDIT_NEW_LIBRARY, LIB_EDIT_FRAME::OnCreateNewLibrary ) + EVT_TOOL( ID_LIBEDIT_ADD_LIBRARY, LIB_EDIT_FRAME::OnAddLibrary ) + EVT_TOOL( ID_LIBEDIT_SAVE_LIBRARY, LIB_EDIT_FRAME::OnSaveLibrary ) + EVT_MENU( ID_LIBEDIT_SAVE_LIBRARY_AS, LIB_EDIT_FRAME::OnSaveLibrary ) + EVT_MENU( ID_LIBEDIT_SAVE_ALL_LIBS, LIB_EDIT_FRAME::OnSaveAllLibraries ) + EVT_TOOL( ID_LIBEDIT_REVERT_LIBRARY, LIB_EDIT_FRAME::OnRevertLibrary ) - EVT_TOOL( ID_LIBEDIT_SELECT_PART, LIB_EDIT_FRAME::LoadOneLibraryPart ) + // Part actions + EVT_TOOL( ID_LIBEDIT_NEW_PART, LIB_EDIT_FRAME::OnCreateNewPart ) + EVT_TOOL( ID_LIBEDIT_EDIT_PART, LIB_EDIT_FRAME::OnEditPart ) + EVT_TOOL( ID_LIBEDIT_IMPORT_PART, LIB_EDIT_FRAME::OnImportPart ) + EVT_TOOL( ID_LIBEDIT_EXPORT_PART, LIB_EDIT_FRAME::OnExportPart ) + EVT_TOOL( ID_LIBEDIT_SAVE_PART, LIB_EDIT_FRAME::OnSavePart ) + EVT_TOOL( ID_LIBEDIT_REVERT_PART, LIB_EDIT_FRAME::OnRevertPart ) + EVT_TOOL( ID_LIBEDIT_REMOVE_PART, LIB_EDIT_FRAME::OnRemovePart ) + EVT_TOOL( ID_LIBEDIT_CUT_PART, LIB_EDIT_FRAME::OnCopyCutPart ) + EVT_TOOL( ID_LIBEDIT_COPY_PART, LIB_EDIT_FRAME::OnCopyCutPart ) + EVT_TOOL( ID_LIBEDIT_PASTE_PART, LIB_EDIT_FRAME::OnPasteDuplicatePart ) + EVT_TOOL( ID_LIBEDIT_DUPLICATE_PART, LIB_EDIT_FRAME::OnPasteDuplicatePart ) + + // Main horizontal toolbar. + EVT_TOOL( ID_TO_LIBVIEW, LIB_EDIT_FRAME::OnOpenLibraryViewer ) + EVT_TOOL( wxID_COPY, LIB_EDIT_FRAME::Process_Special_Functions ) + EVT_TOOL( wxID_PASTE, LIB_EDIT_FRAME::Process_Special_Functions ) + EVT_TOOL( wxID_CUT, LIB_EDIT_FRAME::Process_Special_Functions ) EVT_TOOL( wxID_UNDO, LIB_EDIT_FRAME::GetComponentFromUndoList ) EVT_TOOL( wxID_REDO, LIB_EDIT_FRAME::GetComponentFromRedoList ) EVT_TOOL( ID_LIBEDIT_GET_FRAME_EDIT_PART, LIB_EDIT_FRAME::OnEditComponentProperties ) @@ -107,10 +123,6 @@ BEGIN_EVENT_TABLE( LIB_EDIT_FRAME, EDA_DRAW_FRAME ) EVT_TOOL( ID_LIBEDIT_VIEW_DOC, LIB_EDIT_FRAME::OnViewEntryDoc ) EVT_TOOL( ID_LIBEDIT_EDIT_PIN_BY_PIN, LIB_EDIT_FRAME::Process_Special_Functions ) EVT_TOOL( ID_LIBEDIT_EDIT_PIN_BY_TABLE, LIB_EDIT_FRAME::OnOpenPinTable ) - EVT_TOOL( ExportPartId, LIB_EDIT_FRAME::OnExportPart ) - EVT_TOOL( CreateNewLibAndSavePartId, LIB_EDIT_FRAME::OnExportPart ) - EVT_TOOL( ImportPartId, LIB_EDIT_FRAME::OnImportPart ) - EVT_TOOL( ID_LIBEDIT_SAVE_CURRENT_PART, LIB_EDIT_FRAME::OnSaveCurrentPart ) EVT_COMBOBOX( ID_LIBEDIT_SELECT_PART_NUMBER, LIB_EDIT_FRAME::OnSelectPart ) EVT_COMBOBOX( ID_LIBEDIT_SELECT_ALIAS, LIB_EDIT_FRAME::OnSelectAlias ) @@ -123,10 +135,10 @@ BEGIN_EVENT_TABLE( LIB_EDIT_FRAME, EDA_DRAW_FRAME ) // Left vertical toolbar (option toolbar). EVT_TOOL( ID_LIBEDIT_SHOW_ELECTRICAL_TYPE, LIB_EDIT_FRAME::OnShowElectricalType ) + EVT_TOOL( ID_LIBEDIT_SHOW_HIDE_SEARCH_TREE, LIB_EDIT_FRAME::OnToggleSearchTree ) // menubar commands EVT_MENU( wxID_EXIT, LIB_EDIT_FRAME::CloseWindow ) - EVT_MENU( ID_LIBEDIT_SAVE_CURRENT_LIB_AS, LIB_EDIT_FRAME::OnSaveActiveLibrary ) EVT_MENU( ID_LIBEDIT_GEN_PNG_FILE, LIB_EDIT_FRAME::OnPlotCurrentComponent ) EVT_MENU( ID_LIBEDIT_GEN_SVG_FILE, LIB_EDIT_FRAME::OnPlotCurrentComponent ) EVT_MENU( wxID_HELP, EDA_DRAW_FRAME::GetKicadHelp ) @@ -155,18 +167,21 @@ BEGIN_EVENT_TABLE( LIB_EDIT_FRAME, EDA_DRAW_FRAME ) EVT_MENU_RANGE( ID_LIBEDIT_MIRROR_X, ID_LIBEDIT_ORIENT_NORMAL, LIB_EDIT_FRAME::OnOrient ) + // Update user interface elements. - EVT_UPDATE_UI( ExportPartId, LIB_EDIT_FRAME::OnUpdateEditingPart ) - EVT_UPDATE_UI( CreateNewLibAndSavePartId, LIB_EDIT_FRAME::OnUpdateEditingPart ) - EVT_UPDATE_UI( ID_LIBEDIT_SAVE_CURRENT_PART, LIB_EDIT_FRAME::OnUpdateEditingPart ) + EVT_UPDATE_UI( wxID_PASTE, LIB_EDIT_FRAME::OnUpdatePaste ) + EVT_UPDATE_UI( ID_LIBEDIT_REVERT_LIBRARY, LIB_EDIT_FRAME::OnUpdateLibModified ) + EVT_UPDATE_UI( ID_LIBEDIT_EXPORT_PART, LIB_EDIT_FRAME::OnUpdateEditingPart ) + EVT_UPDATE_UI( ID_LIBEDIT_SAVE_PART, LIB_EDIT_FRAME::OnUpdatePartModified ) + EVT_UPDATE_UI( ID_LIBEDIT_REVERT_PART, LIB_EDIT_FRAME::OnUpdatePartModified ) + EVT_UPDATE_UI( ID_LIBEDIT_PASTE_PART, LIB_EDIT_FRAME::OnUpdateClipboardNotEmpty ) EVT_UPDATE_UI( ID_LIBEDIT_GET_FRAME_EDIT_FIELDS, LIB_EDIT_FRAME::OnUpdateEditingPart ) EVT_UPDATE_UI( ID_LIBEDIT_CHECK_PART, LIB_EDIT_FRAME::OnUpdateEditingPart ) EVT_UPDATE_UI( ID_LIBEDIT_GET_FRAME_EDIT_PART, LIB_EDIT_FRAME::OnUpdateEditingPart ) - EVT_UPDATE_UI( ID_LIBEDIT_NEW_PART_FROM_EXISTING, LIB_EDIT_FRAME::OnUpdateEditingPart ) EVT_UPDATE_UI( wxID_UNDO, LIB_EDIT_FRAME::OnUpdateUndo ) EVT_UPDATE_UI( wxID_REDO, LIB_EDIT_FRAME::OnUpdateRedo ) - EVT_UPDATE_UI( ID_LIBEDIT_SAVE_CURRENT_LIB, LIB_EDIT_FRAME::OnUpdateSaveCurrentLib ) - EVT_UPDATE_UI( ID_LIBEDIT_SAVE_CURRENT_LIB_AS, LIB_EDIT_FRAME::OnUpdateSaveCurrentLibAs ) + EVT_UPDATE_UI( ID_LIBEDIT_SAVE_LIBRARY, LIB_EDIT_FRAME::OnUpdateSaveLib ) + EVT_UPDATE_UI( ID_LIBEDIT_SAVE_LIBRARY_AS, LIB_EDIT_FRAME::OnUpdateSaveLibAs ) EVT_UPDATE_UI( ID_LIBEDIT_VIEW_DOC, LIB_EDIT_FRAME::OnUpdateViewDoc ) EVT_UPDATE_UI( ID_LIBEDIT_EDIT_PIN_BY_PIN, LIB_EDIT_FRAME::OnUpdatePinByPin ) EVT_UPDATE_UI( ID_LIBEDIT_EDIT_PIN_BY_TABLE, LIB_EDIT_FRAME::OnUpdatePinTable ) @@ -199,6 +214,8 @@ LIB_EDIT_FRAME::LIB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : m_my_part = NULL; m_tempCopyComponent = NULL; + m_treePane = nullptr; + m_libMgr = nullptr; // Delayed initialization if( m_textSize == -1 ) @@ -213,7 +230,8 @@ LIB_EDIT_FRAME::LIB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : LoadSettings( config() ); - SetScreen( new SCH_SCREEN( aKiway ) ); + m_dummyScreen = new SCH_SCREEN( aKiway ); + SetScreen( m_dummyScreen ); GetScreen()->m_Center = true; GetScreen()->SetMaxUndoItems( m_UndoRedoCountMax ); @@ -233,6 +251,9 @@ LIB_EDIT_FRAME::LIB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : if( m_canvas ) m_canvas->SetEnableBlockCommands( true ); + m_libMgr = new LIB_MANAGER( *this ); + m_treePane = new CMP_TREE_PANE( this, m_libMgr ); + ReCreateMenuBar(); ReCreateHToolbar(); ReCreateVToolbar(); @@ -280,13 +301,16 @@ LIB_EDIT_FRAME::LIB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : wxAuiPaneInfo( vert ).Name( "m_VToolBar" ).Right() ); m_auimgr.AddPane( m_optionsToolBar, - wxAuiPaneInfo( vert ).Name( "m_optionsToolBar" ).Left() ); + wxAuiPaneInfo( vert ).Name( "m_optionsToolBar" ).Left().Row( 0 ) ); m_auimgr.AddPane( m_canvas, wxAuiPaneInfo().Name( "DrawFrame" ).CentrePane() ); m_auimgr.AddPane( m_messagePanel, - wxAuiPaneInfo( mesg ).Name( "MsgPanel" ).Bottom().Layer(10) ); + wxAuiPaneInfo( mesg ).Name( "MsgPanel" ).Bottom().Layer( 10 ) ); + + m_auimgr.AddPane( m_treePane, wxAuiPaneInfo().Name( "ComponentTree" ).Left().Row( 1 ) + .Resizable().MinSize( 250, 400 ).Dock().CloseButton( false ) ); m_auimgr.Update(); @@ -306,12 +330,14 @@ LIB_EDIT_FRAME::~LIB_EDIT_FRAME() Unbind( wxEVT_COMMAND_MENU_SELECTED, &LIB_EDIT_FRAME::OnEditSymbolLibTable, this, ID_EDIT_SYM_LIB_TABLE ); + // current screen is destroyed in EDA_DRAW_FRAME + SetScreen( m_dummyScreen ); + m_drawItem = m_lastDrawItem = NULL; delete m_tempCopyComponent; + delete m_libMgr; delete m_my_part; - m_my_part = NULL; - m_tempCopyComponent = NULL; } @@ -323,30 +349,15 @@ void LIB_EDIT_FRAME::SetDrawItem( LIB_ITEM* drawItem ) void LIB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event ) { - if( GetScreen()->IsModify() ) + if( saveAllLibraries() ) { - int ii = DisplayExitDialog( this, _( "Save the changes in the library before closing?" ) ); - - switch( ii ) - { - case wxID_NO: - break; - - case wxID_YES: - if( SaveActiveLibrary( false ) ) - break; - - // fall through: cancel the close because of an error - - case wxID_CANCEL: - Event.Veto(); - return; - } - - GetScreen()->ClrModify(); + saveSymbolLibTables( true, true ); + Destroy(); + } + else + { + Event.Veto(); } - - Destroy(); } @@ -461,6 +472,28 @@ void LIB_EDIT_FRAME::OnShowElectricalType( wxCommandEvent& event ) } +void LIB_EDIT_FRAME::OnToggleSearchTree( wxCommandEvent& event ) +{ + auto& treePane = m_auimgr.GetPane( m_treePane ); + treePane.Show( !IsSearchTreeShown() ); + m_auimgr.Update(); +} + + +void LIB_EDIT_FRAME::OnEditSymbolLibTable( wxCommandEvent& aEvent ) +{ + SCH_BASE_FRAME::OnEditSymbolLibTable( aEvent ); + m_libMgr->Sync( true ); + m_treePane->Refresh(); +} + + +bool LIB_EDIT_FRAME::IsSearchTreeShown() +{ + return m_auimgr.GetPane( m_treePane ).IsShown(); +} + + void LIB_EDIT_FRAME::OnUpdateSelectTool( wxUpdateUIEvent& aEvent ) { aEvent.Check( GetToolId() == aEvent.GetId() ); @@ -475,7 +508,7 @@ void LIB_EDIT_FRAME::OnUpdateElectricalType( wxUpdateUIEvent& aEvent ) void LIB_EDIT_FRAME::OnUpdateEditingPart( wxUpdateUIEvent& aEvent ) { - LIB_PART* part = GetCurPart(); + LIB_PART* part = GetCurPart(); aEvent.Enable( part != NULL ); @@ -484,9 +517,44 @@ void LIB_EDIT_FRAME::OnUpdateEditingPart( wxUpdateUIEvent& aEvent ) } -void LIB_EDIT_FRAME::OnUpdateNotEditingPart( wxUpdateUIEvent& event ) +void LIB_EDIT_FRAME::OnUpdatePartModified( wxUpdateUIEvent& aEvent ) { - event.Enable( !GetCurPart() ); + LIB_ID libId = getTargetLibId(); + const wxString& partName = libId.GetLibItemName(); + const wxString& libName = libId.GetLibNickname(); + + if( aEvent.GetId() == ID_LIBEDIT_SAVE_PART ) + { + bool readOnly = libName.IsEmpty() || m_libMgr->IsLibraryReadOnly( libName ); + + aEvent.SetText( readOnly ? _( "Save [Read Only]" ) : _( "Save" ) ); + aEvent.Enable( !readOnly && !partName.IsEmpty() + && m_libMgr->IsPartModified( partName, libName ) ); + } + else if( aEvent.GetId() == ID_LIBEDIT_REVERT_PART ) + { + aEvent.Enable( !partName.IsEmpty() && !libName.IsEmpty() + && m_libMgr->IsPartModified( partName, libName ) ); + } + else wxFAIL; +} + + +void LIB_EDIT_FRAME::OnUpdatePaste( wxUpdateUIEvent& event ) +{ + event.Enable( m_clipboard.GetCount() > 0 ); +} + + +void LIB_EDIT_FRAME::OnUpdateLibModified( wxUpdateUIEvent& aEvent ) +{ + aEvent.Enable( m_libMgr->IsLibraryModified( getTargetLib() ) ); +} + + +void LIB_EDIT_FRAME::OnUpdateClipboardNotEmpty( wxUpdateUIEvent& aEvent ) +{ + aEvent.Enable( !!m_copiedPart ); } @@ -504,22 +572,21 @@ void LIB_EDIT_FRAME::OnUpdateRedo( wxUpdateUIEvent& event ) } -void LIB_EDIT_FRAME::OnUpdateSaveCurrentLib( wxUpdateUIEvent& event ) +void LIB_EDIT_FRAME::OnUpdateSaveLib( wxUpdateUIEvent& event ) { - wxString lib = GetCurLib(); - SYMBOL_LIB_TABLE* table = Prj().SchSymbolLibTable(); + wxString lib = getTargetLib(); + bool readOnly = lib.IsEmpty() || m_libMgr->IsLibraryReadOnly( lib ); - event.Enable( !lib.empty() && table->HasLibrary( lib ) && table->IsSymbolLibWritable( lib ) && - GetScreen()->IsModify() ); + event.SetText( readOnly ? _( "Save library [Read Only]" ) : _( "Save library" ) ); + event.Enable( !readOnly && m_libMgr->IsLibraryModified( lib ) ); } -void LIB_EDIT_FRAME::OnUpdateSaveCurrentLibAs( wxUpdateUIEvent& event ) +void LIB_EDIT_FRAME::OnUpdateSaveLibAs( wxUpdateUIEvent& event ) { - wxString lib = GetCurLib(); - SYMBOL_LIB_TABLE* table = Prj().SchSymbolLibTable(); + wxString lib = getTargetLib(); - event.Enable( !lib.empty() && table->HasLibrary( lib ) ); + event.Enable( m_libMgr->LibraryExists( lib ) ); } @@ -676,50 +743,12 @@ void LIB_EDIT_FRAME::OnSelectBodyStyle( wxCommandEvent& event ) } -void LIB_EDIT_FRAME::OnSaveCurrentPart( wxCommandEvent& aEvent ) -{ - LIB_PART* part = GetCurPart(); - - if( !part ) - { - DisplayError( this, _( "No part to save." ) ); - return; - } - - wxString libNickname = GetCurLib(); - - if( libNickname.empty() ) - SelectActiveLibrary(); - - libNickname = GetCurLib(); - - if( !libNickname ) - { - DisplayError( this, _( "No valid library specified." ) ); - return; - } - - try - { - Prj().SchSymbolLibTable()->SaveSymbol( libNickname, new LIB_PART( *part ) ); - } - catch( ... ) - { - wxString msg; - msg.Printf( _( "Unexpected error occured saving symbol '%s' to symbol library '%s'." ), - part->GetName(), libNickname ); - DisplayError( this, msg ); - return; - } - - refreshSchematic(); -} - - void LIB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) { int id = event.GetId(); wxPoint pos; + SCH_SCREEN* screen = GetScreen(); + BLOCK_SELECTOR& block = screen->m_BlockLocate; m_canvas->SetIgnoreMouseEvents( true ); @@ -728,6 +757,8 @@ void LIB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) switch( id ) // Stop placement commands before handling new command. { + case wxID_COPY: + case wxID_CUT: case ID_POPUP_LIBEDIT_END_CREATE_ITEM: case ID_LIBEDIT_EDIT_PIN: case ID_POPUP_LIBEDIT_BODY_EDIT_ITEM: @@ -770,10 +801,6 @@ void LIB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) case ID_POPUP_LIBEDIT_CANCEL_EDITING: break; - case ID_LIBEDIT_SELECT_CURRENT_LIB: - SelectActiveLibrary(); - break; - case ID_LIBEDIT_EDIT_PIN_BY_PIN: m_editPinsPerPartOrConvert = m_mainToolBar->GetToolToggled( ID_LIBEDIT_EDIT_PIN_BY_PIN ); break; @@ -898,48 +925,48 @@ void LIB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) case ID_POPUP_ZOOM_BLOCK: m_canvas->SetAutoPanRequest( false ); - GetScreen()->m_BlockLocate.SetCommand( BLOCK_ZOOM ); + block.SetCommand( BLOCK_ZOOM ); HandleBlockEnd( &dc ); break; case ID_POPUP_DELETE_BLOCK: m_canvas->SetAutoPanRequest( false ); - GetScreen()->m_BlockLocate.SetCommand( BLOCK_DELETE ); + block.SetCommand( BLOCK_DELETE ); m_canvas->MoveCursorToCrossHair(); HandleBlockEnd( &dc ); break; case ID_POPUP_DUPLICATE_BLOCK: m_canvas->SetAutoPanRequest( false ); - GetScreen()->m_BlockLocate.SetCommand( BLOCK_DUPLICATE ); + block.SetCommand( BLOCK_DUPLICATE ); m_canvas->MoveCursorToCrossHair(); HandleBlockEnd( &dc ); break; case ID_POPUP_SELECT_ITEMS_BLOCK: m_canvas->SetAutoPanRequest( false ); - GetScreen()->m_BlockLocate.SetCommand( BLOCK_SELECT_ITEMS_ONLY ); + block.SetCommand( BLOCK_SELECT_ITEMS_ONLY ); m_canvas->MoveCursorToCrossHair(); HandleBlockEnd( &dc ); break; case ID_POPUP_MIRROR_Y_BLOCK: m_canvas->SetAutoPanRequest( false ); - GetScreen()->m_BlockLocate.SetCommand( BLOCK_MIRROR_Y ); + block.SetCommand( BLOCK_MIRROR_Y ); m_canvas->MoveCursorToCrossHair(); HandleBlockPlace( &dc ); break; case ID_POPUP_MIRROR_X_BLOCK: m_canvas->SetAutoPanRequest( false ); - GetScreen()->m_BlockLocate.SetCommand( BLOCK_MIRROR_X ); + block.SetCommand( BLOCK_MIRROR_X ); m_canvas->MoveCursorToCrossHair(); HandleBlockPlace( &dc ); break; case ID_POPUP_ROTATE_BLOCK: m_canvas->SetAutoPanRequest( false ); - GetScreen()->m_BlockLocate.SetCommand( BLOCK_ROTATE ); + block.SetCommand( BLOCK_ROTATE ); m_canvas->MoveCursorToCrossHair(); HandleBlockPlace( &dc ); break; @@ -950,6 +977,25 @@ void LIB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) HandleBlockPlace( &dc ); break; + case wxID_COPY: + block.SetCommand( BLOCK_COPY ); + block.SetMessageBlock( this ); + HandleBlockEnd( &dc ); + break; + + case wxID_PASTE: + HandleBlockBegin( &dc, BLOCK_PASTE, GetCrossHairPosition() ); + break; + + case wxID_CUT: + if( block.GetCommand() != BLOCK_MOVE ) + break; + + block.SetCommand( BLOCK_CUT ); + block.SetMessageBlock( this ); + HandleBlockEnd( &dc ); + break; + default: DisplayError( this, "LIB_EDIT_FRAME::Process_Special_Functions error" ); break; @@ -968,7 +1014,7 @@ void LIB_EDIT_FRAME::OnActivate( wxActivateEvent& event ) } -wxString LIB_EDIT_FRAME::GetCurLib() +wxString LIB_EDIT_FRAME::GetCurLib() const { wxString libNickname = Prj().GetRString( PROJECT::SCH_LIBEDIT_CUR_LIB ); @@ -994,23 +1040,31 @@ wxString LIB_EDIT_FRAME::SetCurLib( const wxString& aLibNickname ) else Prj().SetRString( PROJECT::SCH_LIBEDIT_CUR_LIB, aLibNickname ); + m_libMgr->SetCurrentLib( aLibNickname ); + return old; } -LIB_PART* LIB_EDIT_FRAME::GetCurPart() -{ - return m_my_part; -} - - void LIB_EDIT_FRAME::SetCurPart( LIB_PART* aPart ) { - delete m_my_part; - m_my_part = aPart; // take ownership here + wxASSERT( m_my_part != aPart ); + + if( m_my_part != aPart ) + { + delete m_my_part; + m_my_part = aPart; + } + + // select the current component in the tree widget + if( aPart ) + m_treePane->GetCmpTree()->SelectLibId( aPart->GetLibId() ); + + wxString partName = aPart ? aPart->GetName() : wxString(); + m_libMgr->SetCurrentPart( partName ); // retain in case this wxFrame is re-opened later on the same PROJECT - Prj().SetRString( PROJECT::SCH_LIBEDIT_CUR_PART, aPart ? aPart->GetName() : wxString() ); + Prj().SetRString( PROJECT::SCH_LIBEDIT_CUR_PART, partName ); } @@ -1070,6 +1124,7 @@ void LIB_EDIT_FRAME::EditSymbolText( wxDC* DC, LIB_ITEM* DrawItem ) void LIB_EDIT_FRAME::OnEditComponentProperties( wxCommandEvent& event ) { bool partLocked = GetCurPart()->UnitsLocked(); + wxString oldName = GetCurPart()->GetName(); DIALOG_EDIT_COMPONENT_IN_LIBRARY dlg( this ); @@ -1083,6 +1138,8 @@ void LIB_EDIT_FRAME::OnEditComponentProperties( wxCommandEvent& event ) m_editPinsPerPartOrConvert = GetCurPart()->UnitsLocked() ? true : false; } + m_libMgr->UpdatePart( GetCurPart(), GetCurLib(), oldName ); + UpdateAliasSelectList(); UpdatePartSelectList(); DisplayLibInfos(); @@ -1092,22 +1149,6 @@ void LIB_EDIT_FRAME::OnEditComponentProperties( wxCommandEvent& event ) } -void LIB_EDIT_FRAME::OnCreateNewPartFromExisting( wxCommandEvent& event ) -{ - LIB_PART* part = GetCurPart(); - - wxCHECK_RET( part, "Cannot create new part from non-existent current part." ); - - INSTALL_UNBUFFERED_DC( dc, m_canvas ); - m_canvas->CrossHairOff( &dc ); - - EditField( &part->GetValueField() ); - - m_canvas->MoveCursorToCrossHair(); - m_canvas->CrossHairOn( &dc ); -} - - void LIB_EDIT_FRAME::OnSelectTool( wxCommandEvent& aEvent ) { int id = aEvent.GetId(); @@ -1402,6 +1443,14 @@ void LIB_EDIT_FRAME::deleteItem( wxDC* aDC ) } +void LIB_EDIT_FRAME::OnModify() +{ + GetScreen()->SetModify(); + storeCurrentPart(); + m_treePane->GetCmpTree()->Refresh(); +} + + void LIB_EDIT_FRAME::OnSelectItem( wxCommandEvent& aEvent ) { int id = aEvent.GetId(); @@ -1454,3 +1503,159 @@ void LIB_EDIT_FRAME::refreshSchematic() // in case any symbols have changed. Kiway().ExpressMail( FRAME_SCH, MAIL_SCH_REFRESH, std::string( "" ), this ); } + + +bool LIB_EDIT_FRAME::addLibraryFile( bool aCreateNew ) +{ + wxFileName fileName = getLibraryFileName( !aCreateNew ); + wxString libName = fileName.GetName(); + + if( libName.IsEmpty() ) + return false; + + if( m_libMgr->LibraryExists( libName ) ) + { + DisplayError( this, + wxString::Format( _( "Library '%s' already exists" ), GetChars( libName ) ) ); + return false; + } + + m_libMgr->AddLibrary( fileName.GetFullPath() ); + + if( aCreateNew ) + Prj().SchSymbolLibTable()->CreateSymbolLib( libName ); + + return true; +} + + +wxFileName LIB_EDIT_FRAME::getLibraryFileName( bool aExisting ) +{ + wxFileName fn = m_libMgr->GetUniqueLibraryName(); + fn.SetExt( SchematicLibraryFileExtension ); + + wxFileDialog dlg( this, + aExisting ? _( "Select Library" ) : _( "New Library" ), + Prj().GetProjectPath(), + aExisting ? wxString( wxEmptyString ) : fn.GetFullName() , + SchematicLibraryFileWildcard(), + aExisting ? wxFD_OPEN | wxFD_FILE_MUST_EXIST : + wxFD_SAVE | wxFD_CHANGE_DIR | wxFD_OVERWRITE_PROMPT ); + + if( dlg.ShowModal() == wxID_CANCEL ) + return wxFileName(); + + fn = dlg.GetPath(); + fn.SetExt( SchematicLibraryFileExtension ); + + return fn; +} + + +LIB_PART* LIB_EDIT_FRAME::getTargetPart() const +{ + LIB_ALIAS* alias = nullptr; + + if( m_treePane->GetCmpTree()->IsMenuActive() ) + { + LIB_ID libId = m_treePane->GetCmpTree()->GetSelectedLibId(); + alias = m_libMgr->GetAlias( libId.GetLibItemName(), libId.GetLibNickname() ); + } + else if( LIB_PART* part = GetCurPart() ) + { + alias = part->GetAlias( 0 ); + } + + return alias ? alias->GetPart() : nullptr; +} + + +LIB_ID LIB_EDIT_FRAME::getTargetLibId() const +{ + if( m_treePane->GetCmpTree()->IsMenuActive() ) + return m_treePane->GetCmpTree()->GetSelectedLibId(); + + if( LIB_PART* part = GetCurPart() ) + return part->GetLibId(); + + return LIB_ID(); +} + + +wxString LIB_EDIT_FRAME::getTargetLib() const +{ + if( m_treePane->GetCmpTree()->IsMenuActive() ) + { + LIB_ID libId = m_treePane->GetCmpTree()->GetSelectedLibId(); + return libId.GetLibNickname(); + } + else + { + return GetCurLib(); + } +} + + +SYMBOL_LIB_TABLE* LIB_EDIT_FRAME::SelectSymLibTable() +{ + wxArrayString libTableNames; + libTableNames.Add( _( "Global" ) ); + libTableNames.Add( _( "Project" ) ); + + switch( SelectSingleOption( this, _( "Select Symbol Library Table" ), + _( "Choose the Library Table to add the library:" ), libTableNames ) ) + { + case 0: return &SYMBOL_LIB_TABLE::GetGlobalLibTable(); + case 1: return Prj().SchSymbolLibTable(); + } + + return nullptr; +} + + +bool LIB_EDIT_FRAME::backupFile( const wxFileName& aOriginalFile, const wxString& aBackupExt ) +{ + if( aOriginalFile.FileExists() ) + { + wxFileName backupFileName( aOriginalFile ); + backupFileName.SetExt( "bck" ); + + if( backupFileName.FileExists() ) + wxRemoveFile( backupFileName.GetFullPath() ); + + if( !wxCopyFile( aOriginalFile.GetFullPath(), backupFileName.GetFullPath() ) ) + { + DisplayError( this, _( "Failed to save backup document to file " ) + + backupFileName.GetFullPath() ); + return false; + } + } + + return true; +} + + +void LIB_EDIT_FRAME::storeCurrentPart() +{ + if( m_my_part && !GetCurLib().IsEmpty() && GetScreen()->IsModify() ) + m_libMgr->UpdatePart( m_my_part, GetCurLib() ); // UpdatePart() makes a copy +} + + +bool LIB_EDIT_FRAME::isCurrentPart( const LIB_ID& aLibId ) const +{ + return ( GetCurPart() && aLibId == GetCurPart()->GetLibId() ); +} + + +void LIB_EDIT_FRAME::emptyScreen() +{ + SetCurLib( wxEmptyString ); + SetCurPart( nullptr ); + m_aliasName.Empty(); + m_drawItem = m_lastDrawItem = nullptr; + SetScreen( m_dummyScreen ); + m_dummyScreen->ClearUndoRedoList(); + Zoom_Automatique( false ); + Refresh(); +} diff --git a/eeschema/libeditframe.h b/eeschema/libeditframe.h index 5242fe3987..07ff983b26 100644 --- a/eeschema/libeditframe.h +++ b/eeschema/libeditframe.h @@ -4,6 +4,8 @@ * Copyright (C) 2014 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2008 Wayne Stambaugh * Copyright (C) 2004-2017 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2017 CERN + * @author Maciej Suminski * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -37,13 +39,17 @@ #include #include +#include class SCH_EDIT_FRAME; +class SYMBOL_LIB_TABLE; class LIB_PART; class LIB_ALIAS; class LIB_FIELD; class DIALOG_LIB_EDIT_TEXT; +class CMP_TREE_PANE; class LIB_ID; +class LIB_MANAGER; /** @@ -56,6 +62,8 @@ class LIB_EDIT_FRAME : public SCH_BASE_FRAME LIB_COLLECTOR m_collectedItems; ///< Used for hit testing. wxComboBox* m_partSelectBox; ///< a Box to select a part to edit (if any) wxComboBox* m_aliasSelectBox; ///< a box to select the alias to edit (if any) + CMP_TREE_PANE* m_treePane; ///< component search tree widget + LIB_MANAGER* m_libMgr; ///< manager taking care of temporary modificatoins /** Convert of the item currently being drawn. */ bool m_drawSpecificConvert; @@ -137,7 +145,7 @@ public: ~LIB_EDIT_FRAME(); /** The nickname of the current library being edited and empty string if none. */ - wxString GetCurLib(); + wxString GetCurLib() const; /** Sets the current library nickname and returns the old library nickname. */ wxString SetCurLib( const wxString& aLibNickname ); @@ -147,7 +155,10 @@ public: * * This is a LIB_PART that I own, it is at best a copy of one in a library. */ - LIB_PART* GetCurPart(); + LIB_PART* GetCurPart() const + { + return m_my_part; + } /** * Take ownership of aPart and notes that it is the one currently being edited. @@ -204,6 +215,50 @@ public: void Process_Special_Functions( wxCommandEvent& event ); void OnSelectTool( wxCommandEvent& aEvent ); + /** + * Creates a new library. The library is added to the project libraries table. + */ + void OnCreateNewLibrary( wxCommandEvent& aEvent ) + { + addLibraryFile( true ); + } + + /** + * Adds an existing library. The library is added to the project libraries table. + */ + void OnAddLibrary( wxCommandEvent& aEvent ) + { + addLibraryFile( false ); + } + + /** + * The command event handler to save the changes to the current library. + * + * A backup file of the current library is saved with the .bak extension before the + * changes made to the library are saved. + */ + void OnSaveLibrary( wxCommandEvent& event ); + + /** + * Saves all changes in modified libraries. + */ + void OnSaveAllLibraries( wxCommandEvent& event ); + + /** + * Reverts unsaved changes in a library. + */ + void OnRevertLibrary( wxCommandEvent& aEvent ); + + /** + * Creates a new part in the selected library. + */ + void OnCreateNewPart( wxCommandEvent& aEvent ); + + /** + * Opens the selected part for editing. + */ + void OnEditPart( wxCommandEvent& aEvent ); + /** * Routine to read one part. * The format is that of libraries, but it loads only 1 component. @@ -213,11 +268,30 @@ public: void OnImportPart( wxCommandEvent& event ); /** - * Function OnExportPart - * creates a new library and backup the current component in this library or export + * Creates a new library and backup the current component in this library or exports * the component of the current library. */ void OnExportPart( wxCommandEvent& event ); + + /** + * Saves a single part in the selected library. The library file is updated without including + * the remaining unsaved changes. + */ + void OnSavePart( wxCommandEvent& aEvent ); + + /** + * Reverts unsaved changes in a part, restoring to the last saved state. + */ + void OnRevertPart( wxCommandEvent& aEvent ); + + /** + * Removes a part from the working copy of a library. + */ + void OnRemovePart( wxCommandEvent& aEvent ); + + void OnCopyCutPart( wxCommandEvent& aEvent ); + void OnPasteDuplicatePart( wxCommandEvent& aEvent ); + void OnSelectAlias( wxCommandEvent& event ); void OnSelectPart( wxCommandEvent& event ); @@ -226,39 +300,14 @@ public: */ void OnShowElectricalType( wxCommandEvent& event ); - /** - * Delete a symbol from the current library. - * - * The deleted entry can be an alias or a component. If the entry is an alias, - * it is removed from the component and the list of alias is updated. If the - * entry is a component and the list of aliases is empty, the component and all - * it drawable items are deleted. Otherwise the first alias in the alias list - * becomes the new component name and the other aliases become dependent on - * renamed component. - * - * @note This only deletes the entry in memory. The file does not change. - */ - void DeleteOnePart( wxCommandEvent& event ); + void OnToggleSearchTree( wxCommandEvent& event ); - /** - * Create a new library symbol. - * - * If an old component is currently in edit, it is deleted. - */ - void CreateNewLibraryPart( wxCommandEvent& event ); + void OnEditSymbolLibTable( wxCommandEvent& aEvent ) override; + + bool IsSearchTreeShown(); - void OnCreateNewPartFromExisting( wxCommandEvent& event ); void OnEditComponentProperties( wxCommandEvent& event ); - void InstallFieldsEditorDialog( wxCommandEvent& event ); - - /** - * Loads a symbol from the currently selected library. - * - * If a library is already selected, the user is prompted for the component name - * to load. If there is no current selected library, the user is prompted to select - * a library name and then select component to load. - */ - void LoadOneLibraryPart( wxCommandEvent& event ); + void InstallFieldsEditorDialog( wxCommandEvent& event ); void OnViewEntryDoc( wxCommandEvent& event ); void OnCheckComponent( wxCommandEvent& event ); @@ -268,15 +317,16 @@ public: void OnOpenPinTable( wxCommandEvent& aEvent ); - void OnSaveCurrentPart( wxCommandEvent& aEvent ); - + void OnUpdatePaste( wxUpdateUIEvent& event ); void OnUpdateSelectTool( wxUpdateUIEvent& aEvent ); void OnUpdateEditingPart( wxUpdateUIEvent& event ); - void OnUpdateNotEditingPart( wxUpdateUIEvent& event ); + void OnUpdatePartModified( wxUpdateUIEvent& aEvent ); + void OnUpdateLibModified( wxUpdateUIEvent& aEvent ); + void OnUpdateClipboardNotEmpty( wxUpdateUIEvent& aEvent ); void OnUpdateUndo( wxUpdateUIEvent& event ); void OnUpdateRedo( wxUpdateUIEvent& event ); - void OnUpdateSaveCurrentLib( wxUpdateUIEvent& event ); - void OnUpdateSaveCurrentLibAs( wxUpdateUIEvent& event ); + void OnUpdateSaveLib( wxUpdateUIEvent& event ); + void OnUpdateSaveLibAs( wxUpdateUIEvent& event ); void OnUpdateViewDoc( wxUpdateUIEvent& event ); void OnUpdatePinByPin( wxUpdateUIEvent& event ); void OnUpdatePinTable( wxUpdateUIEvent& event ); @@ -349,10 +399,7 @@ public: * Must be called after a schematic change in order to set the "modify" flag of the * current screen. */ - void OnModify() - { - GetScreen()->SetModify(); - } + void OnModify(); const wxString& GetAliasName() { return m_aliasName; } @@ -419,6 +466,18 @@ public: bool IsEditingDrawItem() { return m_drawItem && m_drawItem->InEditMode(); } private: + void loadPart( const wxString& aLibrary, const wxString& aPart, int Unit ); + + /** + * Saves the changes to the current library. + * + * A backup file of the current library is saved with the .bak extension before the + * changes made to the library are saved. + * @param aLibrary is the library name. + * @param aNewFile Ask for a new file name to save the library. + * @return True if the library was successfully saved. + */ + bool saveLibrary( const wxString& aLibrary, bool aNewFile ); /** * Called when the frame is activated. Tests if the current library exists. @@ -437,24 +496,6 @@ private: */ void SelectActiveLibrary( const wxString& aLibrary = wxEmptyString ); - /** - * The command event handler to save the changes to the current library. - * - * A backup file of the current library is saved with the .bak extension before the - * changes made to the library are saved. - */ - void OnSaveActiveLibrary( wxCommandEvent& event ); - - /** - * Saves the changes to the current library. - * - * A backup file of the current library is saved with the .bak extension before the - * changes made to the library are saved. - * @param newFile Ask for a new file name to save the library. - * @return True if the library was successfully saved. - */ - bool SaveActiveLibrary( bool newFile ); - /** * Loads a symbol from the current active library, optionally setting the selected * unit and convert. @@ -645,6 +686,71 @@ public: */ void SVG_PlotComponent( const wxString& aFullFileName ); + /** + * Displays a dialog asking the user to select a symbol library table. + * @return Pointer to the selected symbol library table or nullptr if cancelled. + */ + SYMBOL_LIB_TABLE* SelectSymLibTable(); + +private: + ///> Helper screen used when no part is loaded + SCH_SCREEN* m_dummyScreen; + + ///> Creates a backup copy of a file with requested extension + bool backupFile( const wxFileName& aOriginalFile, const wxString& aBackupExt ); + + ///> Returns currently edited part. + LIB_PART* getTargetPart() const; + + ///> Returns either the part selected in the component tree, if context menu is active + ///> or the currently modified part. + LIB_ID getTargetLibId() const; + + ///> Returns either the library selected in the component tree, if context menu is active + ///> or the library that is currently modified. + wxString getTargetLib() const; + + ///> Returns true when the operation has succeded (all requested libraries have been saved or + ///> none was selected and confirmed by OK). + bool saveAllLibraries(); + + ///> Creates or adds an existing library to the symbol library table. + bool addLibraryFile( bool aCreateNew ); + + ///> Displays a file browser dialog to select a library file. + wxFileName getLibraryFileName( bool aExisting ); + + ///> Stores the currently modified part in the library manager buffer. + void storeCurrentPart(); + + ///> Returns true if currently modified part has the same LIB_ID. + bool isCurrentPart( const LIB_ID& aLibId ) const; + + ///> Restores the empty editor screen, without any part or library selected. + void emptyScreen(); + + ///> Renames LIB_PART aliases to avoid conflicts before adding a component to a library + void fixDuplicateAliases( LIB_PART* aPart, const wxString& aLibrary ); + + void InitBlockPasteInfos() override; + + /** + * Copies items selected in the current part to the internal clipboard. + */ + void copySelectedItems(); + + /** + * Pastes items from the internal clipboard to the current part. + * @param aOffset is the offset where the pasted items should be located. + */ + void pasteClipboard( const wxPoint& aOffset ); + + ///> Clipboard buffer storing LIB_ITEMs + BLOCK_SELECTOR m_clipboard; + + // Copy/cut/paste buffer to move parts between libraries + std::unique_ptr m_copiedPart; + DECLARE_EVENT_TABLE() }; diff --git a/eeschema/libfield.cpp b/eeschema/libfield.cpp index eaca9bdf87..5e11226aa3 100644 --- a/eeschema/libfield.cpp +++ b/eeschema/libfield.cpp @@ -35,6 +35,7 @@ #include #include #include +#include void LIB_EDIT_FRAME::EditField( LIB_FIELD* aField ) @@ -42,14 +43,12 @@ void LIB_EDIT_FRAME::EditField( LIB_FIELD* aField ) wxString newFieldValue; wxString title; wxString caption; - wxString oldName; if( aField == NULL ) return; LIB_PART* parent = aField->GetParent(); - - wxASSERT( parent ); + wxCHECK( parent, /* void */ ); // Editing the component value field is equivalent to creating a new component based // on the current component. Set the dialog message to inform the user. @@ -75,17 +74,19 @@ void LIB_EDIT_FRAME::EditField( LIB_FIELD* aField ) newFieldValue = dlg.GetText(); wxString fieldText = aField->GetFullText( m_unit ); + bool creatingNewComponent = aField->GetId() == VALUE && newFieldValue != aField->GetText(); + /* If the value field is changed, this is equivalent to creating a new component from * the old one. Rename the component and remove any conflicting aliases to prevent name * errors when updating the library. */ - if( aField->GetId() == VALUE && newFieldValue != aField->GetText() ) + if( creatingNewComponent ) { wxString msg; wxString lib = GetCurLib(); // Test the current library for name conflicts. - if( !lib.empty() && Prj().SchSymbolLibTable()->LoadSymbol( lib, newFieldValue ) ) + if( !lib.empty() && m_libMgr->PartExists( newFieldValue, lib ) ) { msg.Printf( _( "The name '%s' conflicts with an existing entry in the component library '%s'.\n\n" @@ -124,7 +125,7 @@ void LIB_EDIT_FRAME::EditField( LIB_FIELD* aField ) bool conflicts = false; wxArrayString libAliasNames, symbolAliasNames; - Prj().SchSymbolLibTable()->EnumerateSymbolLib( lib, libAliasNames ); + libAliasNames = m_libMgr->GetAliasNames( lib ); symbolAliasNames = parent->GetAliasNames(); for( size_t i = 0; i < symbolAliasNames.GetCount(); i++ ) @@ -156,7 +157,7 @@ void LIB_EDIT_FRAME::EditField( LIB_FIELD* aField ) for( size_t i = 0; i < aliases.GetCount(); i++ ) { - if( Prj().SchSymbolLibTable()->LoadSymbol( lib, aliases[ i ] ) != NULL ) + if( m_libMgr->GetAlias( aliases[i], lib ) != NULL ) parent->RemoveAlias( aliases[ i ] ); } } @@ -164,13 +165,18 @@ void LIB_EDIT_FRAME::EditField( LIB_FIELD* aField ) if( !parent->HasAlias( m_aliasName ) ) m_aliasName = newFieldValue; + + //m_libMgr->RemovePart( fieldText, lib ); + m_libMgr->UpdatePart( parent, lib, fieldText ); + } + + + if( !aField->InEditMode() && !creatingNewComponent ) + { + SaveCopyInUndoList( parent ); } dlg.UpdateField( aField ); - - if( !aField->InEditMode() ) - SaveCopyInUndoList( parent ); - m_canvas->Refresh(); OnModify(); diff --git a/eeschema/list_operations.h b/eeschema/list_operations.h new file mode 100644 index 0000000000..f421e861bf --- /dev/null +++ b/eeschema/list_operations.h @@ -0,0 +1,81 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2017 KiCad Developers, see CHANGELOG.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 + */ + +#ifndef LIST_OPERATIONS_H +#define LIST_OPERATIONS_H + +namespace KIGFX { +class COLOR4D; +} + +class wxPoint; +class wxDC; +class EDA_DRAW_PANEL; +class SCH_ITEM; +class SCH_SCREEN; +class PICKED_ITEMS_LIST; + +void SetSchItemParent( SCH_ITEM* Struct, SCH_SCREEN* Screen ); +void RotateListOfItems( PICKED_ITEMS_LIST& aItemsList, const wxPoint& rotationPoint ); +void MirrorY( PICKED_ITEMS_LIST& aItemsList, const wxPoint& aMirrorPoint ); +void MirrorX( PICKED_ITEMS_LIST& aItemsList, const wxPoint& aMirrorPoint ); + +/** + * Function MoveItemsInList + * Move a list of items to a given move vector + * @param aItemsList = list of picked items + * @param aMoveVector = the move vector value + */ +void MoveItemsInList( PICKED_ITEMS_LIST& aItemsList, const wxPoint& aMoveVector ); + +/** + * Function DeleteItemsInList + * delete schematic items in aItemsList + * deleted items are put in undo list + */ +void DeleteItemsInList( EDA_DRAW_PANEL* panel, PICKED_ITEMS_LIST& aItemsList ); + +/** + * Routine to copy a new entity of an object for each object in list and + * reposition it. + * Return the new created object list in aItemsList + */ +void DuplicateItemsInList( SCH_SCREEN* screen, PICKED_ITEMS_LIST& aItemsList, + const wxPoint& aMoveVector ); + +/** + * Routine to create a new copy of given struct. + * The new object is not put in draw list (not linked) + * + * @param aDrawStruct = the SCH_ITEM to duplicate + * @param aClone (default = false) + * if true duplicate also some parameters that must be unique + * (timestamp and sheet name) + * aClone must be false. use true only is undo/redo duplications + */ +SCH_ITEM* DuplicateStruct( SCH_ITEM* aDrawStruct, bool aClone = false ); + +void DrawDanglingSymbol( EDA_DRAW_PANEL* panel, wxDC* DC, + const wxPoint& pos, const KIGFX::COLOR4D& Color ); + +#endif /* LIST_OPERATIONS_H */ diff --git a/eeschema/menubar_libedit.cpp b/eeschema/menubar_libedit.cpp index ae40769f4d..64c1595a1b 100644 --- a/eeschema/menubar_libedit.cpp +++ b/eeschema/menubar_libedit.cpp @@ -25,7 +25,7 @@ /** * @file eeschema/menubar_libedit.cpp - * @brief (Re)Create the main menubar for the component editor frame (LibEdit) + * @brief (Re)Create the main menubar for the part editor frame (LibEdit) */ #include @@ -37,11 +37,9 @@ #include "hotkeys.h" #include "libeditframe.h" -extern int CreateNewLibAndSavePartId; - /** - * @brief (Re)Create the menubar for the component editor frame + * @brief (Re)Create the menubar for the part editor frame */ void LIB_EDIT_FRAME::ReCreateMenuBar() { @@ -64,33 +62,40 @@ void LIB_EDIT_FRAME::ReCreateMenuBar() // Menu File: wxMenu* fileMenu = new wxMenu; - // Select current library + // Creating/loading libraries AddMenuItem( fileMenu, - ID_LIBEDIT_SELECT_CURRENT_LIB, - _( "Select &Current Library" ), - _( "Select working library" ), - KiBitmap( library_xpm ) ); + ID_LIBEDIT_NEW_LIBRARY, + _( "&Create New Library" ), + _( "Creates an empty library" ), + KiBitmap( new_library_xpm ) ); + + AddMenuItem( fileMenu, + ID_LIBEDIT_ADD_LIBRARY, + _( "&Add Existing Library" ), + _( "Adds a previously created library" ), + KiBitmap( add_library_xpm ) ); + + // Separator fileMenu->AppendSeparator(); - // Save current library - text = AddHotkeyName( _( "&Save Current Library" ), g_Libedit_Hokeys_Descr, HK_SAVE_LIB ); + // Save library variants + text = AddHotkeyName( _( "&Save Library" ), g_Libedit_Hokeys_Descr, HK_SAVE_LIB ); AddMenuItem( fileMenu, - ID_LIBEDIT_SAVE_CURRENT_LIB, text, + ID_LIBEDIT_SAVE_LIBRARY, text, _( "Save the current active library" ), - KiBitmap( save_xpm ) ); + KiBitmap( save_library_xpm ) ); - // Save current library as... AddMenuItem( fileMenu, - ID_LIBEDIT_SAVE_CURRENT_LIB_AS, - _( "Save Current Library &As..." ), - _( "Save current active library as..." ), + ID_LIBEDIT_SAVE_LIBRARY_AS, + _( "&Save Library As.." ), + _( "Save the current library to a new file" ), KiBitmap( save_as_xpm ) ); AddMenuItem( fileMenu, - CreateNewLibAndSavePartId, - _( "Create &New Library and Save Current Component" ), - _( "Save current component to new library" ), - KiBitmap( new_library_xpm ) ); + ID_LIBEDIT_SAVE_ALL_LIBS, + _( "&Save All Libraries" ), + _( "Save all library changes" ), + KiBitmap( save_xpm ) ); // Separator fileMenu->AppendSeparator(); @@ -99,14 +104,14 @@ void LIB_EDIT_FRAME::ReCreateMenuBar() AddMenuItem( fileMenu, ID_LIBEDIT_GEN_PNG_FILE, _( "Create &PNG File from Screen..." ), - _( "Create a PNG file from the component displayed on screen" ), + _( "Create a PNG file from the part displayed on screen" ), KiBitmap( plot_xpm ) ); // Export as SVG file AddMenuItem( fileMenu, ID_LIBEDIT_GEN_SVG_FILE, _( "Create S&VG File..." ), - _( "Create a SVG file from the current loaded component" ), + _( "Create a SVG file from the current loaded part" ), KiBitmap( plot_svg_xpm ) ); // Separator @@ -139,16 +144,6 @@ void LIB_EDIT_FRAME::ReCreateMenuBar() _( "Redo the last undo command" ), KiBitmap( redo_xpm ) ); - // Separator - editMenu->AppendSeparator(); - - // Delete - AddMenuItem( editMenu, - ID_LIBEDIT_DELETE_ITEM_BUTT, - _( "&Delete" ), - HELP_DELETE_ITEMS, - KiBitmap( delete_xpm ) ); - // Menu View: wxMenu* viewMenu = new wxMenu; @@ -177,13 +172,77 @@ void LIB_EDIT_FRAME::ReCreateMenuBar() text = AddHotkeyName( _( "&Fit on Screen" ), g_Libedit_Hokeys_Descr, HK_ZOOM_AUTO ); AddMenuItem( viewMenu, ID_ZOOM_PAGE, text, HELP_ZOOM_FIT, KiBitmap( zoom_fit_in_page_xpm ) ); - // Separator - viewMenu->AppendSeparator(); - // Redraw text = AddHotkeyName( _( "&Redraw" ), g_Libedit_Hokeys_Descr, HK_ZOOM_REDRAW ); AddMenuItem( viewMenu, ID_ZOOM_REDRAW, text, HELP_ZOOM_REDRAW, KiBitmap( zoom_redraw_xpm ) ); + // Separator + viewMenu->AppendSeparator(); + + AddMenuItem( viewMenu, + ID_LIBEDIT_SHOW_HIDE_SEARCH_TREE, + _( "&Search tree" ), + _( "Toggles the search tree visibility" ), + KiBitmap( search_tree_xpm ) ); + + // Menu Part: + wxMenu* partMenu = new wxMenu; + + AddMenuItem( partMenu, + ID_LIBEDIT_NEW_PART, + _( "Create &New" ), + _( "Create a new empty part" ), + KiBitmap( new_component_xpm ) ); + + text = AddHotkeyName( _( "&Save Part" ), g_Libedit_Hokeys_Descr, HK_SAVE_PART ); + AddMenuItem( partMenu, + ID_LIBEDIT_SAVE_PART, + text, + _( "Saves the current part to the library" ), + KiBitmap( save_part_xpm ) ); + + partMenu->AppendSeparator(); + + AddMenuItem( partMenu, + ID_LIBEDIT_IMPORT_PART, + _( "&Import" ), + _( "Import a part to the current library" ), + KiBitmap( import_part_xpm ) ); + + AddMenuItem( partMenu, + ID_LIBEDIT_EXPORT_PART, + _( "&Export" ), + _( "Export the current part" ), + KiBitmap( export_part_xpm ) ); + + partMenu->AppendSeparator(); + + AddMenuItem( partMenu, + ID_LIBEDIT_GET_FRAME_EDIT_PART, + _( "&Properties" ), + _( "Edit part properties" ), + KiBitmap( part_properties_xpm ) ); + + AddMenuItem( partMenu, + ID_LIBEDIT_GET_FRAME_EDIT_FIELDS, + _( "&Fields" ), + _( "Edit field properties" ), + KiBitmap( edit_text_xpm ) ); + + partMenu->AppendSeparator(); + + AddMenuItem( partMenu, + ID_LIBEDIT_EDIT_PIN_BY_TABLE, + _( "Pi&n Table" ), + _( "Show pin table" ), + KiBitmap( pin_table_xpm ) ); + + AddMenuItem( partMenu, + ID_LIBEDIT_CHECK_PART, + _( "ERC" ), + _( "Check duplicate and off grid pins" ), + KiBitmap( erc_xpm ) ); + // Menu Place: wxMenu* placeMenu = new wxMenu; @@ -243,7 +302,7 @@ void LIB_EDIT_FRAME::ReCreateMenuBar() AddMenuItem( preferencesMenu, wxID_PREFERENCES, _( "General &Options" ), - _( "Set Component Editor default values and options" ), + _( "Set Part Editor default values and options" ), KiBitmap( preference_xpm ) ); // Language submenu @@ -293,6 +352,7 @@ void LIB_EDIT_FRAME::ReCreateMenuBar() menuBar->Append( fileMenu, _( "&File" ) ); menuBar->Append( editMenu, _( "&Edit" ) ); menuBar->Append( viewMenu, _( "&View" ) ); + menuBar->Append( partMenu, _( "&Part" ) ); menuBar->Append( placeMenu, _( "&Place" ) ); menuBar->Append( preferencesMenu, _( "P&references" ) ); menuBar->Append( helpMenu, _( "&Help" ) ); diff --git a/eeschema/operations_on_items_lists.cpp b/eeschema/operations_on_items_lists.cpp index 6f0b790c27..a470c5d6f7 100644 --- a/eeschema/operations_on_items_lists.cpp +++ b/eeschema/operations_on_items_lists.cpp @@ -34,7 +34,7 @@ #include #include -#include +#include #include #include #include @@ -72,7 +72,7 @@ void SetSchItemParent( SCH_ITEM* Struct, SCH_SCREEN* Screen ) } -void RotateListOfItems( PICKED_ITEMS_LIST& aItemsList, wxPoint& rotationPoint ) +void RotateListOfItems( PICKED_ITEMS_LIST& aItemsList, const wxPoint& rotationPoint ) { for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { @@ -83,7 +83,7 @@ void RotateListOfItems( PICKED_ITEMS_LIST& aItemsList, wxPoint& rotationPoint ) } -void MirrorY( PICKED_ITEMS_LIST& aItemsList, wxPoint& aMirrorPoint ) +void MirrorY( PICKED_ITEMS_LIST& aItemsList, const wxPoint& aMirrorPoint ) { for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { @@ -94,7 +94,7 @@ void MirrorY( PICKED_ITEMS_LIST& aItemsList, wxPoint& aMirrorPoint ) } -void MirrorX( PICKED_ITEMS_LIST& aItemsList, wxPoint& aMirrorPoint ) +void MirrorX( PICKED_ITEMS_LIST& aItemsList, const wxPoint& aMirrorPoint ) { for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { @@ -105,13 +105,7 @@ void MirrorX( PICKED_ITEMS_LIST& aItemsList, wxPoint& aMirrorPoint ) } -/** - * Function MoveItemsInList - * Move a list of items to a given move vector - * @param aItemsList = list of picked items - * @param aMoveVector = the move vector value - */ -void MoveItemsInList( PICKED_ITEMS_LIST& aItemsList, const wxPoint aMoveVector ) +void MoveItemsInList( PICKED_ITEMS_LIST& aItemsList, const wxPoint& aMoveVector ) { for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ ) { @@ -121,11 +115,6 @@ void MoveItemsInList( PICKED_ITEMS_LIST& aItemsList, const wxPoint aMoveVector ) } -/** - * Function DeleteItemsInList - * delete schematic items in aItemsList - * deleted items are put in undo list - */ void DeleteItemsInList( EDA_DRAW_PANEL* panel, PICKED_ITEMS_LIST& aItemsList ) { SCH_SCREEN* screen = (SCH_SCREEN*) panel->GetScreen(); @@ -182,12 +171,8 @@ void SCH_EDIT_FRAME::DeleteItem( SCH_ITEM* aItem ) } -/* Routine to copy a new entity of an object for each object in list and - * reposition it. - * Return the new created object list in aItemsList - */ void DuplicateItemsInList( SCH_SCREEN* screen, PICKED_ITEMS_LIST& aItemsList, - const wxPoint aMoveVector ) + const wxPoint& aMoveVector ) { SCH_ITEM* newitem; @@ -238,16 +223,6 @@ void DuplicateItemsInList( SCH_SCREEN* screen, PICKED_ITEMS_LIST& aItemsList, } -/** - * Function DuplicateStruct - * Routine to create a new copy of given struct. - * The new object is not put in draw list (not linked) - * @param aDrawStruct = the SCH_ITEM to duplicate - * @param aClone (default = false) - * if true duplicate also some parameters that must be unique - * (timestamp and sheet name) - * aClone must be false. use true only is undo/redo duplications - */ SCH_ITEM* DuplicateStruct( SCH_ITEM* aDrawStruct, bool aClone ) { wxCHECK_MSG( aDrawStruct != NULL, NULL, diff --git a/eeschema/pinedit.cpp b/eeschema/pinedit.cpp index ef1ae4a6f5..fd041ed64f 100644 --- a/eeschema/pinedit.cpp +++ b/eeschema/pinedit.cpp @@ -286,7 +286,6 @@ void LIB_EDIT_FRAME::PlacePin() SaveCopyInUndoList( part ); m_canvas->SetMouseCapture( NULL, NULL ); - OnModify(); cur_pin->Move( newpos ); if( cur_pin->IsNew() ) @@ -314,6 +313,7 @@ void LIB_EDIT_FRAME::PlacePin() m_drawItem = NULL; + OnModify(); m_canvas->Refresh(); } diff --git a/eeschema/project_rescue.cpp b/eeschema/project_rescue.cpp index 48303d0bef..0a482d1c78 100644 --- a/eeschema/project_rescue.cpp +++ b/eeschema/project_rescue.cpp @@ -409,7 +409,6 @@ wxString RESCUE_SYMBOL_LIB_TABLE_CANDIDATE::GetActionDescription() const bool RESCUE_SYMBOL_LIB_TABLE_CANDIDATE::PerformAction( RESCUER* aRescuer ) { LIB_PART new_part( *m_cache_candidate ); - new_part.SetLibId( m_new_id ); new_part.SetName( m_new_id.GetLibItemName() ); new_part.RemoveAllAliases(); aRescuer->AddPart( &new_part ); diff --git a/eeschema/project_rescue.h b/eeschema/project_rescue.h index 0e6d575e9a..c01c2d7bb6 100644 --- a/eeschema/project_rescue.h +++ b/eeschema/project_rescue.h @@ -309,7 +309,6 @@ class LEGACY_RESCUER : public RESCUER { private: std::unique_ptr m_rescue_lib; - PART_LIBS* m_libs; public: LEGACY_RESCUER( SCH_EDIT_FRAME& aEditFrame, PROJECT& aProject ) : diff --git a/eeschema/protos.h b/eeschema/protos.h deleted file mode 100644 index 441c36d16c..0000000000 --- a/eeschema/protos.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2007 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 2014 KiCad Developers, see CHANGELOG.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 - */ - - -#ifndef __PROTOS_H__ -#define __PROTOS_H__ - -class EDA_DRAW_PANEL; -class PICKED_ITEMS_LIST; -class SCH_ITEM; - - -// operations_on_item_lists.cpp -void DeleteItemsInList( EDA_DRAW_PANEL* panel, PICKED_ITEMS_LIST& aItemsList ); - -/** - * Function DuplicateStruct - * creates a new copy of given struct. - * @param aDrawStruct = the SCH_ITEM to duplicate - * @param aClone (defualt = true) - * if true duplicate also some parameters that must be unique - * (timestamp and sheet name) - * aClone must be false. use true only is undo/redo duplications - */ -SCH_ITEM* DuplicateStruct( SCH_ITEM* DrawStruct, bool aClone = false ); - - -/****************/ -/* EEREDRAW.CPP */ -/****************/ -void DrawDanglingSymbol( EDA_DRAW_PANEL* panel, wxDC* DC, - const wxPoint& pos, COLOR4D Color ); - - -#endif /* __PROTOS_H__ */ diff --git a/eeschema/sch_base_frame.cpp b/eeschema/sch_base_frame.cpp index 11554d7231..028731b20a 100644 --- a/eeschema/sch_base_frame.cpp +++ b/eeschema/sch_base_frame.cpp @@ -268,37 +268,7 @@ void SCH_BASE_FRAME::OnEditSymbolLibTable( wxCommandEvent& aEvent ) if( dlg.ShowModal() == wxID_CANCEL ) return; - try - { - FILE_OUTPUTFORMATTER sf( SYMBOL_LIB_TABLE::GetGlobalTableFileName() ); - - SYMBOL_LIB_TABLE::GetGlobalLibTable().Format( &sf, 0 ); - } - catch( const IO_ERROR& ioe ) - { - wxString msg = wxString::Format( _( "Error occurred saving the global symbol library " - "table:\n\n%s" ), - GetChars( ioe.What().GetData() ) ); - wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR ); - } - - if( !Prj().GetProjectName().IsEmpty() ) - { - wxFileName fn( Prj().GetProjectPath(), SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() ); - - try - { - Prj().SchSymbolLibTable()->Save( fn.GetFullPath() ); - } - catch( const IO_ERROR& ioe ) - { - wxString msg = wxString::Format( _( "Error occurred saving project specific " - "symbol library table:\n\n%s" ), - GetChars( ioe.What() ) ); - wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR ); - } - } - + saveSymbolLibTables( true, true ); LIB_EDIT_FRAME* editor = (LIB_EDIT_FRAME*) Kiway().Player( FRAME_SCH_LIB_EDITOR, false ); @@ -335,3 +305,47 @@ LIB_PART* SCH_BASE_FRAME::GetLibPart( const LIB_ID& aLibId, bool aUseCacheLib, b return SchGetLibPart( aLibId, Prj().SchSymbolLibTable(), cache, this, aShowErrorMsg ); } + + +bool SCH_BASE_FRAME::saveSymbolLibTables( bool aGlobal, bool aProject ) +{ + bool success = true; + + if( aGlobal ) + { + try + { + FILE_OUTPUTFORMATTER sf( SYMBOL_LIB_TABLE::GetGlobalTableFileName() ); + + SYMBOL_LIB_TABLE::GetGlobalLibTable().Format( &sf, 0 ); + } + catch( const IO_ERROR& ioe ) + { + success = false; + wxString msg = wxString::Format( _( "Error occurred saving the global symbol library " + "table:\n\n%s" ), + GetChars( ioe.What().GetData() ) ); + wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR ); + } + } + + if( aProject && !Prj().GetProjectName().IsEmpty() ) + { + wxFileName fn( Prj().GetProjectPath(), SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() ); + + try + { + Prj().SchSymbolLibTable()->Save( fn.GetFullPath() ); + } + catch( const IO_ERROR& ioe ) + { + success = false; + wxString msg = wxString::Format( _( "Error occurred saving project specific " + "symbol library table:\n\n%s" ), + GetChars( ioe.What() ) ); + wxMessageBox( msg, _( "File Save Error" ), wxOK | wxICON_ERROR ); + } + } + + return success; +} diff --git a/eeschema/sch_base_frame.h b/eeschema/sch_base_frame.h index ae673f1b41..030de47feb 100644 --- a/eeschema/sch_base_frame.h +++ b/eeschema/sch_base_frame.h @@ -201,7 +201,7 @@ public: const LIB_ID* aHighlight = nullptr, bool aAllowFields = true ); - void OnEditSymbolLibTable( wxCommandEvent& aEvent ); + virtual void OnEditSymbolLibTable( wxCommandEvent& aEvent ); /** * Load symbol from symbol library table. @@ -281,6 +281,15 @@ protected: * false on cancel */ bool SelectPartNameToLoad( wxString& aLibrary, wxString& aBufName ); + + /** + * Saves Symbol Library Tables to disk. + * + * @param aGlobal when true, the Global Table is saved. + * @param aProject when true, the Project Table is saved. + * @return True when all requested actions succeeded. + */ + bool saveSymbolLibTables( bool aGlobal, bool aProject ); }; #endif // SCH_BASE_FRAME_H_ diff --git a/eeschema/sch_legacy_plugin.cpp b/eeschema/sch_legacy_plugin.cpp index e581272a14..04de9889d9 100644 --- a/eeschema/sch_legacy_plugin.cpp +++ b/eeschema/sch_legacy_plugin.cpp @@ -2476,30 +2476,22 @@ LIB_PART* SCH_LEGACY_PLUGIN_CACHE::loadPart( FILE_LINE_READER& aReader ) part->SetUnitCount( 1 ); // Copy part name and prefix. - LIB_FIELD& value = part->GetValueField(); // The root alias is added to the alias list by SetName() which is called by SetText(). if( name.IsEmpty() ) { - part->m_name = "~"; - value.SetText( "~" ); + part->SetName( "~" ); } else if( name[0] != '~' ) { - part->m_name = name; - value.SetText( name ); + part->SetName( name ); } else { - name = name.Right( name.Length() - 1 ); - part->m_name = name; - value.SetText( name ); - value.SetVisible( false ); + part->SetName( name.Right( name.Length() - 1 ) ); + part->GetValueField().SetVisible( false ); } - // Don't set the library alias, this is determined by the symbol library table. - part->SetLibId( LIB_ID( wxEmptyString, part->GetName() ) ); - // There are some code paths in SetText() that do not set the root alias to the // alias list so add it here if it didn't get added by SetText(). if( !part->HasAlias( part->GetName() ) ) @@ -2766,7 +2758,7 @@ void SCH_LEGACY_PLUGIN_CACHE::loadField( std::unique_ptr< LIB_PART >& aPart, // Ensure the VALUE field = the part name (can be not the case // with malformed libraries: edited by hand, or converted from other tools) if( fixedField->GetId() == VALUE ) - fixedField->m_Text = aPart->m_name; + fixedField->m_Text = aPart->GetName(); } else { diff --git a/eeschema/sch_line.cpp b/eeschema/sch_line.cpp index cac70ec01e..4e3246c2ab 100644 --- a/eeschema/sch_line.cpp +++ b/eeschema/sch_line.cpp @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/eeschema/sch_text.cpp b/eeschema/sch_text.cpp index b38400fa68..e94a183a35 100644 --- a/eeschema/sch_text.cpp +++ b/eeschema/sch_text.cpp @@ -40,7 +40,7 @@ #include #include -#include +#include #include #include diff --git a/eeschema/schedit.cpp b/eeschema/schedit.cpp index e33743b325..102f1fcbe7 100644 --- a/eeschema/schedit.cpp +++ b/eeschema/schedit.cpp @@ -40,7 +40,7 @@ #include #include -#include +#include #include #include #include diff --git a/eeschema/schematic_undo_redo.cpp b/eeschema/schematic_undo_redo.cpp index ecc288bfb2..09a83a6bce 100644 --- a/eeschema/schematic_undo_redo.cpp +++ b/eeschema/schematic_undo_redo.cpp @@ -32,7 +32,7 @@ #include #include -#include +#include #include #include #include diff --git a/eeschema/schframe.cpp b/eeschema/schframe.cpp index 9800551956..0cc8f0d86a 100644 --- a/eeschema/schframe.cpp +++ b/eeschema/schframe.cpp @@ -322,8 +322,6 @@ BEGIN_EVENT_TABLE( SCH_EDIT_FRAME, EDA_DRAW_FRAME ) EVT_MENU_RANGE( ID_SELECT_ITEM_START, ID_SELECT_ITEM_END, SCH_EDIT_FRAME::OnSelectItem ) /* Handle user interface update events. */ - EVT_UPDATE_UI( wxID_CUT, SCH_EDIT_FRAME::OnUpdateBlockSelected ) - EVT_UPDATE_UI( wxID_COPY, SCH_EDIT_FRAME::OnUpdateBlockSelected ) EVT_UPDATE_UI( wxID_PASTE, SCH_EDIT_FRAME::OnUpdatePaste ) EVT_UPDATE_UI( ID_TB_OPTIONS_HIDDEN_PINS, SCH_EDIT_FRAME::OnUpdateHiddenPins ) EVT_UPDATE_UI( ID_TB_OPTIONS_BUS_WIRES_ORIENT, SCH_EDIT_FRAME::OnUpdateBusOrientation ) @@ -783,14 +781,6 @@ void SCH_EDIT_FRAME::OnModify() } -void SCH_EDIT_FRAME::OnUpdateBlockSelected( wxUpdateUIEvent& event ) -{ - bool enable = ( GetScreen() && GetScreen()->m_BlockLocate.GetCommand() == BLOCK_MOVE ); - - event.Enable( enable ); -} - - void SCH_EDIT_FRAME::OnUpdatePaste( wxUpdateUIEvent& event ) { event.Enable( m_blockItems.GetCount() > 0 ); diff --git a/eeschema/schframe.h b/eeschema/schframe.h index 86abc4a063..e80e9bbeba 100644 --- a/eeschema/schframe.h +++ b/eeschema/schframe.h @@ -869,7 +869,6 @@ private: void OnCopySchematicItemRequest( wxCommandEvent& event ); /* User interface update event handlers. */ - void OnUpdateBlockSelected( wxUpdateUIEvent& event ); void OnUpdatePaste( wxUpdateUIEvent& event ); void OnUpdateHiddenPins( wxUpdateUIEvent& event ); void OnUpdateBusOrientation( wxUpdateUIEvent& event ); diff --git a/eeschema/tool_lib.cpp b/eeschema/tool_lib.cpp index 2a06cc832c..de4f46c8dd 100644 --- a/eeschema/tool_lib.cpp +++ b/eeschema/tool_lib.cpp @@ -45,11 +45,6 @@ #endif -extern int ExportPartId; -extern int ImportPartId; -extern int CreateNewLibAndSavePartId; - - void LIB_EDIT_FRAME::ReCreateVToolbar() { if( m_drawToolBar != NULL ) @@ -108,55 +103,49 @@ void LIB_EDIT_FRAME::ReCreateHToolbar() KICAD_AUI_TB_STYLE | wxAUI_TB_HORZ_LAYOUT ); // Set up toolbar - m_mainToolBar->AddTool( ID_LIBEDIT_SELECT_CURRENT_LIB, wxEmptyString, KiBitmap( library_xpm ), - _( "Select working library" ) ); + m_mainToolBar->AddTool( ID_LIBEDIT_NEW_LIBRARY, wxEmptyString, + KiBitmap( new_library_xpm ), + _( "Create a new library" ) ); - m_mainToolBar->AddTool( ID_LIBEDIT_SAVE_CURRENT_LIB, wxEmptyString, + m_mainToolBar->AddTool( ID_LIBEDIT_ADD_LIBRARY, wxEmptyString, + KiBitmap( add_library_xpm ), + _( "Add an existing library" ) ); + + m_mainToolBar->AddTool( ID_LIBEDIT_SAVE_LIBRARY, wxEmptyString, KiBitmap( save_library_xpm ), - _( "Save into current library" ) ); - - m_mainToolBar->AddTool( CreateNewLibAndSavePartId, wxEmptyString, KiBitmap( new_library_xpm ), - _( "Save current component to new library" ) ); - - m_mainToolBar->AddTool( ID_TO_LIBVIEW, wxEmptyString, KiBitmap( library_browse_xpm ), - HELP_RUN_LIB_VIEWER ); - - m_mainToolBar->AddSeparator(); - m_mainToolBar->AddTool( ID_LIBEDIT_DELETE_PART, wxEmptyString, KiBitmap( delete_xpm ), - _( "Delete component in current library" ) ); + _( "Save current library" ) ); m_mainToolBar->AddSeparator(); m_mainToolBar->AddTool( ID_LIBEDIT_NEW_PART, wxEmptyString, KiBitmap( new_component_xpm ), - _( "Create new component" ) ); + _( "Create new part" ) ); - m_mainToolBar->AddTool( ID_LIBEDIT_SELECT_PART, wxEmptyString, - KiBitmap( import_cmp_from_lib_xpm ), - _( "Load component from current library" ) ); + m_mainToolBar->AddTool( ID_LIBEDIT_SAVE_PART, wxEmptyString, + KiBitmap( save_part_xpm ), + _( "Save current part" ) ); - m_mainToolBar->AddTool( ID_LIBEDIT_NEW_PART_FROM_EXISTING, wxEmptyString, - KiBitmap( copycomponent_xpm ), - _( "Create new component from current component" ) ); + m_mainToolBar->AddTool( ID_LIBEDIT_IMPORT_PART, wxEmptyString, KiBitmap( import_part_xpm ), + _( "Import part" ) ); - m_mainToolBar->AddTool( ID_LIBEDIT_SAVE_CURRENT_PART, wxEmptyString, - KiBitmap( save_part_in_mem_xpm ), - _( "Update current component in current library" ) ); - - m_mainToolBar->AddTool( ImportPartId, wxEmptyString, KiBitmap( import_xpm ), - _( "Import component" ) ); - - m_mainToolBar->AddTool( ExportPartId, wxEmptyString, KiBitmap( export_xpm ), - _( "Export component" ) ); + m_mainToolBar->AddTool( ID_LIBEDIT_EXPORT_PART, wxEmptyString, KiBitmap( export_part_xpm ), + _( "Export part" ) ); m_mainToolBar->AddSeparator(); - msg = AddHotkeyName( _( "Undo last command" ), g_Libedit_Hokeys_Descr, HK_UNDO, IS_COMMENT ); + + m_mainToolBar->AddTool( wxID_PASTE, wxEmptyString, KiBitmap( paste_xpm ), + _( "Paste" ) ); + + m_mainToolBar->AddSeparator(); + + msg = AddHotkeyName( HELP_UNDO, g_Libedit_Hokeys_Descr, HK_UNDO, IS_COMMENT ); m_mainToolBar->AddTool( wxID_UNDO, wxEmptyString, KiBitmap( undo_xpm ), msg ); - msg = AddHotkeyName( _( "Redo last command" ), g_Libedit_Hokeys_Descr, HK_REDO, - IS_COMMENT ); + + msg = AddHotkeyName( HELP_REDO, g_Libedit_Hokeys_Descr, HK_REDO, IS_COMMENT ); m_mainToolBar->AddTool( wxID_REDO, wxEmptyString, KiBitmap( redo_xpm ), msg ); m_mainToolBar->AddSeparator(); + m_mainToolBar->AddTool( ID_LIBEDIT_GET_FRAME_EDIT_PART, wxEmptyString, - KiBitmap( part_properties_xpm ), _( "Edit component properties" ) ); + KiBitmap( part_properties_xpm ), _( "Edit part properties" ) ); m_mainToolBar->AddTool( ID_LIBEDIT_GET_FRAME_EDIT_FIELDS, wxEmptyString, KiBitmap( text_xpm ), @@ -250,5 +239,9 @@ void LIB_EDIT_FRAME::CreateOptionToolbar() KiBitmap( pin_show_etype_xpm ), _( "Show pins electrical type" ), wxITEM_CHECK ); + m_optionsToolBar->AddTool( ID_LIBEDIT_SHOW_HIDE_SEARCH_TREE, wxEmptyString, + KiBitmap( search_tree_xpm ), + _( "Toggles the search tree" ), wxITEM_CHECK ); + m_optionsToolBar->Realize(); } diff --git a/eeschema/tool_sch.cpp b/eeschema/tool_sch.cpp index a622db49d4..0ede8eead5 100644 --- a/eeschema/tool_sch.cpp +++ b/eeschema/tool_sch.cpp @@ -80,12 +80,6 @@ void SCH_EDIT_FRAME::ReCreateHToolbar() m_mainToolBar->AddSeparator(); - m_mainToolBar->AddTool( wxID_CUT, wxEmptyString, KiBitmap( cut_xpm ), - _( "Cut selected item" ) ); - - m_mainToolBar->AddTool( wxID_COPY, wxEmptyString, KiBitmap( copy_xpm ), - _( "Copy selected item" ) ); - m_mainToolBar->AddTool( wxID_PASTE, wxEmptyString, KiBitmap( paste_xpm ), _( "Paste" ) ); diff --git a/eeschema/widgets/cmp_tree_pane.cpp b/eeschema/widgets/cmp_tree_pane.cpp new file mode 100644 index 0000000000..c1b229b105 --- /dev/null +++ b/eeschema/widgets/cmp_tree_pane.cpp @@ -0,0 +1,103 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2017 CERN + * @author Maciej Suminski + * + * 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 3 + * 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: + * https://www.gnu.org/licenses/gpl-3.0.html + * or you may search the http://www.gnu.org website for the version 3 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "cmp_tree_pane.h" + +#include +#include +#include +#include +#include + +CMP_TREE_PANE::CMP_TREE_PANE( LIB_EDIT_FRAME* aParent, LIB_MANAGER* aLibMgr ) + : wxPanel( aParent ), + m_libEditFrame( aParent ), + m_libMgr( aLibMgr ) +{ + // Create widgets + wxBoxSizer* boxSizer = new wxBoxSizer( wxVERTICAL ); + + m_libMgr->Sync(); + m_tree = new COMPONENT_TREE( this, &SYMBOL_LIB_TABLE::GetGlobalLibTable(), + m_libMgr->GetAdapter(), COMPONENT_TREE::SEARCH ); + + boxSizer->Add( m_tree, 1, wxEXPAND | wxALL, 5 ); + + SetSizer( boxSizer ); + Layout(); + boxSizer->Fit( this ); + + // Setup right click-context menus + std::unique_ptr menuLibrary = std::make_unique(); + menuLibrary->Append( ID_LIBEDIT_NEW_LIBRARY, _( "New library..." ) ); + menuLibrary->Append( ID_LIBEDIT_ADD_LIBRARY, _( "Add existing library..." ) ); + menuLibrary->Append( ID_LIBEDIT_SAVE_LIBRARY, _( "Save library" ) ); + menuLibrary->Append( ID_LIBEDIT_SAVE_LIBRARY_AS, _( "Save library as..." ) ); + menuLibrary->Append( ID_LIBEDIT_REVERT_LIBRARY, _( "Revert library" ) ); + menuLibrary->AppendSeparator(); + menuLibrary->Append( ID_LIBEDIT_NEW_PART, _( "New part..." ) ); + menuLibrary->Append( ID_LIBEDIT_IMPORT_PART, _( "Import part..." ) ); + menuLibrary->Append( ID_LIBEDIT_PASTE_PART, _( "Paste part" ) ); + + std::unique_ptr menuPart = std::make_unique(); + menuPart->Append( ID_LIBEDIT_EDIT_PART, _( "Edit" ) ); + menuPart->Append( ID_LIBEDIT_REMOVE_PART, _( "Remove" ) ); + menuPart->Append( ID_LIBEDIT_EXPORT_PART, _( "Export..." ) ); + menuPart->Append( ID_LIBEDIT_SAVE_PART, _( "Save" ) ); + menuPart->Append( ID_LIBEDIT_REVERT_PART, _( "Revert" ) ); + menuPart->AppendSeparator(); + menuPart->Append( ID_LIBEDIT_CUT_PART, _( "Cut" ) ); + menuPart->Append( ID_LIBEDIT_COPY_PART, _( "Copy" ) ); + menuPart->Append( ID_LIBEDIT_DUPLICATE_PART, _( "Duplicate" ) ); + menuPart->AppendSeparator(); + + // Menu displayed when nothing is selected + std::unique_ptr menuNoSelection = std::make_unique(); + menuNoSelection->Append( ID_LIBEDIT_NEW_LIBRARY, _( "New library..." ) ); + menuNoSelection->Append( ID_LIBEDIT_ADD_LIBRARY, _( "Add existing library..." ) ); + + m_tree->SetMenu( CMP_TREE_NODE::LIBID, std::move( menuPart ) ); + m_tree->SetMenu( CMP_TREE_NODE::LIB, std::move( menuLibrary ) ); + m_tree->SetMenu( CMP_TREE_NODE::INVALID, std::move( menuNoSelection ) ); + + // Event handlers + Bind( COMPONENT_SELECTED, &CMP_TREE_PANE::onComponentSelected, this ); +} + + +CMP_TREE_PANE::~CMP_TREE_PANE() +{ + delete m_tree; +} + + +void CMP_TREE_PANE::onComponentSelected( wxCommandEvent& aEvent ) +{ + // Repost the event + wxCommandEvent evt( ID_LIBEDIT_EDIT_PART ); + // I cannot figure out why the two methods below do not work.. + //wxPostEvent( libEditFrame, evt ); + //wxQueueEvent( m_libEditFrame, new wxCommandEvent( ID_LIBEDIT_EDIT_PART ) ); + m_libEditFrame->OnEditPart( evt ); +} diff --git a/eeschema/widgets/cmp_tree_pane.h b/eeschema/widgets/cmp_tree_pane.h new file mode 100644 index 0000000000..da76d88173 --- /dev/null +++ b/eeschema/widgets/cmp_tree_pane.h @@ -0,0 +1,57 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2017 CERN + * @author Maciej Suminski + * + * 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 3 + * 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: + * https://www.gnu.org/licenses/gpl-3.0.html + * or you may search the http://www.gnu.org website for the version 3 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef CMP_TREE_PANE_H +#define CMP_TREE_PANE_H + +#include + +class COMPONENT_TREE; +class LIB_EDIT_FRAME; +class LIB_MANAGER; + +/** + * Library Editor pane with component tree and symbol library table selector. + */ +class CMP_TREE_PANE : public wxPanel +{ +public: + CMP_TREE_PANE( LIB_EDIT_FRAME* aParent, LIB_MANAGER* aLibMgr ); + ~CMP_TREE_PANE(); + + COMPONENT_TREE* GetCmpTree() const + { + return m_tree; + } + +protected: + void onSymLibTableSelected( wxCommandEvent& aEvent ); + void onComponentSelected( wxCommandEvent& aEvent ); + + LIB_EDIT_FRAME* m_libEditFrame; + COMPONENT_TREE* m_tree; ///< component search tree widget + LIB_MANAGER* m_libMgr; +}; + +#endif /* CMP_TREE_PANE_H */ diff --git a/eeschema/widgets/component_tree.cpp b/eeschema/widgets/component_tree.cpp index fe2e245756..8b6724d077 100644 --- a/eeschema/widgets/component_tree.cpp +++ b/eeschema/widgets/component_tree.cpp @@ -36,13 +36,17 @@ COMPONENT_TREE::COMPONENT_TREE( wxWindow* aParent, SYMBOL_LIB_TABLE* aSymLibTable, - CMP_TREE_MODEL_ADAPTER::PTR& aAdapter, WIDGETS aWidgets ) + CMP_TREE_MODEL_ADAPTER_BASE::PTR& aAdapter, WIDGETS aWidgets ) : wxPanel( aParent ), m_sym_lib_table( aSymLibTable ), m_adapter( aAdapter ), m_query_ctrl( nullptr ), - m_details_ctrl( nullptr ) + m_details_ctrl( nullptr ), + m_filtering( false ) { + // create space for context menu pointers, INVALID is the max value + m_menus.resize( CMP_TREE_NODE::TYPE::INVALID + 1 ); + auto sizer = new wxBoxSizer( wxVERTICAL ); // Search text control @@ -89,6 +93,7 @@ COMPONENT_TREE::COMPONENT_TREE( wxWindow* aParent, SYMBOL_LIB_TABLE* aSymLibTabl m_tree_ctrl->Bind( wxEVT_DATAVIEW_ITEM_ACTIVATED, &COMPONENT_TREE::onTreeActivate, this ); m_tree_ctrl->Bind( wxEVT_DATAVIEW_SELECTION_CHANGED, &COMPONENT_TREE::onTreeSelect, this ); + m_tree_ctrl->Bind( wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, &COMPONENT_TREE::onContextMenu, this ); Bind( COMPONENT_PRESELECTED, &COMPONENT_TREE::onPreselect, this ); @@ -127,6 +132,12 @@ LIB_ID COMPONENT_TREE::GetSelectedLibId( int* aUnit ) const } +void COMPONENT_TREE::SelectLibId( const LIB_ID& aLibId ) +{ + selectIfValid( m_adapter->FindItem( aLibId ) ); +} + + void COMPONENT_TREE::selectIfValid( const wxDataViewItem& aTreeId ) { if( aTreeId.IsOk() ) @@ -154,9 +165,24 @@ void COMPONENT_TREE::postSelectEvent() void COMPONENT_TREE::onQueryText( wxCommandEvent& aEvent ) { + // Store the state + if( !m_filtering ) + { + m_selection = m_tree_ctrl->GetSelection(); + saveExpandFlag(); + } + m_adapter->UpdateSearchString( m_query_ctrl->GetLineText( 0 ) ); + m_filtering = !m_query_ctrl->IsEmpty(); postPreselectEvent(); + // Restore the state + if( !m_filtering ) + { + selectIfValid( m_selection ); + restoreExpandFlag(); + } + // Required to avoid interaction with SetHint() // See documentation for wxTextEntry::SetHint aEvent.Skip(); @@ -236,5 +262,46 @@ void COMPONENT_TREE::onPreselect( wxCommandEvent& aEvent ) } +void COMPONENT_TREE::onContextMenu( wxDataViewEvent& aEvent ) +{ + auto const sel = m_tree_ctrl->GetSelection(); + auto type = sel.IsOk() ? m_adapter->GetTypeFor( sel ) : CMP_TREE_NODE::INVALID; + + if( m_menus[type] ) + { + m_menuActive = true; + PopupMenu( m_menus[type].get() ); + m_menuActive = false; + } +} + + +void COMPONENT_TREE::saveExpandFlag() +{ + wxDataViewItemArray items; + m_adapter->GetChildren( wxDataViewItem( nullptr ), items ); + m_expanded.clear(); + + for( const auto& item : items ) + { + if( m_tree_ctrl->IsExpanded( item ) ) + m_expanded.push_back( item ); + } +} + + +void COMPONENT_TREE::restoreExpandFlag() +{ + m_tree_ctrl->Freeze(); + + for( const auto& item : m_expanded ) + { + m_tree_ctrl->Expand( item ); + } + + m_tree_ctrl->Thaw(); +} + + wxDEFINE_EVENT( COMPONENT_PRESELECTED, wxCommandEvent ); wxDEFINE_EVENT( COMPONENT_SELECTED, wxCommandEvent ); diff --git a/eeschema/widgets/component_tree.h b/eeschema/widgets/component_tree.h index 4f9084d010..0917e4f951 100644 --- a/eeschema/widgets/component_tree.h +++ b/eeschema/widgets/component_tree.h @@ -47,7 +47,7 @@ public: enum WIDGETS { NONE = 0x00, SEARCH = 0x01, DETAILS = 0x02, ALL = 0xFF }; COMPONENT_TREE( wxWindow* aParent, SYMBOL_LIB_TABLE* aSymLibTable, - CMP_TREE_MODEL_ADAPTER::PTR& aAdapter, WIDGETS aWidgets = ALL ); + CMP_TREE_MODEL_ADAPTER_BASE::PTR& aAdapter, WIDGETS aWidgets = ALL ); /** * For multi-unit components, if the user selects the component itself @@ -60,6 +60,32 @@ public: */ LIB_ID GetSelectedLibId( int* aUnit = nullptr ) const; + /** + * Select a part in the tree widget. + * + * @param aLibId is the identifier of part to be selected. + */ + void SelectLibId( const LIB_ID& aLibId ); + + /** + * Associates a right click context menu for a specific node type. + * @param aType is the node type to have a menu associated. + * @param aMenu is the associated menu. + */ + void SetMenu( CMP_TREE_NODE::TYPE aType, std::unique_ptr aMenu ) + { + m_menus[aType] = std::move( aMenu ); + } + + /** + * Returns the status of right-click context menu. + * @return True in case a right-click context menu is active. + */ + bool IsMenuActive() const + { + return m_menuActive; + } + protected: /** * If a wxDataViewitem is valid, select it and post a selection event. @@ -86,12 +112,36 @@ protected: void onDetailsLink( wxHtmlLinkEvent& aEvent ); void onPreselect( wxCommandEvent& aEvent ); + void onContextMenu( wxDataViewEvent& aEvent ); + + /** + * Store the list of expanded nodes in the tree widget. + */ + void saveExpandFlag(); + + /** + * Restore the expanded nodes in the tree widget. + */ + void restoreExpandFlag(); SYMBOL_LIB_TABLE* m_sym_lib_table; - CMP_TREE_MODEL_ADAPTER::PTR m_adapter; + CMP_TREE_MODEL_ADAPTER_BASE::PTR m_adapter; + wxTextCtrl* m_query_ctrl; wxDataViewCtrl* m_tree_ctrl; wxHtmlWindow* m_details_ctrl; + + ///> Right click context menus for each tree level + std::vector> m_menus; + + ///> Flag indicating whether a right-click context menu is active + bool m_menuActive; + + bool m_filtering; + + ///> List of expanded nodes + std::vector m_expanded; + wxDataViewItem m_selection; }; ///> Custom event sent when a new component is preselected diff --git a/eeschema/widgets/widget_eeschema_color_config.h b/eeschema/widgets/widget_eeschema_color_config.h index 6f9fb8a076..a9df2c715f 100644 --- a/eeschema/widgets/widget_eeschema_color_config.h +++ b/eeschema/widgets/widget_eeschema_color_config.h @@ -43,7 +43,6 @@ class WIDGET_EESCHEMA_COLOR_CONFIG : public wxPanel { private: EDA_DRAW_FRAME* m_drawFrame; - wxColourPickerCtrl* m_SelBgColor; wxBoxSizer* m_mainBoxSizer; // Creates the controls and sizers diff --git a/include/bitmaps.h b/include/bitmaps.h index 848dc5c596..3442ab633e 100644 --- a/include/bitmaps.h +++ b/include/bitmaps.h @@ -48,6 +48,7 @@ EXTERN_BITMAP( add_hierarchical_subsheet_xpm ) EXTERN_BITMAP( add_hierar_pin_xpm ) EXTERN_BITMAP( add_junction_xpm ) EXTERN_BITMAP( add_keepout_area_xpm ) +EXTERN_BITMAP( add_library_xpm ) EXTERN_BITMAP( add_line2bus_xpm ) EXTERN_BITMAP( add_line_label_xpm ) EXTERN_BITMAP( add_line_xpm ) @@ -158,6 +159,7 @@ EXTERN_BITMAP( export_dsn_xpm ) EXTERN_BITMAP( export_idf_xpm ) EXTERN_BITMAP( export_footprint_names_xpm ) EXTERN_BITMAP( export_module_xpm ) +EXTERN_BITMAP( export_part_xpm ) EXTERN_BITMAP( export_xpm ) EXTERN_BITMAP( fabrication_xpm ) EXTERN_BITMAP( file_footprint_xpm ) @@ -216,6 +218,7 @@ EXTERN_BITMAP( import_cmp_from_lib_xpm ) EXTERN_BITMAP( import_footprint_names_xpm ) EXTERN_BITMAP( import_hierarchical_label_xpm ) EXTERN_BITMAP( import_module_xpm ) +EXTERN_BITMAP( import_part_xpm ) EXTERN_BITMAP( import_setup_xpm ) EXTERN_BITMAP( import_xpm ) EXTERN_BITMAP( import3d_xpm ) @@ -434,10 +437,12 @@ EXTERN_BITMAP( rotate_neg_z_xpm ) EXTERN_BITMAP( rotate_pos_z_xpm ) EXTERN_BITMAP( save_as_xpm ) EXTERN_BITMAP( save_library_xpm ) +EXTERN_BITMAP( save_part_xpm ) EXTERN_BITMAP( save_part_in_mem_xpm ) EXTERN_BITMAP( save_project_xpm ) EXTERN_BITMAP( save_setup_xpm ) EXTERN_BITMAP( save_xpm ) +EXTERN_BITMAP( search_tree_xpm ) EXTERN_BITMAP( select_grid_xpm ) EXTERN_BITMAP( select_layer_pair_xpm ) EXTERN_BITMAP( select_w_layer_xpm ) diff --git a/include/confirm.h b/include/confirm.h index 6dab366cf6..5769f7ecec 100644 --- a/include/confirm.h +++ b/include/confirm.h @@ -32,6 +32,7 @@ #define __INCLUDE__CONFIRM_H__ #include +#include /** * Function DisplayExitDialog @@ -121,4 +122,30 @@ void DisplayHtmlInfoMessage( wxWindow* parent, const wxString& title, const wxSize& size = wxDefaultSize ); +/** + * Displays a dialog with radioboxes asking the user to select an option. + * @param aParent is the parent window. + * @param aTitle is the dialog title. + * @param aMessage is a text label displayed in the first row of the dialog. + * @param aOptions is a vector of possible options. + * @return Index of the selected option or -1 when the dialog has been cancelled. + */ +int SelectSingleOption( wxWindow* aParent, const wxString& aTitle, const wxString& aMessage, + const wxArrayString& aOptions ); + +/** + * Displays a dialog with checkboxes asking the user to select one or more options. + * @param aParent is the parent window. + * @param aTitle is the dialog title. + * @param aMessage is a text label displayed in the first row of the dialog. + * @param aOptions is a vector of possible options. + * @param aDefaultState is the default state for the checkboxes. + * @return Vector containing indices of the selected option. + */ +std::pair> SelectMultipleOptions( wxWindow* aParent, const wxString& aTitle, + const wxString& aMessage, const wxArrayString& aOptions, bool aDefaultState = false ); + +std::pair> SelectMultipleOptions( wxWindow* aParent, const wxString& aTitle, + const wxString& aMessage, const std::vector& aOptions, bool aDefaultState = false ); + #endif /* __INCLUDE__CONFIRM_H__ */