diff --git a/common/class_layer_box_selector.cpp b/common/class_layer_box_selector.cpp index bfabbf7ff3..e2ef3fc538 100644 --- a/common/class_layer_box_selector.cpp +++ b/common/class_layer_box_selector.cpp @@ -143,7 +143,7 @@ void LAYER_BOX_SELECTOR::Resync() layername = board->GetLayerName( layerid ); if( m_layerhotkeys && m_hotkeys != NULL ) - layername = AddHotkeyName( layername, m_hotkeys, layerhk[layerid], false ); + layername = AddHotkeyName( layername, m_hotkeys, layerhk[layerid], IS_COMMENT ); Append( layername, layerbmp, (void*) layerid ); } diff --git a/common/hotkeys_basic.cpp b/common/hotkeys_basic.cpp index 1ef0e01ab5..53908c71a9 100644 --- a/common/hotkeys_basic.cpp +++ b/common/hotkeys_basic.cpp @@ -171,17 +171,40 @@ wxString ReturnKeyNameFromKeyCode( int aKeycode, bool* aIsFound ) } +/* + * helper function use in AddHotkeyName to calculate an accelerator string + * In some menus, accelerators do not perform exactely the same action as + * the hotkey that perfoms a similar action. + * this is usually the case when this action uses the current mouse position + * for instance zoom action is ran from the F1 key or the Zoom menu. + * a zoom uses the mouse position from a hot key and not from the menu + * In this case, the accelerator if Shift+ + * But for some keys, the Shift modifier is not usable, and the accelerator is Alt+ + */ +static void AddModifierToKey( wxString& aFullKey, const wxString & aKey ) +{ +#if 1 // set to 0 for new behavior, 1 for old + aFullKey << wxT( " <" ) << aKey << wxT( ">" ); +#else + if( aKey.IsSameAs(wxT( "/" ) ) ) + aFullKey << wxT( "\t" ) << MODIFIER_ALT << aKey; + else + aFullKey << wxT( "\t" ) << MODIFIER_SHIFT << aKey; +#endif +} + /* AddHotkeyName * Add the key name from the Command id value ( m_Idcommand member value) * aText = a wxString. returns aText + key name * aList = pointer to a Ki_HotkeyInfo list of commands * aCommandId = Command Id value - * aIsShortCut = true to add (active shortcuts in menus) - * = false to add <(keyname)> + * aShortCutType = IS_HOTKEY to add (shortcuts in menus, same as hotkeys) + * IS_ACCELERATOR to add (accelerators in menus, not hotkeys) + * IS_COMMENT to add <(keyname)> mainly in tooltips * Return a wxString (aTest + key name) if key found or aText without modification */ wxString AddHotkeyName( const wxString& aText, Ki_HotkeyInfo** aList, - int aCommandId, bool aIsShortCut ) + int aCommandId, HOTKEY_ACTION_TYPE aShortCutType ) { wxString msg = aText; wxString keyname; @@ -191,10 +214,18 @@ wxString AddHotkeyName( const wxString& aText, Ki_HotkeyInfo** aList, if( !keyname.IsEmpty() ) { - if( aIsShortCut ) - msg << wxT( "\t" ) << keyname; - else - msg << wxT( " <" ) << keyname << wxT( ">" ); + switch( aShortCutType ) + { + case IS_HOTKEY: + msg << wxT( "\t" ) << keyname; + break; + case IS_ACCELERATOR: + AddModifierToKey( msg, keyname ); + break; + case IS_COMMENT: + msg << wxT( " (" ) << keyname << wxT( ")" ); + break; + } } return msg; @@ -206,14 +237,15 @@ wxString AddHotkeyName( const wxString& aText, Ki_HotkeyInfo** aList, * aText = a wxString. returns aText + key name * aList = pointer to a Ki_HotkeyInfoSectionDescriptor DescrList of commands * aCommandId = Command Id value - * aIsShortCut = true to add (active shortcuts in menus) - * = false to add <(keyname)> + * aShortCutType = IS_HOTKEY to add (active shortcuts in menus) + * IS_ACCELERATOR to add (active accelerators in menus) + * IS_COMMENT to add <(keyname)> * Return a wxString (aText + key name) if key found or aText without modification */ wxString AddHotkeyName( const wxString& aText, struct Ki_HotkeyInfoSectionDescriptor* aDescList, int aCommandId, - bool aIsShortCut ) + HOTKEY_ACTION_TYPE aShortCutType ) { wxString msg = aText; wxString keyname; @@ -228,11 +260,18 @@ wxString AddHotkeyName( const wxString& aText, if( !keyname.IsEmpty() ) { - if( aIsShortCut ) - msg << wxT( "\t" ) << keyname; - else - msg << wxT( " <" ) << keyname << wxT( ">" ); - + switch( aShortCutType ) + { + case IS_HOTKEY: + msg << wxT( "\t" ) << keyname; + break; + case IS_ACCELERATOR: + AddModifierToKey( msg, keyname ); + break; + case IS_COMMENT: + msg << wxT( " (" ) << keyname << wxT( ")" ); + break; + } break; } } diff --git a/eeschema/menubar.cpp b/eeschema/menubar.cpp index aed8aadc74..28057393fe 100644 --- a/eeschema/menubar.cpp +++ b/eeschema/menubar.cpp @@ -42,17 +42,17 @@ void SCH_EDIT_FRAME::ReCreateMenuBar() // New AddMenuItem( fileMenu, - ID_NEW_PROJECT, - _( "&New\tCtrl+N" ), - _( "New schematic project" ), - KiBitmap( new_xpm ) ); + ID_NEW_PROJECT, + _( "&New\tCtrl+N" ), + _( "New schematic project" ), + KiBitmap( new_xpm ) ); // Open AddMenuItem( fileMenu, - ID_LOAD_PROJECT, - _( "&Open\tCtrl+O" ), - _( "Open an existing schematic project" ), - KiBitmap( open_document_xpm ) ); + ID_LOAD_PROJECT, + _( "&Open\tCtrl+O" ), + _( "Open an existing schematic project" ), + KiBitmap( open_document_xpm ) ); // Open Recent submenu static wxMenu* openRecentMenu; @@ -66,106 +66,106 @@ void SCH_EDIT_FRAME::ReCreateMenuBar() wxGetApp().m_fileHistory.UseMenu( openRecentMenu ); wxGetApp().m_fileHistory.AddFilesToMenu( openRecentMenu ); AddMenuItem( fileMenu, openRecentMenu, - wxID_ANY, _( "Open &Recent" ), - _( "Open a recent opened schematic project" ), - KiBitmap( open_project_xpm ) ); + wxID_ANY, _( "Open &Recent" ), + _( "Open a recent opened schematic project" ), + KiBitmap( open_project_xpm ) ); // Separator fileMenu->AppendSeparator(); // Save schematic project AddMenuItem( fileMenu, - ID_SAVE_PROJECT, - _( "&Save Whole Schematic Project\tCtrl+S" ), - _( "Save all sheets in the schematic project" ), - KiBitmap( save_project_xpm ) ); + ID_SAVE_PROJECT, + _( "&Save Whole Schematic Project\tCtrl+S" ), + _( "Save all sheets in the schematic project" ), + KiBitmap( save_project_xpm ) ); // Save current sheet AddMenuItem( fileMenu, - ID_SAVE_ONE_SHEET, - _( "Save &Current Sheet Only" ), - _( "Save only current schematic sheet" ), - KiBitmap( save_xpm ) ); + ID_SAVE_ONE_SHEET, + _( "Save &Current Sheet Only" ), + _( "Save only current schematic sheet" ), + KiBitmap( save_xpm ) ); // Save current sheet as AddMenuItem( fileMenu, - ID_SAVE_ONE_SHEET_AS, - _( "Save Current Sheet &as" ), - _( "Save current schematic sheet as..." ), - KiBitmap( save_as_xpm ) ); + ID_SAVE_ONE_SHEET_AS, + _( "Save Current Sheet &as" ), + _( "Save current schematic sheet as..." ), + KiBitmap( save_as_xpm ) ); // Separator fileMenu->AppendSeparator(); // Page settings AddMenuItem( fileMenu, - ID_SHEET_SET, - _( "P&age Settings" ), - _( "Settigns for page size and information" ), - KiBitmap( sheetset_xpm ) ); + ID_SHEET_SET, + _( "P&age Settings" ), + _( "Settigns for page size and information" ), + KiBitmap( sheetset_xpm ) ); // Print AddMenuItem( fileMenu, - wxID_PRINT, - _( "P&rint" ), - _( "Print schematic" ), - KiBitmap( print_button_xpm ) ); + wxID_PRINT, + _( "P&rint" ), + _( "Print schematic" ), + KiBitmap( print_button_xpm ) ); // Plot submenu wxMenu* choice_plot_fmt = new wxMenu; // Plot PostScript AddMenuItem( choice_plot_fmt, ID_GEN_PLOT_PS, - _( "Plot PostScript" ), - _( "Plot schematic sheet in PostScript format" ), - KiBitmap( plot_ps_xpm ) ); + _( "Plot PostScript" ), + _( "Plot schematic sheet in PostScript format" ), + KiBitmap( plot_ps_xpm ) ); // Plot HPGL AddMenuItem( choice_plot_fmt, - ID_GEN_PLOT_HPGL, - _( "Plot HPGL" ), - _( "Plot schematic sheet in HPGL format" ), - KiBitmap( plot_hpg_xpm ) ); + ID_GEN_PLOT_HPGL, + _( "Plot HPGL" ), + _( "Plot schematic sheet in HPGL format" ), + KiBitmap( plot_hpg_xpm ) ); // Plot SVG AddMenuItem( choice_plot_fmt, - ID_GEN_PLOT_SVG, - _( "Plot SVG" ), - _( "Plot schematic sheet in SVG format" ), - KiBitmap( plot_xpm ) ); + ID_GEN_PLOT_SVG, + _( "Plot SVG" ), + _( "Plot schematic sheet in SVG format" ), + KiBitmap( plot_xpm ) ); // Plot DXF AddMenuItem( choice_plot_fmt, - ID_GEN_PLOT_DXF, - _( "Plot DXF" ), - _( "Plot schematic sheet in DXF format" ), - KiBitmap( plot_xpm ) ); + ID_GEN_PLOT_DXF, + _( "Plot DXF" ), + _( "Plot schematic sheet in DXF format" ), + KiBitmap( plot_xpm ) ); // Plot to Clipboard (Windows only) #ifdef __WINDOWS__ AddMenuItem( choice_plot_fmt, ID_GEN_COPY_SHEET_TO_CLIPBOARD, - _( "Plot to Clipboard" ), - _( "Export drawings to clipboard" ), - KiBitmap( copy_button_xpm ) ); + _( "Plot to Clipboard" ), + _( "Export drawings to clipboard" ), + KiBitmap( copy_button_xpm ) ); #endif // __WINDOWS__ // Plot submenu AddMenuItem( fileMenu, choice_plot_fmt, - ID_GEN_PLOT, _( "&Plot" ), - _( "Plot schematic sheet in HPGL, PostScript or SVG format" ), - KiBitmap( plot_xpm ) ); + ID_GEN_PLOT, _( "&Plot" ), + _( "Plot schematic sheet in HPGL, PostScript or SVG format" ), + KiBitmap( plot_xpm ) ); // Separator fileMenu->AppendSeparator(); // Quit AddMenuItem( fileMenu, - wxID_EXIT, - _( "&Quit" ), - _( "Quit EESchema" ), - KiBitmap( exit_xpm ) ); + wxID_EXIT, + _( "&Quit" ), + _( "Quit EESchema" ), + KiBitmap( exit_xpm ) ); // Menu Edit: wxMenu* editMenu = new wxMenu; @@ -183,8 +183,8 @@ void SCH_EDIT_FRAME::ReCreateMenuBar() // Delete editMenu->AppendSeparator(); AddMenuItem( editMenu, ID_SCHEMATIC_DELETE_ITEM_BUTT, - _( "Delete" ), HELP_DELETE_ITEMS, - KiBitmap( delete_body_xpm ) ); + _( "Delete" ), HELP_DELETE_ITEMS, + KiBitmap( delete_body_xpm ) ); // Find editMenu->AppendSeparator(); @@ -194,10 +194,10 @@ void SCH_EDIT_FRAME::ReCreateMenuBar() // Backannotate editMenu->AppendSeparator(); AddMenuItem( editMenu, - ID_BACKANNO_ITEMS, - _( "&Backannotate" ), - _( "Back annotate the footprint fields" ), - KiBitmap( import_footprint_names_xpm ) ); + ID_BACKANNO_ITEMS, + _( "&Backannotate" ), + _( "Back annotate the footprint fields" ), + KiBitmap( import_footprint_names_xpm ) ); // Menu View: wxMenu* viewMenu = new wxMenu; @@ -219,12 +219,12 @@ void SCH_EDIT_FRAME::ReCreateMenuBar() // Zoom in text = AddHotkeyName( _( "Zoom In" ), s_Schematic_Hokeys_Descr, - ID_ZOOM_IN, false ); // add comment, not a shortcut + HK_ZOOM_IN, IS_ACCELERATOR ); // add an accelerator, not a shortcut AddMenuItem( viewMenu, ID_ZOOM_IN, text, HELP_ZOOM_IN, KiBitmap( zoom_in_xpm ) ); // Zoom out text = AddHotkeyName( _( "Zoom Out" ), s_Schematic_Hokeys_Descr, - ID_ZOOM_OUT, false ); // add comment, not a shortcut + HK_ZOOM_OUT, IS_ACCELERATOR ); // add accelerator, not a shortcut AddMenuItem( viewMenu, ID_ZOOM_OUT, text, HELP_ZOOM_OUT, KiBitmap( zoom_out_xpm ) ); // Fit on screen @@ -237,10 +237,10 @@ void SCH_EDIT_FRAME::ReCreateMenuBar() // Hierarchy AddMenuItem( viewMenu, - ID_HIERARCHY, - _( "H&ierarchy" ), - _( "Navigate schematic hierarchy" ), - KiBitmap( hierarchy_nav_xpm ) ); + ID_HIERARCHY, + _( "H&ierarchy" ), + _( "Navigate schematic hierarchy" ), + KiBitmap( hierarchy_nav_xpm ) ); // Redraw text = AddHotkeyName( _( "Redraw" ), s_Schematic_Hokeys_Descr, HK_ZOOM_REDRAW ); @@ -252,155 +252,155 @@ void SCH_EDIT_FRAME::ReCreateMenuBar() // Component text = AddHotkeyName( _( "Component" ), s_Schematic_Hokeys_Descr, - HK_ADD_NEW_COMPONENT, false ); // add comment, not a shortcut + HK_ADD_NEW_COMPONENT, IS_ACCELERATOR ); // add an accelerator, not a shortcut AddMenuItem( placeMenu, ID_SCH_PLACE_COMPONENT, text, - HELP_PLACE_COMPONENTS, - KiBitmap( add_component_xpm ) ); + HELP_PLACE_COMPONENTS, + KiBitmap( add_component_xpm ) ); // Power port text = AddHotkeyName( _( "Power Port" ), s_Schematic_Hokeys_Descr, - HK_ADD_NEW_POWER, false ); // add comment, not a shortcut + HK_ADD_NEW_POWER, IS_ACCELERATOR ); // add an accelerator, not a shortcut AddMenuItem( placeMenu, ID_PLACE_POWER_BUTT, text, - HELP_PLACE_POWERPORT, - KiBitmap( add_power_xpm ) ); + HELP_PLACE_POWERPORT, + KiBitmap( add_power_xpm ) ); // Wire text = AddHotkeyName( _( "Wire" ), s_Schematic_Hokeys_Descr, - HK_BEGIN_WIRE, false ); // add comment, not a shortcut + HK_BEGIN_WIRE, IS_ACCELERATOR ); // add an accelerator, not a shortcut AddMenuItem( placeMenu, ID_WIRE_BUTT, text, - HELP_PLACE_WIRE, - KiBitmap( add_line_xpm ) ); + HELP_PLACE_WIRE, + KiBitmap( add_line_xpm ) ); // Bus text = AddHotkeyName( _( "Bus" ), s_Schematic_Hokeys_Descr, - HK_BEGIN_BUS, false ); // add comment, not a shortcut + HK_BEGIN_BUS, IS_ACCELERATOR ); // add an accelerator, not a shortcut AddMenuItem( placeMenu, ID_BUS_BUTT, text, - HELP_PLACE_BUS, - KiBitmap( add_bus_xpm ) ); + HELP_PLACE_BUS, + KiBitmap( add_bus_xpm ) ); // Wire to Bus entry text = AddHotkeyName( _( "Wire to Bus Entry" ), s_Schematic_Hokeys_Descr, - HK_ADD_WIRE_ENTRY, false ); // add comment, not a shortcut + HK_ADD_WIRE_ENTRY, IS_ACCELERATOR ); // addan accelerator, not a shortcut AddMenuItem( placeMenu, ID_WIRETOBUS_ENTRY_BUTT, text, - HELP_PLACE_WIRE2BUS_ENTRY, - KiBitmap( add_line2bus_xpm ) ); + HELP_PLACE_WIRE2BUS_ENTRY, + KiBitmap( add_line2bus_xpm ) ); // Bus to Bus entry text = AddHotkeyName( _( "Bus to Bus Entry" ), s_Schematic_Hokeys_Descr, - HK_ADD_BUS_ENTRY, false ); // add comment, not a shortcut + HK_ADD_BUS_ENTRY, IS_ACCELERATOR ); // add an accelerator, not a shortcut AddMenuItem( placeMenu, ID_BUSTOBUS_ENTRY_BUTT, text, - HELP_PLACE_BUS2BUS_ENTRY, - KiBitmap( add_bus2bus_xpm ) ); + HELP_PLACE_BUS2BUS_ENTRY, + KiBitmap( add_bus2bus_xpm ) ); // No Connect Flag text = AddHotkeyName( _( "No Connect Flag" ), s_Schematic_Hokeys_Descr, - HK_ADD_NOCONN_FLAG, false ); // add comment, not a shortcut + HK_ADD_NOCONN_FLAG, IS_ACCELERATOR ); // add an accelerator, not a shortcut AddMenuItem( placeMenu, ID_NOCONN_BUTT, text, HELP_PLACE_NC_FLAG, KiBitmap( noconn_xpm ) ); // Net name text = AddHotkeyName( _( "Label" ), s_Schematic_Hokeys_Descr, - HK_ADD_LABEL, false ); // add comment, not a shortcut + HK_ADD_LABEL, IS_ACCELERATOR ); // add an accelerator, not a shortcut AddMenuItem( placeMenu, ID_LABEL_BUTT, text, - HELP_PLACE_NETLABEL, - KiBitmap( add_line_label_xpm ) ); + HELP_PLACE_NETLABEL, + KiBitmap( add_line_label_xpm ) ); // Global label text = AddHotkeyName( _( "Global Label" ), s_Schematic_Hokeys_Descr, - HK_ADD_GLABEL, false ); // add comment, not a shortcut + HK_ADD_GLABEL, IS_ACCELERATOR ); // add an accelerator, not a shortcut AddMenuItem( placeMenu, ID_GLABEL_BUTT, text, - HELP_PLACE_GLOBALLABEL, - KiBitmap( add_glabel_xpm ) ); + HELP_PLACE_GLOBALLABEL, + KiBitmap( add_glabel_xpm ) ); // Junction text = AddHotkeyName( _( "Junction" ), s_Schematic_Hokeys_Descr, - HK_ADD_JUNCTION, false ); // add comment, not a shortcut + HK_ADD_JUNCTION, IS_ACCELERATOR ); // add an accelerator, not a shortcut AddMenuItem( placeMenu, ID_JUNCTION_BUTT, text, - HELP_PLACE_JUNCTION, - KiBitmap( add_junction_xpm ) ); + HELP_PLACE_JUNCTION, + KiBitmap( add_junction_xpm ) ); // Separator placeMenu->AppendSeparator(); // Hierarchical label text = AddHotkeyName( _( "Hierarchical Label" ), s_Schematic_Hokeys_Descr, - HK_ADD_HLABEL, false ); // add comment, not a shortcut + HK_ADD_HLABEL, IS_ACCELERATOR ); // add an accelerator, not a shortcut text = AddHotkeyName( _( "Hierarchical Label" ), s_Schematic_Hokeys_Descr, - HK_ADD_HLABEL, false ); // add comment, not a shortcut + HK_ADD_HLABEL, IS_ACCELERATOR ); // add an accelerator, not a shortcut AddMenuItem( placeMenu, ID_HIERLABEL_BUTT, - text, HELP_PLACE_HIER_LABEL, - KiBitmap( add_hierarchical_label_xpm ) ); + text, HELP_PLACE_HIER_LABEL, + KiBitmap( add_hierarchical_label_xpm ) ); // Hierarchical sheet text = AddHotkeyName( _( "Hierarchical Sheet" ), s_Schematic_Hokeys_Descr, - HK_ADD_HIER_SHEET, false ); // add comment, not a shortcut + HK_ADD_HIER_SHEET, IS_ACCELERATOR ); // add an accelerator, not a shortcut AddMenuItem( placeMenu, ID_SHEET_SYMBOL_BUTT, text, - HELP_PLACE_SHEET, - KiBitmap( add_hierarchical_subsheet_xpm ) ); + HELP_PLACE_SHEET, + KiBitmap( add_hierarchical_subsheet_xpm ) ); // Import hierarchical sheet AddMenuItem( placeMenu, - ID_IMPORT_HLABEL_BUTT, - _( "Import Hierarchical Label" ), - HELP_IMPORT_SHEETPIN, - KiBitmap( import_hierarchical_label_xpm ) ); + ID_IMPORT_HLABEL_BUTT, + _( "Import Hierarchical Label" ), + HELP_IMPORT_SHEETPIN, + KiBitmap( import_hierarchical_label_xpm ) ); // Add hierarchical Pin to Sheet AddMenuItem( placeMenu, - ID_SHEET_PIN_BUTT, - _( "Hierarchical Pin to Sheet" ), - HELP_PLACE_SHEETPIN, - KiBitmap( add_hierar_pin_xpm ) ); + ID_SHEET_PIN_BUTT, + _( "Hierarchical Pin to Sheet" ), + HELP_PLACE_SHEETPIN, + KiBitmap( add_hierar_pin_xpm ) ); // Separator placeMenu->AppendSeparator(); // Graphic line or polygon text = AddHotkeyName( _( "Graphic Polyline" ), s_Schematic_Hokeys_Descr, - HK_ADD_GRAPHIC_POLYLINE, false ); // add comment, not a shortcut + HK_ADD_GRAPHIC_POLYLINE, IS_ACCELERATOR ); // add an accelerator, not a shortcut AddMenuItem( placeMenu, ID_LINE_COMMENT_BUTT, text, - HELP_PLACE_GRAPHICLINES, - KiBitmap( add_dashed_line_xpm ) ); + HELP_PLACE_GRAPHICLINES, + KiBitmap( add_dashed_line_xpm ) ); // Graphic text text = AddHotkeyName( _( "Graphic Text" ), s_Schematic_Hokeys_Descr, - HK_ADD_GRAPHIC_TEXT, false ); // add comment, not a shortcut + HK_ADD_GRAPHIC_TEXT, IS_ACCELERATOR ); // add an accelerator, not a shortcut AddMenuItem( placeMenu, ID_TEXT_COMMENT_BUTT, text, - HELP_PLACE_GRAPHICTEXTS, - KiBitmap( add_text_xpm ) ); + HELP_PLACE_GRAPHICTEXTS, + KiBitmap( add_text_xpm ) ); // Graphic image - AddMenuItem( placeMenu, ID_ADD_IMAGE_BUTT, _("Image"), - HELP_PLACE_GRAPHICIMAGES, - KiBitmap( image_xpm ) ); + AddMenuItem( placeMenu, ID_ADD_IMAGE_BUTT, _( "Image" ), + HELP_PLACE_GRAPHICIMAGES, + KiBitmap( image_xpm ) ); // Menu Preferences: wxMenu* preferencesMenu = new wxMenu; // Library AddMenuItem( preferencesMenu, - ID_CONFIG_REQ, - _( "&Library" ), - _( "Library preferences" ), - KiBitmap( library_xpm ) ); + ID_CONFIG_REQ, + _( "&Library" ), + _( "Library preferences" ), + KiBitmap( library_xpm ) ); // Colors AddMenuItem( preferencesMenu, - ID_COLORS_SETUP, - _( "&Colors" ), - _( "Color preferences" ), - KiBitmap( palette_xpm ) ); + ID_COLORS_SETUP, + _( "&Colors" ), + _( "Color preferences" ), + KiBitmap( palette_xpm ) ); // Options (Preferences on WXMAC) #ifdef __WXMAC__ - preferencesMenu->Append(wxID_PREFERENCES); + preferencesMenu->Append( wxID_PREFERENCES ); #else AddMenuItem( preferencesMenu, - wxID_PREFERENCES, - _( "&Options" ), - _( "EESchema preferences" ), - KiBitmap( preference_xpm ) ); + wxID_PREFERENCES, + _( "&Options" ), + _( "EESchema preferences" ), + KiBitmap( preference_xpm ) ); #endif // __WXMAC__ @@ -415,83 +415,83 @@ void SCH_EDIT_FRAME::ReCreateMenuBar() // Save preferences AddMenuItem( preferencesMenu, - ID_CONFIG_SAVE, - _( "&Save Preferences" ), - _( "Save application preferences" ), - KiBitmap( save_setup_xpm ) ); + ID_CONFIG_SAVE, + _( "&Save Preferences" ), + _( "Save application preferences" ), + KiBitmap( save_setup_xpm ) ); // Read preferences AddMenuItem( preferencesMenu, - ID_CONFIG_READ, - _( "&Read Preferences" ), - _( "Read application preferences" ), - KiBitmap( read_setup_xpm ) ); + ID_CONFIG_READ, + _( "&Read Preferences" ), + _( "Read application preferences" ), + KiBitmap( read_setup_xpm ) ); // Menu Tools: wxMenu* toolsMenu = new wxMenu; // Library viewer AddMenuItem( toolsMenu, - ID_TO_LIBRARY, - _( "Library &Browser" ), - _( "Library browser" ), - KiBitmap( library_browse_xpm ) ); + ID_TO_LIBRARY, + _( "Library &Browser" ), + _( "Library browser" ), + KiBitmap( library_browse_xpm ) ); // Library editor AddMenuItem( toolsMenu, - ID_TO_LIBRARY, - _( "Library &Editor" ), - _( "Library editor" ), - KiBitmap( libedit_xpm ) ); + ID_TO_LIBRARY, + _( "Library &Editor" ), + _( "Library editor" ), + KiBitmap( libedit_xpm ) ); // Separator toolsMenu->AppendSeparator(); // Annotate AddMenuItem( toolsMenu, - ID_GET_ANNOTATE, - _( "&Annotate" ), - _( "Annotate the components in the schematic" ), - KiBitmap( annotate_xpm ) ); + ID_GET_ANNOTATE, + _( "&Annotate" ), + _( "Annotate the components in the schematic" ), + KiBitmap( annotate_xpm ) ); // ERC AddMenuItem( toolsMenu, - ID_GET_ERC, - _( "ER&C" ), - _( "Perform electrical rule check" ), - KiBitmap( erc_xpm ) ); + ID_GET_ERC, + _( "ER&C" ), + _( "Perform electrical rule check" ), + KiBitmap( erc_xpm ) ); // Generate netlist AddMenuItem( toolsMenu, - ID_GET_NETLIST, - _( "Generate &Netlist" ), - _( "Generate the component netlist" ), - KiBitmap( netlist_xpm ) ); + ID_GET_NETLIST, + _( "Generate &Netlist" ), + _( "Generate the component netlist" ), + KiBitmap( netlist_xpm ) ); // Generate bill of materials AddMenuItem( toolsMenu, - ID_GET_TOOLS, - _( "Generate Bill of Materials" ), - _( "Generate bill of materials" ), - KiBitmap( tools_xpm ) ); + ID_GET_TOOLS, + _( "Generate Bill of Materials" ), + _( "Generate bill of materials" ), + KiBitmap( tools_xpm ) ); // Separator toolsMenu->AppendSeparator(); //Run CVPcb AddMenuItem( toolsMenu, - ID_TO_CVPCB, - _( "A&ssign Component Footprints" ), - _( "Run CVPcb" ), - KiBitmap( cvpcb_xpm ) ); + ID_TO_CVPCB, + _( "A&ssign Component Footprints" ), + _( "Run CVPcb" ), + KiBitmap( cvpcb_xpm ) ); // Run PCBNew AddMenuItem( toolsMenu, - ID_TO_PCB, - _( "&Layout Printed Circuit Board" ), - _( "Run PCBNew" ), - KiBitmap( pcbnew_xpm ) ); + ID_TO_PCB, + _( "&Layout Printed Circuit Board" ), + _( "Run PCBNew" ), + KiBitmap( pcbnew_xpm ) ); // Help Menu: @@ -502,23 +502,23 @@ void SCH_EDIT_FRAME::ReCreateMenuBar() // Contents AddMenuItem( helpMenu, - wxID_HELP, - _( "&Contents" ), - _( "Open the Eeschema handbook" ), - KiBitmap( online_help_xpm ) ); + wxID_HELP, + _( "&Contents" ), + _( "Open the Eeschema handbook" ), + KiBitmap( online_help_xpm ) ); AddMenuItem( helpMenu, - wxID_INDEX, - _( "&Getting Started in KiCad" ), - _( "Open the \"Getting Started in KiCad\" guide for beginners" ), - KiBitmap( help_xpm ) ); + wxID_INDEX, + _( "&Getting Started in KiCad" ), + _( "Open the \"Getting Started in KiCad\" guide for beginners" ), + KiBitmap( help_xpm ) ); // About EESchema helpMenu->AppendSeparator(); AddMenuItem( helpMenu, - wxID_ABOUT, - _( "&About EESchema" ), - _( "About EESchema schematic designer" ), - KiBitmap( info_xpm ) ); + wxID_ABOUT, + _( "&About EESchema" ), + _( "About EESchema schematic designer" ), + KiBitmap( info_xpm ) ); // Create the menubar and append all submenus menuBar->Append( fileMenu, _( "&File" ) ); diff --git a/eeschema/tool_lib.cpp b/eeschema/tool_lib.cpp index 3bea465d57..5e560dc637 100644 --- a/eeschema/tool_lib.cpp +++ b/eeschema/tool_lib.cpp @@ -116,9 +116,9 @@ void LIB_EDIT_FRAME::ReCreateHToolbar() _( "Save current component to new library" ) ); m_HToolBar->AddSeparator(); - msg = AddHotkeyName( _( "Undo last command" ), s_Schematic_Hokeys_Descr, HK_UNDO, false ); + msg = AddHotkeyName( _( "Undo last command" ), s_Schematic_Hokeys_Descr, HK_UNDO, IS_COMMENT ); m_HToolBar->AddTool( wxID_UNDO, wxEmptyString, KiBitmap( undo_xpm ), msg ); - msg = AddHotkeyName( _( "Redo the last command" ), s_Schematic_Hokeys_Descr, HK_REDO, false ); + msg = AddHotkeyName( _( "Redo the last command" ), s_Schematic_Hokeys_Descr, HK_REDO, IS_COMMENT ); m_HToolBar->AddTool( wxID_REDO, wxEmptyString, KiBitmap( redo_xpm ), msg ); m_HToolBar->AddSeparator(); @@ -133,16 +133,16 @@ void LIB_EDIT_FRAME::ReCreateHToolbar() _( "Test for duplicate pins and off grid pins" ) ); m_HToolBar->AddSeparator(); - msg = AddHotkeyName( HELP_ZOOM_IN, s_Libedit_Hokeys_Descr, HK_ZOOM_IN, false ); + msg = AddHotkeyName( HELP_ZOOM_IN, s_Libedit_Hokeys_Descr, HK_ZOOM_IN, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_IN, wxEmptyString, KiBitmap( zoom_in_xpm ), msg ); - msg = AddHotkeyName( HELP_ZOOM_OUT, s_Libedit_Hokeys_Descr, HK_ZOOM_OUT, false ); + msg = AddHotkeyName( HELP_ZOOM_OUT, s_Libedit_Hokeys_Descr, HK_ZOOM_OUT, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_OUT, wxEmptyString, KiBitmap( zoom_out_xpm ), msg ); - msg = AddHotkeyName( HELP_ZOOM_REDRAW, s_Libedit_Hokeys_Descr, HK_ZOOM_REDRAW, false ); + msg = AddHotkeyName( HELP_ZOOM_REDRAW, s_Libedit_Hokeys_Descr, HK_ZOOM_REDRAW, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_REDRAW, wxEmptyString, KiBitmap( zoom_redraw_xpm ), msg ); - msg = AddHotkeyName( HELP_ZOOM_FIT, s_Libedit_Hokeys_Descr, HK_ZOOM_AUTO, false ); + msg = AddHotkeyName( HELP_ZOOM_FIT, s_Libedit_Hokeys_Descr, HK_ZOOM_AUTO, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_PAGE, wxEmptyString, KiBitmap( zoom_fit_in_page_xpm ), msg ); m_HToolBar->AddSeparator(); diff --git a/eeschema/tool_sch.cpp b/eeschema/tool_sch.cpp index 6dda09482e..cd3e3af1ec 100644 --- a/eeschema/tool_sch.cpp +++ b/eeschema/tool_sch.cpp @@ -64,33 +64,33 @@ void SCH_EDIT_FRAME::ReCreateHToolbar() m_HToolBar->AddSeparator(); - msg = AddHotkeyName( HELP_UNDO, s_Schematic_Hokeys_Descr, HK_UNDO, false ); + msg = AddHotkeyName( HELP_UNDO, s_Schematic_Hokeys_Descr, HK_UNDO, IS_COMMENT ); m_HToolBar->AddTool( wxID_UNDO, wxEmptyString, KiBitmap( undo_xpm ), msg ); - msg = AddHotkeyName( HELP_REDO, s_Schematic_Hokeys_Descr, HK_REDO, false ); + msg = AddHotkeyName( HELP_REDO, s_Schematic_Hokeys_Descr, HK_REDO, IS_COMMENT ); m_HToolBar->AddTool( wxID_REDO, wxEmptyString, KiBitmap( redo_xpm ), msg ); m_HToolBar->AddSeparator(); - msg = AddHotkeyName( HELP_FIND, s_Schematic_Hokeys_Descr, HK_FIND_ITEM, false ); + msg = AddHotkeyName( HELP_FIND, s_Schematic_Hokeys_Descr, HK_FIND_ITEM, IS_COMMENT ); m_HToolBar->AddTool( ID_FIND_ITEMS, wxEmptyString, KiBitmap( find_xpm ), msg ); m_HToolBar->AddSeparator(); - msg = AddHotkeyName( HELP_ZOOM_IN, s_Schematic_Hokeys_Descr, HK_ZOOM_IN, false ); + msg = AddHotkeyName( HELP_ZOOM_IN, s_Schematic_Hokeys_Descr, HK_ZOOM_IN, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_IN, wxEmptyString, KiBitmap( zoom_in_xpm ), msg ); - msg = AddHotkeyName( HELP_ZOOM_OUT, s_Schematic_Hokeys_Descr, HK_ZOOM_OUT, false ); + msg = AddHotkeyName( HELP_ZOOM_OUT, s_Schematic_Hokeys_Descr, HK_ZOOM_OUT, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_OUT, wxEmptyString, KiBitmap( zoom_out_xpm ), msg ); - msg = AddHotkeyName( HELP_ZOOM_REDRAW, s_Schematic_Hokeys_Descr, HK_ZOOM_REDRAW, false ); + msg = AddHotkeyName( HELP_ZOOM_REDRAW, s_Schematic_Hokeys_Descr, HK_ZOOM_REDRAW, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_REDRAW, wxEmptyString, KiBitmap( zoom_redraw_xpm ), msg ); - msg = AddHotkeyName( HELP_ZOOM_FIT, s_Schematic_Hokeys_Descr, HK_ZOOM_AUTO, false ); + msg = AddHotkeyName( HELP_ZOOM_FIT, s_Schematic_Hokeys_Descr, HK_ZOOM_AUTO, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_PAGE, wxEmptyString, KiBitmap( zoom_fit_in_page_xpm ), msg ); diff --git a/eeschema/tool_viewlib.cpp b/eeschema/tool_viewlib.cpp index 5e66926dd8..f78ef443af 100644 --- a/eeschema/tool_viewlib.cpp +++ b/eeschema/tool_viewlib.cpp @@ -47,22 +47,22 @@ void LIB_VIEW_FRAME::ReCreateHToolbar() m_HToolBar->AddSeparator(); msg = AddHotkeyName( _( "Zoom in" ), s_Viewlib_Hokeys_Descr, - HK_ZOOM_IN, false ); + HK_ZOOM_IN, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_IN, wxEmptyString, KiBitmap( zoom_in_xpm ), msg ); msg = AddHotkeyName( _( "Zoom out" ), s_Viewlib_Hokeys_Descr, - HK_ZOOM_OUT, false ); + HK_ZOOM_OUT, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_OUT, wxEmptyString, KiBitmap( zoom_out_xpm ), msg ); msg = AddHotkeyName( _( "Redraw view" ), s_Viewlib_Hokeys_Descr, - HK_ZOOM_REDRAW, false ); + HK_ZOOM_REDRAW, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_REDRAW, wxEmptyString, KiBitmap( zoom_redraw_xpm ), msg ); msg = AddHotkeyName( _( "Zoom auto" ), s_Viewlib_Hokeys_Descr, - HK_ZOOM_AUTO, false ); + HK_ZOOM_AUTO, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_PAGE, wxEmptyString, KiBitmap( zoom_fit_in_page_xpm ), msg ); diff --git a/gerbview/class_aperture_macro.cpp b/gerbview/class_aperture_macro.cpp index bdd1551c1a..d241675eea 100644 --- a/gerbview/class_aperture_macro.cpp +++ b/gerbview/class_aperture_macro.cpp @@ -1,814 +1,814 @@ -/****************************/ -/* class_aperture_macro.cpp */ -/****************************/ - - -/* - * This program source code file is part of KICAD, a free EDA CAD application. - * - * Copyright (C) 1992-2010 Jean-Pierre Charras - * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck - * Copyright (C) 1992-2010 Kicad Developers, see change_log.txt for contributors. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, you may find one here: - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "fctsys.h" -#include "common.h" -#include "macros.h" -#include "trigo.h" -#include "gr_basic.h" - -#include "gerbview.h" -#include "class_GERBER.h" - - - -/** - * Function scale - * converts a distance given in floating point to our deci-mils - */ -extern int scale( double aCoord, bool isMetric ); // defined it rs274d.cpp - -/** - * Function mapPt - * translates a point from the aperture macro coordinate system to our - * deci-mils coordinate system. - * @return wxPoint - The gerbview coordinate system vector. - */ -static wxPoint mapPt( double x, double y, bool isMetric ) -{ - wxPoint ret( scale( x, isMetric ), scale( y, isMetric ) ); - - return ret; -} - -/** - * Function mapExposure - * translates the first parameter from an aperture macro into a current - * exposure setting. - * @param aParent = a GERBER_DRAW_ITEM that handle: - * ** m_Exposure A dynamic setting which can change throughout the - * reading of the gerber file, and it indicates whether the current tool - * is lit or not. - * ** m_ImageNegative A dynamic setting which can change throughout the reading - * of the gerber file, and it indicates whether the current D codes are to - * be interpreted as erasures or not. - * @return true to draw with current color, false to draw with alt color (erase) - */ -bool AM_PRIMITIVE::mapExposure( GERBER_DRAW_ITEM* aParent ) -{ - bool exposure; - switch( primitive_id ) - { - case AMP_CIRCLE: - case AMP_LINE2: - case AMP_LINE20: - case AMP_LINE_CENTER: - case AMP_LINE_LOWER_LEFT: - case AMP_OUTLINE: - case AMP_THERMAL: - case AMP_POLYGON: - // All have an exposure parameter and can return true or false - switch( GetExposure(aParent) ) - { - case 0: // exposure always OFF - exposure = false; - break; - - default: - case 1: // exposure always OON - exposure = true; - break; - - case 2: // reverse exposure - exposure = !aParent->GetLayerPolarity(); - } - break; - - case AMP_MOIRE: - case AMP_EOF: - case AMP_UNKNOWN: - default: - return true; // All have no exposure parameter and must return true (no change for exposure) - break; - } - - return exposure ^ aParent->m_imageParams->m_ImageNegative; -} - - -/** - * Function GetExposure - * returns the first parameter in integer form. Some but not all primitives - * use the first parameter as an exposure control. - */ -int AM_PRIMITIVE::GetExposure(GERBER_DRAW_ITEM* aParent) const -{ - // No D_CODE* for GetValue() - wxASSERT( params.size() && params[0].IsImmediate() ); - return (int) params[0].GetValue( aParent->GetDcodeDescr() ); -} - -/** - * Function DrawBasicShape - * Draw the primitive shape for flashed items. - */ -void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent, - EDA_RECT* aClipBox, - wxDC* aDC, - int aColor, int aAltColor, - wxPoint aShapePos, - bool aFilledShape ) -{ - static std::vector polybuffer; // create a static buffer to avoid a lot of memory reallocation - polybuffer.clear(); - - wxPoint curPos = aShapePos; - D_CODE* tool = aParent->GetDcodeDescr(); - int rotation; - if( mapExposure( aParent ) == false ) - { - EXCHG(aColor, aAltColor); - } - - switch( primitive_id ) - { - case AMP_CIRCLE: // Circle, given diameter and position - { - /* Generated by an aperture macro declaration like: - * "1,1,0.3,0.5, 1.0*" - * type (1), exposure, diameter, pos.x, pos.y - * type is not stored in parameters list, so the first parameter is exposure - */ - curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), m_GerbMetric ); - curPos = aParent->GetABPosition( curPos ); - int radius = scale( params[1].GetValue( tool ), m_GerbMetric ) / 2; - if( !aFilledShape ) - GRCircle( aClipBox, aDC, curPos, radius, 0, aColor ); - else - GRFilledCircle( aClipBox, aDC, curPos, radius, aColor ); - } - break; - - case AMP_LINE2: - case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation) - { - /* Generated by an aperture macro declaration like: - * "2,1,0.3,0,0, 0.5, 1.0,-135*" - * type (2), exposure, width, start.x, start.y, end.x, end.y, rotation - * type is not stored in parameters list, so the first parameter is exposure - */ - ConvertShapeToPolygon( aParent, polybuffer ); - - // shape rotation: - rotation = wxRound( params[6].GetValue( tool ) * 10.0 ); - if( rotation ) - { - for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) - RotatePoint( &polybuffer[ii], -rotation ); - } - - // Move to current position: - for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) - { - polybuffer[ii] += curPos; - polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); - } - - GRClosedPoly( aClipBox, aDC, - polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); - } - break; - - case AMP_LINE_CENTER: - { - /* Generated by an aperture macro declaration like: - * "21,1,0.3,0.03,0,0,-135*" - * type (21), exposure, ,width, height, center pos.x, center pos.y, rotation - * type is not stored in parameters list, so the first parameter is exposure - */ - ConvertShapeToPolygon( aParent, polybuffer ); - - // shape rotation: - rotation = wxRound( params[5].GetValue( tool ) * 10.0 ); - if( rotation ) - { - for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) - RotatePoint( &polybuffer[ii], -rotation ); - } - - // Move to current position: - for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) - { - polybuffer[ii] += curPos; - polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); - } - - GRClosedPoly( aClipBox, aDC, - polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); - } - break; - - case AMP_LINE_LOWER_LEFT: - { - /* Generated by an aperture macro declaration like: - * "22,1,0.3,0.03,0,0,-135*" - * type (22), exposure, ,width, height, corner pos.x, corner pos.y, rotation - * type is not stored in parameters list, so the first parameter is exposure - */ - ConvertShapeToPolygon( aParent, polybuffer ); - - // shape rotation: - rotation = wxRound( params[5].GetValue( tool ) * 10.0 ); - if( rotation ) - { - for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) - RotatePoint( &polybuffer[ii], -rotation ); - } - - // Move to current position: - for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) - { - polybuffer[ii] += curPos; - polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); - } - - GRClosedPoly( aClipBox, aDC, - polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); - } - break; - - case AMP_THERMAL: - { - /* Generated by an aperture macro declaration like: - * "7, 0,0,1.0,0.3,0.01,-13*" - * type (7), center.x , center.y, outside diam, inside diam, crosshair thickness, rotation - * type is not stored in parameters list, so the first parameter is center.x - */ - curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ), m_GerbMetric ); - ConvertShapeToPolygon( aParent, polybuffer ); - - // shape rotation: - rotation = wxRound( params[5].GetValue( tool ) * 10.0 ); - - // Because a thermal shape has 4 identical sub-shapes, only one is created in polybuffer. - // We must draw 4 sub-shapes rotated by 90 deg - std::vector subshape_poly; - for( int ii = 0; ii < 4; ii++ ) - { - subshape_poly = polybuffer; - int sub_rotation = rotation + 900 * ii; - for( unsigned jj = 0; jj < subshape_poly.size(); jj++ ) - RotatePoint( &subshape_poly[jj], -sub_rotation ); - - // Move to current position: - for( unsigned jj = 0; jj < subshape_poly.size(); jj++ ) - { - subshape_poly[jj] += curPos; - subshape_poly[jj] = aParent->GetABPosition( subshape_poly[jj] ); - } - - GRClosedPoly( aClipBox, aDC, - subshape_poly.size(), &subshape_poly[0], true, aAltColor, - aAltColor ); - } - } - break; - - case AMP_MOIRE: // A cross hair with n concentric circles - { - curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ), - m_GerbMetric ); - - /* Generated by an aperture macro declaration like: - * "6,0,0,0.125,.01,0.01,3,0.003,0.150,0" - * type(6), pos.x, pos.y, diam, penwidth, gap, circlecount, crosshair thickness, crosshaire len, rotation - * type is not stored in parameters list, so the first parameter is pos.x - */ - int outerDiam = scale( params[2].GetValue( tool ), m_GerbMetric ); - int penThickness = scale( params[3].GetValue( tool ), m_GerbMetric ); - int gap = scale( params[4].GetValue( tool ), m_GerbMetric ); - int numCircles = wxRound( params[5].GetValue( tool ) ); - - // Draw circles: - wxPoint center = aParent->GetABPosition( curPos ); - // adjust outerDiam by this on each nested circle - int diamAdjust = (gap + penThickness); //*2; //Should we use * 2 ? - for( int i = 0; i < numCircles; ++i, outerDiam -= diamAdjust ) - { - if( outerDiam <= 0 ) - break; - if( !aFilledShape ) - { - // draw the border of the pen's path using two circles, each as narrow as possible - GRCircle( aClipBox, aDC, center, outerDiam / 2, 0, aColor ); - GRCircle( aClipBox, aDC, center, outerDiam / 2 - penThickness, 0, aColor ); - } - else // Filled mode - { - GRCircle( aClipBox, aDC, center, - (outerDiam - penThickness) / 2, penThickness, aColor ); - } - } - - // Draw the cross: - ConvertShapeToPolygon( aParent, polybuffer ); - - rotation = wxRound( params[8].GetValue( tool ) * 10.0 ); - for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) - { - // shape rotation: - RotatePoint( &polybuffer[ii], -rotation ); - // Move to current position: - polybuffer[ii] += curPos; - polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); - } - - GRClosedPoly( aClipBox, aDC, - polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); - } - break; - - case AMP_OUTLINE: - { - /* Generated by an aperture macro declaration like: - * "4,1,3,0.0,0.0,0.0,0.5,0.5,0.5,0.5,0.0,-25" - * type(4), exposure, corners count, corner1.x, corner.1y, ..., rotation - * type is not stored in parameters list, so the first parameter is exposure - */ - int numPoints = (int) params[1].GetValue( tool ); - rotation = wxRound( params[numPoints * 2 + 4].GetValue( tool ) * 10.0 ); - wxPoint pos; - // Read points. numPoints does not include the starting point, so add 1. - for( int i = 0; iGetABPosition( polybuffer[ii] ); - } - - GRClosedPoly( aClipBox, aDC, - polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); - } - break; - - case AMP_POLYGON: // Is a regular polygon - /* Generated by an aperture macro declaration like: - * "5,1,0.6,0,0,0.5,25" - * type(5), exposure, vertices count, pox.x, pos.y, diameter, rotation - * type is not stored in parameters list, so the first parameter is exposure - */ - curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), m_GerbMetric ); - // Creates the shape: - ConvertShapeToPolygon( aParent, polybuffer ); - - // rotate polygon and move it to the actual position - rotation = wxRound( params[5].GetValue( tool ) * 10.0 ); - for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) - { - RotatePoint( &polybuffer[ii], -rotation ); - polybuffer[ii] += curPos; - polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); - } - GRClosedPoly( aClipBox, aDC, - polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); - break; - - case AMP_EOF: - // not yet supported, waiting for you. - break; - - case AMP_UNKNOWN: - default: - D( printf( "AM_PRIMITIVE::DrawBasicShape() err: unknown prim id %d\n",primitive_id) ); - break; - } -} - - -/** - * Function ConvertShapeToPolygon (virtual) - * convert a shape to an equivalent polygon. - * Arcs and circles are approximated by segments - * Useful when a shape is not a graphic primitive (shape with hole, - * rotated shape ... ) and cannot be easily drawn. - * note for some schapes conbining circles and solid lines (rectangles), only rectangles are converted - * because circles are very easy to draw (no rotation problem) so convert them in polygons, - * and draw them as polygons is not a good idea. - */ -void AM_PRIMITIVE::ConvertShapeToPolygon( GERBER_DRAW_ITEM* aParent, - std::vector& aBuffer ) -{ - D_CODE* tool = aParent->GetDcodeDescr(); - - switch( primitive_id ) - { - case AMP_CIRCLE: // Circle, currently convertion not needed - break; - - case AMP_LINE2: - case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation) - { - int width = scale( params[1].GetValue( tool ), m_GerbMetric ); - wxPoint start = mapPt( params[2].GetValue( tool ), - params[3].GetValue( tool ), m_GerbMetric ); - wxPoint end = mapPt( params[4].GetValue( tool ), - params[5].GetValue( tool ), m_GerbMetric ); - wxPoint delta = end - start; - int len = wxRound( hypot( delta.x, delta.y ) ); - - // To build the polygon, we must create a horizonta polygon starting to "start" - // and rotate it to have it end point to "end" - wxPoint currpt; - currpt.y += width / 2; // Upper left - aBuffer.push_back( currpt ); - currpt.x = len; // Upper right - aBuffer.push_back( currpt ); - currpt.y -= width; // lower right - aBuffer.push_back( currpt ); - currpt.x = 0; // Upper left - aBuffer.push_back( currpt ); - - // Rotate rectangle and move it to the actual start point - int angle = wxRound( atan2( (double) delta.y, (double) delta.x ) * 1800.0 / M_PI ); - - for( unsigned ii = 0; ii < 4; ii++ ) - { - RotatePoint( &aBuffer[ii], -angle ); - aBuffer[ii] += start; - } - } - break; - - case AMP_LINE_CENTER: - { - wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric ); - wxPoint pos = mapPt( params[3].GetValue( tool ), params[4].GetValue( tool ), m_GerbMetric ); - - // Build poly: - pos.x -= size.x / 2; - pos.y -= size.y / 2; // Lower left - aBuffer.push_back( pos ); - pos.y += size.y; // Upper left - aBuffer.push_back( pos ); - pos.x += size.x; // Upper right - aBuffer.push_back( pos ); - pos.y -= size.y; // lower right - aBuffer.push_back( pos ); - } - break; - - case AMP_LINE_LOWER_LEFT: - { - wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric ); - wxPoint lowerLeft = mapPt( params[3].GetValue( tool ), params[4].GetValue( - tool ), m_GerbMetric ); - - // Build poly: - aBuffer.push_back( lowerLeft ); - lowerLeft.y += size.y; // Upper left - aBuffer.push_back( lowerLeft ); - lowerLeft.x += size.x; // Upper right - aBuffer.push_back( lowerLeft ); - lowerLeft.y -= size.y; // lower right - aBuffer.push_back( lowerLeft ); - } - break; - - case AMP_THERMAL: - { - // Only 1/4 of the full shape is built, because the other 3 shapes will be draw from this first - // rotated by 90, 180 and 270 deg. - // params = center.x (unused here), center.y (unused here), outside diam, inside diam, crosshair thickness - int outerRadius = scale( params[2].GetValue( tool ), m_GerbMetric ) / 2; - int innerRadius = scale( params[3].GetValue( tool ), m_GerbMetric ) / 2; - int halfthickness = scale( params[4].GetValue( tool ), m_GerbMetric ) / 2; - int angle_start = wxRound( asin( - (double) halfthickness / innerRadius ) * 1800 / M_PI ); - - // Draw shape in the first cadrant (X and Y > 0) - wxPoint pos, startpos; - - // Inner arc - startpos.x = innerRadius; - int angle_end = 900 - angle_start; - int angle; - for( angle = angle_start; angle < angle_end; angle += 100 ) - { - pos = startpos; - RotatePoint( &pos, angle ); - aBuffer.push_back( pos ); - } - - // Last point - pos = startpos; - RotatePoint( &pos, angle_end ); - aBuffer.push_back( pos ); - - // outer arc - startpos.x = outerRadius; - startpos.y = 0; - angle_start = wxRound( asin( (double) halfthickness / outerRadius ) * 1800 / M_PI ); - angle_end = 900 - angle_start; - - // First point, near Y axis, outer arc - for( angle = angle_end; angle > angle_start; angle -= 100 ) - { - pos = startpos; - RotatePoint( &pos, angle ); - aBuffer.push_back( pos ); - } - - // last point - pos = startpos; - RotatePoint( &pos, angle_start ); - aBuffer.push_back( pos ); - - aBuffer.push_back( aBuffer[0] ); // Close poly - } - break; - - case AMP_MOIRE: // A cross hair with n concentric circles. Only the cros is build as polygon - // because circles can be drawn easily - { - int crossHairThickness = scale( params[6].GetValue( tool ), m_GerbMetric ); - int crossHairLength = scale( params[7].GetValue( tool ), m_GerbMetric ); - - // Create cross. First create 1/4 of the shape. - // Others point are the same, totated by 90, 180 and 270 deg - wxPoint pos( crossHairThickness / 2, crossHairLength / 2 ); - aBuffer.push_back( pos ); - pos.y = crossHairThickness / 2; - aBuffer.push_back( pos ); - pos.x = -crossHairLength / 2; - aBuffer.push_back( pos ); - pos.y = -crossHairThickness / 2; - aBuffer.push_back( pos ); - - // Copy the 4 shape, rotated by 90, 180 and 270 deg - for( int jj = 1; jj <= 3; jj ++ ) - { - for( int ii = 0; ii < 4; ii++ ) - { - pos = aBuffer[ii]; - RotatePoint( &pos, jj*900 ); - aBuffer.push_back( pos ); - } - } - } - break; - - case AMP_OUTLINE: - // already is a polygon. Do nothing - break; - - case AMP_POLYGON: // Creates a regular polygon - { - int vertexcount = wxRound( params[1].GetValue( tool ) ); - int radius = scale( params[4].GetValue( tool ), m_GerbMetric ) / 2; - // rs274x said: vertex count = 3 ... 10, and the first corner is on the X axis - if( vertexcount < 3 ) - vertexcount = 3; - if( vertexcount > 10 ) - vertexcount = 10; - for( int ii = 0; ii <= vertexcount; ii++ ) - { - wxPoint pos( radius, 0); - RotatePoint( &pos, ii * 3600 / vertexcount ); - aBuffer.push_back( pos ); - } - } - break; - - case AMP_COMMENT: - case AMP_UNKNOWN: - case AMP_EOF: - break; - } -} - -/** GetShapeDim - * Calculate a value that can be used to evaluate the size of text - * when displaying the D-Code of an item - * due to the complexity of the shape of some primitives - * one cannot calculate the "size" of a shape (only abounding box) - * but here, the "dimension" of the shape is the diameter of the primitive - * or for lines the width of the line - * @param aParent = the parent GERBER_DRAW_ITEM which is actually drawn - * @return a dimension, or -1 if no dim to calculate - */ -int AM_PRIMITIVE::GetShapeDim( GERBER_DRAW_ITEM* aParent ) -{ - int dim = -1; - D_CODE* tool = aParent->GetDcodeDescr(); - - switch( primitive_id ) - { - case AMP_CIRCLE: - // params = exposure, diameter, pos.x, pos.y - dim = scale( params[1].GetValue( tool ), m_GerbMetric ); // Diameter - break; - - case AMP_LINE2: - case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation) - dim = scale( params[1].GetValue( tool ), m_GerbMetric ); // linne width - break; - - case AMP_LINE_CENTER: - { - wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric ); - dim = MIN(size.x, size.y); - } - break; - - case AMP_LINE_LOWER_LEFT: - { - wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric ); - dim = MIN(size.x, size.y); - } - break; - - case AMP_THERMAL: - { - // Only 1/4 of the full shape is built, because the other 3 shapes will be draw from this first - // rotated by 90, 180 and 270 deg. - // params = center.x (unused here), center.y (unused here), outside diam, inside diam, crosshair thickness - dim = scale( params[2].GetValue( tool ), m_GerbMetric ) / 2; // Outer diam - } - break; - - case AMP_MOIRE: // A cross hair with n concentric circles. - dim = scale( params[7].GetValue( tool ), m_GerbMetric ); // = cross hair len - break; - - case AMP_OUTLINE: // a free polygon : - // dim = min side of the bounding box (this is a poor criteria, but what is a good criteria b?) - { - // exposure, corners count, corner1.x, corner.1y, ..., rotation - int numPoints = (int) params[1].GetValue( tool ); - // Read points. numPoints does not include the starting point, so add 1. - // and calculate the bounding box; - wxSize pos_min, pos_max, pos; - for( int i = 0; i pos.x ) - pos_min.x = pos.x; - if( pos_min.y > pos.y ) - pos_min.y = pos.y; - // lower left corner: - if( pos_max.x < pos.x ) - pos_max.x = pos.x; - if( pos_max.y < pos.y ) - pos_max.y = pos.y; - } - } - // calculate dim - wxSize size; - size.x = pos_max.x - pos_min.x; - size.y = pos_max.y - pos_min.y; - dim = MIN( size.x, size.y ); - } - break; - - case AMP_POLYGON: // Regular polygon - dim = scale( params[4].GetValue( tool ), m_GerbMetric ) / 2; // Radius - break; - - case AMP_COMMENT: - case AMP_UNKNOWN: - case AMP_EOF: - break; - } - return dim; -} - - -/** - * Function DrawApertureMacroShape - * Draw the primitive shape for flashed items. - * When an item is flashed, this is the shape of the item - */ -void APERTURE_MACRO::DrawApertureMacroShape( GERBER_DRAW_ITEM* aParent, - EDA_RECT* aClipBox, wxDC* aDC, - int aColor, int aAltColor, - wxPoint aShapePos, bool aFilledShape ) -{ - for( AM_PRIMITIVES::iterator prim_macro = primitives.begin(); - prim_macro != primitives.end(); ++prim_macro ) - { - prim_macro->DrawBasicShape( aParent, aClipBox, aDC, - aColor, aAltColor, - aShapePos, - aFilledShape ); - } -} - -/* Function HasNegativeItems - * return true if this macro has at least one aperture primitives - * that must be drawn in background color - * used to optimize screen refresh - */ -bool APERTURE_MACRO::HasNegativeItems( GERBER_DRAW_ITEM* aParent ) -{ - for( AM_PRIMITIVES::iterator prim_macro = primitives.begin(); - prim_macro != primitives.end(); ++prim_macro ) - { - if( prim_macro->mapExposure( aParent ) == false ) // = is negative - return true; - } - - return false; -} - - -/** GetShapeDim - * Calculate a value that can be used to evaluate the size of text - * when displaying the D-Code of an item - * due to the complexity of a shape using many primitives - * one cannot calculate the "size" of a shape (only abounding box) - * but most of aperture macro are using one or few primitives - * and the "dimension" of the shape is the diameter of the primitive - * (or the max diameter of primitives) - * @return a dimension, or -1 if no dim to calculate - */ -int APERTURE_MACRO::GetShapeDim( GERBER_DRAW_ITEM* aParent ) -{ - int dim = -1; - for( AM_PRIMITIVES::iterator prim_macro = primitives.begin(); - prim_macro != primitives.end(); ++prim_macro ) - { - int pdim = prim_macro->GetShapeDim( aParent ); - if( dim < pdim ) - dim = pdim; - } - - return dim; -} - - -/** - * function GetLocalParam - * Usually, parameters are defined inside the aperture primitive - * using immediate mode or defered mode. - * in defered mode the value is defined in a DCODE that want to use the aperture macro. - * But some parameters are defined outside the aperture primitive - * and are local to the aperture macro - * @return the value of a defered parameter defined inside the aperture macro - * @param aParamId = the param id (defined by $3 or $5 ..) to evaluate - */ -double APERTURE_MACRO::GetLocalParam( const D_CODE* aDcode, unsigned aParamId ) const -{ - // find parameter descr. - const AM_PARAM * param = NULL; - for( unsigned ii = 0; ii < m_localparamStack.size(); ii ++ ) - { - if( m_localparamStack[ii].GetIndex() == aParamId ) - { - param = &m_localparamStack[ii]; - break; - } - } - if ( param == NULL ) // not found - return 0.0; - // Evaluate parameter - double value = param->GetValue( aDcode ); - return value; -} +/****************************/ +/* class_aperture_macro.cpp */ +/****************************/ + + +/* + * This program source code file is part of KICAD, a free EDA CAD application. + * + * Copyright (C) 1992-2010 Jean-Pierre Charras + * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2010 Kicad Developers, see change_log.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "fctsys.h" +#include "common.h" +#include "macros.h" +#include "trigo.h" +#include "gr_basic.h" + +#include "gerbview.h" +#include "class_GERBER.h" + + + +/** + * Function scale + * converts a distance given in floating point to our deci-mils + */ +extern int scale( double aCoord, bool isMetric ); // defined it rs274d.cpp + +/** + * Function mapPt + * translates a point from the aperture macro coordinate system to our + * deci-mils coordinate system. + * @return wxPoint - The gerbview coordinate system vector. + */ +static wxPoint mapPt( double x, double y, bool isMetric ) +{ + wxPoint ret( scale( x, isMetric ), scale( y, isMetric ) ); + + return ret; +} + +/** + * Function mapExposure + * translates the first parameter from an aperture macro into a current + * exposure setting. + * @param aParent = a GERBER_DRAW_ITEM that handle: + * ** m_Exposure A dynamic setting which can change throughout the + * reading of the gerber file, and it indicates whether the current tool + * is lit or not. + * ** m_ImageNegative A dynamic setting which can change throughout the reading + * of the gerber file, and it indicates whether the current D codes are to + * be interpreted as erasures or not. + * @return true to draw with current color, false to draw with alt color (erase) + */ +bool AM_PRIMITIVE::mapExposure( GERBER_DRAW_ITEM* aParent ) +{ + bool exposure; + switch( primitive_id ) + { + case AMP_CIRCLE: + case AMP_LINE2: + case AMP_LINE20: + case AMP_LINE_CENTER: + case AMP_LINE_LOWER_LEFT: + case AMP_OUTLINE: + case AMP_THERMAL: + case AMP_POLYGON: + // All have an exposure parameter and can return true or false + switch( GetExposure(aParent) ) + { + case 0: // exposure always OFF + exposure = false; + break; + + default: + case 1: // exposure always OON + exposure = true; + break; + + case 2: // reverse exposure + exposure = !aParent->GetLayerPolarity(); + } + break; + + case AMP_MOIRE: + case AMP_EOF: + case AMP_UNKNOWN: + default: + return true; // All have no exposure parameter and must return true (no change for exposure) + break; + } + + return exposure ^ aParent->m_imageParams->m_ImageNegative; +} + + +/** + * Function GetExposure + * returns the first parameter in integer form. Some but not all primitives + * use the first parameter as an exposure control. + */ +int AM_PRIMITIVE::GetExposure(GERBER_DRAW_ITEM* aParent) const +{ + // No D_CODE* for GetValue() + wxASSERT( params.size() && params[0].IsImmediate() ); + return (int) params[0].GetValue( aParent->GetDcodeDescr() ); +} + +/** + * Function DrawBasicShape + * Draw the primitive shape for flashed items. + */ +void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent, + EDA_RECT* aClipBox, + wxDC* aDC, + int aColor, int aAltColor, + wxPoint aShapePos, + bool aFilledShape ) +{ + static std::vector polybuffer; // create a static buffer to avoid a lot of memory reallocation + polybuffer.clear(); + + wxPoint curPos = aShapePos; + D_CODE* tool = aParent->GetDcodeDescr(); + int rotation; + if( mapExposure( aParent ) == false ) + { + EXCHG(aColor, aAltColor); + } + + switch( primitive_id ) + { + case AMP_CIRCLE: // Circle, given diameter and position + { + /* Generated by an aperture macro declaration like: + * "1,1,0.3,0.5, 1.0*" + * type (1), exposure, diameter, pos.x, pos.y + * type is not stored in parameters list, so the first parameter is exposure + */ + curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), m_GerbMetric ); + curPos = aParent->GetABPosition( curPos ); + int radius = scale( params[1].GetValue( tool ), m_GerbMetric ) / 2; + if( !aFilledShape ) + GRCircle( aClipBox, aDC, curPos, radius, 0, aColor ); + else + GRFilledCircle( aClipBox, aDC, curPos, radius, aColor ); + } + break; + + case AMP_LINE2: + case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation) + { + /* Generated by an aperture macro declaration like: + * "2,1,0.3,0,0, 0.5, 1.0,-135*" + * type (2), exposure, width, start.x, start.y, end.x, end.y, rotation + * type is not stored in parameters list, so the first parameter is exposure + */ + ConvertShapeToPolygon( aParent, polybuffer ); + + // shape rotation: + rotation = wxRound( params[6].GetValue( tool ) * 10.0 ); + if( rotation ) + { + for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) + RotatePoint( &polybuffer[ii], -rotation ); + } + + // Move to current position: + for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) + { + polybuffer[ii] += curPos; + polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); + } + + GRClosedPoly( aClipBox, aDC, + polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); + } + break; + + case AMP_LINE_CENTER: + { + /* Generated by an aperture macro declaration like: + * "21,1,0.3,0.03,0,0,-135*" + * type (21), exposure, ,width, height, center pos.x, center pos.y, rotation + * type is not stored in parameters list, so the first parameter is exposure + */ + ConvertShapeToPolygon( aParent, polybuffer ); + + // shape rotation: + rotation = wxRound( params[5].GetValue( tool ) * 10.0 ); + if( rotation ) + { + for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) + RotatePoint( &polybuffer[ii], -rotation ); + } + + // Move to current position: + for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) + { + polybuffer[ii] += curPos; + polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); + } + + GRClosedPoly( aClipBox, aDC, + polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); + } + break; + + case AMP_LINE_LOWER_LEFT: + { + /* Generated by an aperture macro declaration like: + * "22,1,0.3,0.03,0,0,-135*" + * type (22), exposure, ,width, height, corner pos.x, corner pos.y, rotation + * type is not stored in parameters list, so the first parameter is exposure + */ + ConvertShapeToPolygon( aParent, polybuffer ); + + // shape rotation: + rotation = wxRound( params[5].GetValue( tool ) * 10.0 ); + if( rotation ) + { + for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) + RotatePoint( &polybuffer[ii], -rotation ); + } + + // Move to current position: + for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) + { + polybuffer[ii] += curPos; + polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); + } + + GRClosedPoly( aClipBox, aDC, + polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); + } + break; + + case AMP_THERMAL: + { + /* Generated by an aperture macro declaration like: + * "7, 0,0,1.0,0.3,0.01,-13*" + * type (7), center.x , center.y, outside diam, inside diam, crosshair thickness, rotation + * type is not stored in parameters list, so the first parameter is center.x + */ + curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ), m_GerbMetric ); + ConvertShapeToPolygon( aParent, polybuffer ); + + // shape rotation: + rotation = wxRound( params[5].GetValue( tool ) * 10.0 ); + + // Because a thermal shape has 4 identical sub-shapes, only one is created in polybuffer. + // We must draw 4 sub-shapes rotated by 90 deg + std::vector subshape_poly; + for( int ii = 0; ii < 4; ii++ ) + { + subshape_poly = polybuffer; + int sub_rotation = rotation + 900 * ii; + for( unsigned jj = 0; jj < subshape_poly.size(); jj++ ) + RotatePoint( &subshape_poly[jj], -sub_rotation ); + + // Move to current position: + for( unsigned jj = 0; jj < subshape_poly.size(); jj++ ) + { + subshape_poly[jj] += curPos; + subshape_poly[jj] = aParent->GetABPosition( subshape_poly[jj] ); + } + + GRClosedPoly( aClipBox, aDC, + subshape_poly.size(), &subshape_poly[0], true, aAltColor, + aAltColor ); + } + } + break; + + case AMP_MOIRE: // A cross hair with n concentric circles + { + curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ), + m_GerbMetric ); + + /* Generated by an aperture macro declaration like: + * "6,0,0,0.125,.01,0.01,3,0.003,0.150,0" + * type(6), pos.x, pos.y, diam, penwidth, gap, circlecount, crosshair thickness, crosshaire len, rotation + * type is not stored in parameters list, so the first parameter is pos.x + */ + int outerDiam = scale( params[2].GetValue( tool ), m_GerbMetric ); + int penThickness = scale( params[3].GetValue( tool ), m_GerbMetric ); + int gap = scale( params[4].GetValue( tool ), m_GerbMetric ); + int numCircles = wxRound( params[5].GetValue( tool ) ); + + // Draw circles: + wxPoint center = aParent->GetABPosition( curPos ); + // adjust outerDiam by this on each nested circle + int diamAdjust = (gap + penThickness); //*2; //Should we use * 2 ? + for( int i = 0; i < numCircles; ++i, outerDiam -= diamAdjust ) + { + if( outerDiam <= 0 ) + break; + if( !aFilledShape ) + { + // draw the border of the pen's path using two circles, each as narrow as possible + GRCircle( aClipBox, aDC, center, outerDiam / 2, 0, aColor ); + GRCircle( aClipBox, aDC, center, outerDiam / 2 - penThickness, 0, aColor ); + } + else // Filled mode + { + GRCircle( aClipBox, aDC, center, + (outerDiam - penThickness) / 2, penThickness, aColor ); + } + } + + // Draw the cross: + ConvertShapeToPolygon( aParent, polybuffer ); + + rotation = wxRound( params[8].GetValue( tool ) * 10.0 ); + for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) + { + // shape rotation: + RotatePoint( &polybuffer[ii], -rotation ); + // Move to current position: + polybuffer[ii] += curPos; + polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); + } + + GRClosedPoly( aClipBox, aDC, + polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); + } + break; + + case AMP_OUTLINE: + { + /* Generated by an aperture macro declaration like: + * "4,1,3,0.0,0.0,0.0,0.5,0.5,0.5,0.5,0.0,-25" + * type(4), exposure, corners count, corner1.x, corner.1y, ..., rotation + * type is not stored in parameters list, so the first parameter is exposure + */ + int numPoints = (int) params[1].GetValue( tool ); + rotation = wxRound( params[numPoints * 2 + 4].GetValue( tool ) * 10.0 ); + wxPoint pos; + // Read points. numPoints does not include the starting point, so add 1. + for( int i = 0; iGetABPosition( polybuffer[ii] ); + } + + GRClosedPoly( aClipBox, aDC, + polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); + } + break; + + case AMP_POLYGON: // Is a regular polygon + /* Generated by an aperture macro declaration like: + * "5,1,0.6,0,0,0.5,25" + * type(5), exposure, vertices count, pox.x, pos.y, diameter, rotation + * type is not stored in parameters list, so the first parameter is exposure + */ + curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), m_GerbMetric ); + // Creates the shape: + ConvertShapeToPolygon( aParent, polybuffer ); + + // rotate polygon and move it to the actual position + rotation = wxRound( params[5].GetValue( tool ) * 10.0 ); + for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) + { + RotatePoint( &polybuffer[ii], -rotation ); + polybuffer[ii] += curPos; + polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); + } + GRClosedPoly( aClipBox, aDC, + polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); + break; + + case AMP_EOF: + // not yet supported, waiting for you. + break; + + case AMP_UNKNOWN: + default: + D( printf( "AM_PRIMITIVE::DrawBasicShape() err: unknown prim id %d\n",primitive_id) ); + break; + } +} + + +/** + * Function ConvertShapeToPolygon (virtual) + * convert a shape to an equivalent polygon. + * Arcs and circles are approximated by segments + * Useful when a shape is not a graphic primitive (shape with hole, + * rotated shape ... ) and cannot be easily drawn. + * note for some schapes conbining circles and solid lines (rectangles), only rectangles are converted + * because circles are very easy to draw (no rotation problem) so convert them in polygons, + * and draw them as polygons is not a good idea. + */ +void AM_PRIMITIVE::ConvertShapeToPolygon( GERBER_DRAW_ITEM* aParent, + std::vector& aBuffer ) +{ + D_CODE* tool = aParent->GetDcodeDescr(); + + switch( primitive_id ) + { + case AMP_CIRCLE: // Circle, currently convertion not needed + break; + + case AMP_LINE2: + case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation) + { + int width = scale( params[1].GetValue( tool ), m_GerbMetric ); + wxPoint start = mapPt( params[2].GetValue( tool ), + params[3].GetValue( tool ), m_GerbMetric ); + wxPoint end = mapPt( params[4].GetValue( tool ), + params[5].GetValue( tool ), m_GerbMetric ); + wxPoint delta = end - start; + int len = wxRound( hypot( delta.x, delta.y ) ); + + // To build the polygon, we must create a horizonta polygon starting to "start" + // and rotate it to have it end point to "end" + wxPoint currpt; + currpt.y += width / 2; // Upper left + aBuffer.push_back( currpt ); + currpt.x = len; // Upper right + aBuffer.push_back( currpt ); + currpt.y -= width; // lower right + aBuffer.push_back( currpt ); + currpt.x = 0; // Upper left + aBuffer.push_back( currpt ); + + // Rotate rectangle and move it to the actual start point + int angle = wxRound( atan2( (double) delta.y, (double) delta.x ) * 1800.0 / M_PI ); + + for( unsigned ii = 0; ii < 4; ii++ ) + { + RotatePoint( &aBuffer[ii], -angle ); + aBuffer[ii] += start; + } + } + break; + + case AMP_LINE_CENTER: + { + wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric ); + wxPoint pos = mapPt( params[3].GetValue( tool ), params[4].GetValue( tool ), m_GerbMetric ); + + // Build poly: + pos.x -= size.x / 2; + pos.y -= size.y / 2; // Lower left + aBuffer.push_back( pos ); + pos.y += size.y; // Upper left + aBuffer.push_back( pos ); + pos.x += size.x; // Upper right + aBuffer.push_back( pos ); + pos.y -= size.y; // lower right + aBuffer.push_back( pos ); + } + break; + + case AMP_LINE_LOWER_LEFT: + { + wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric ); + wxPoint lowerLeft = mapPt( params[3].GetValue( tool ), params[4].GetValue( + tool ), m_GerbMetric ); + + // Build poly: + aBuffer.push_back( lowerLeft ); + lowerLeft.y += size.y; // Upper left + aBuffer.push_back( lowerLeft ); + lowerLeft.x += size.x; // Upper right + aBuffer.push_back( lowerLeft ); + lowerLeft.y -= size.y; // lower right + aBuffer.push_back( lowerLeft ); + } + break; + + case AMP_THERMAL: + { + // Only 1/4 of the full shape is built, because the other 3 shapes will be draw from this first + // rotated by 90, 180 and 270 deg. + // params = center.x (unused here), center.y (unused here), outside diam, inside diam, crosshair thickness + int outerRadius = scale( params[2].GetValue( tool ), m_GerbMetric ) / 2; + int innerRadius = scale( params[3].GetValue( tool ), m_GerbMetric ) / 2; + int halfthickness = scale( params[4].GetValue( tool ), m_GerbMetric ) / 2; + int angle_start = wxRound( asin( + (double) halfthickness / innerRadius ) * 1800 / M_PI ); + + // Draw shape in the first cadrant (X and Y > 0) + wxPoint pos, startpos; + + // Inner arc + startpos.x = innerRadius; + int angle_end = 900 - angle_start; + int angle; + for( angle = angle_start; angle < angle_end; angle += 100 ) + { + pos = startpos; + RotatePoint( &pos, angle ); + aBuffer.push_back( pos ); + } + + // Last point + pos = startpos; + RotatePoint( &pos, angle_end ); + aBuffer.push_back( pos ); + + // outer arc + startpos.x = outerRadius; + startpos.y = 0; + angle_start = wxRound( asin( (double) halfthickness / outerRadius ) * 1800 / M_PI ); + angle_end = 900 - angle_start; + + // First point, near Y axis, outer arc + for( angle = angle_end; angle > angle_start; angle -= 100 ) + { + pos = startpos; + RotatePoint( &pos, angle ); + aBuffer.push_back( pos ); + } + + // last point + pos = startpos; + RotatePoint( &pos, angle_start ); + aBuffer.push_back( pos ); + + aBuffer.push_back( aBuffer[0] ); // Close poly + } + break; + + case AMP_MOIRE: // A cross hair with n concentric circles. Only the cros is build as polygon + // because circles can be drawn easily + { + int crossHairThickness = scale( params[6].GetValue( tool ), m_GerbMetric ); + int crossHairLength = scale( params[7].GetValue( tool ), m_GerbMetric ); + + // Create cross. First create 1/4 of the shape. + // Others point are the same, totated by 90, 180 and 270 deg + wxPoint pos( crossHairThickness / 2, crossHairLength / 2 ); + aBuffer.push_back( pos ); + pos.y = crossHairThickness / 2; + aBuffer.push_back( pos ); + pos.x = -crossHairLength / 2; + aBuffer.push_back( pos ); + pos.y = -crossHairThickness / 2; + aBuffer.push_back( pos ); + + // Copy the 4 shape, rotated by 90, 180 and 270 deg + for( int jj = 1; jj <= 3; jj ++ ) + { + for( int ii = 0; ii < 4; ii++ ) + { + pos = aBuffer[ii]; + RotatePoint( &pos, jj*900 ); + aBuffer.push_back( pos ); + } + } + } + break; + + case AMP_OUTLINE: + // already is a polygon. Do nothing + break; + + case AMP_POLYGON: // Creates a regular polygon + { + int vertexcount = wxRound( params[1].GetValue( tool ) ); + int radius = scale( params[4].GetValue( tool ), m_GerbMetric ) / 2; + // rs274x said: vertex count = 3 ... 10, and the first corner is on the X axis + if( vertexcount < 3 ) + vertexcount = 3; + if( vertexcount > 10 ) + vertexcount = 10; + for( int ii = 0; ii <= vertexcount; ii++ ) + { + wxPoint pos( radius, 0); + RotatePoint( &pos, ii * 3600 / vertexcount ); + aBuffer.push_back( pos ); + } + } + break; + + case AMP_COMMENT: + case AMP_UNKNOWN: + case AMP_EOF: + break; + } +} + +/** GetShapeDim + * Calculate a value that can be used to evaluate the size of text + * when displaying the D-Code of an item + * due to the complexity of the shape of some primitives + * one cannot calculate the "size" of a shape (only abounding box) + * but here, the "dimension" of the shape is the diameter of the primitive + * or for lines the width of the line + * @param aParent = the parent GERBER_DRAW_ITEM which is actually drawn + * @return a dimension, or -1 if no dim to calculate + */ +int AM_PRIMITIVE::GetShapeDim( GERBER_DRAW_ITEM* aParent ) +{ + int dim = -1; + D_CODE* tool = aParent->GetDcodeDescr(); + + switch( primitive_id ) + { + case AMP_CIRCLE: + // params = exposure, diameter, pos.x, pos.y + dim = scale( params[1].GetValue( tool ), m_GerbMetric ); // Diameter + break; + + case AMP_LINE2: + case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation) + dim = scale( params[1].GetValue( tool ), m_GerbMetric ); // linne width + break; + + case AMP_LINE_CENTER: + { + wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric ); + dim = MIN(size.x, size.y); + } + break; + + case AMP_LINE_LOWER_LEFT: + { + wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), m_GerbMetric ); + dim = MIN(size.x, size.y); + } + break; + + case AMP_THERMAL: + { + // Only 1/4 of the full shape is built, because the other 3 shapes will be draw from this first + // rotated by 90, 180 and 270 deg. + // params = center.x (unused here), center.y (unused here), outside diam, inside diam, crosshair thickness + dim = scale( params[2].GetValue( tool ), m_GerbMetric ) / 2; // Outer diam + } + break; + + case AMP_MOIRE: // A cross hair with n concentric circles. + dim = scale( params[7].GetValue( tool ), m_GerbMetric ); // = cross hair len + break; + + case AMP_OUTLINE: // a free polygon : + // dim = min side of the bounding box (this is a poor criteria, but what is a good criteria b?) + { + // exposure, corners count, corner1.x, corner.1y, ..., rotation + int numPoints = (int) params[1].GetValue( tool ); + // Read points. numPoints does not include the starting point, so add 1. + // and calculate the bounding box; + wxSize pos_min, pos_max, pos; + for( int i = 0; i pos.x ) + pos_min.x = pos.x; + if( pos_min.y > pos.y ) + pos_min.y = pos.y; + // lower left corner: + if( pos_max.x < pos.x ) + pos_max.x = pos.x; + if( pos_max.y < pos.y ) + pos_max.y = pos.y; + } + } + // calculate dim + wxSize size; + size.x = pos_max.x - pos_min.x; + size.y = pos_max.y - pos_min.y; + dim = MIN( size.x, size.y ); + } + break; + + case AMP_POLYGON: // Regular polygon + dim = scale( params[4].GetValue( tool ), m_GerbMetric ) / 2; // Radius + break; + + case AMP_COMMENT: + case AMP_UNKNOWN: + case AMP_EOF: + break; + } + return dim; +} + + +/** + * Function DrawApertureMacroShape + * Draw the primitive shape for flashed items. + * When an item is flashed, this is the shape of the item + */ +void APERTURE_MACRO::DrawApertureMacroShape( GERBER_DRAW_ITEM* aParent, + EDA_RECT* aClipBox, wxDC* aDC, + int aColor, int aAltColor, + wxPoint aShapePos, bool aFilledShape ) +{ + for( AM_PRIMITIVES::iterator prim_macro = primitives.begin(); + prim_macro != primitives.end(); ++prim_macro ) + { + prim_macro->DrawBasicShape( aParent, aClipBox, aDC, + aColor, aAltColor, + aShapePos, + aFilledShape ); + } +} + +/* Function HasNegativeItems + * return true if this macro has at least one aperture primitives + * that must be drawn in background color + * used to optimize screen refresh + */ +bool APERTURE_MACRO::HasNegativeItems( GERBER_DRAW_ITEM* aParent ) +{ + for( AM_PRIMITIVES::iterator prim_macro = primitives.begin(); + prim_macro != primitives.end(); ++prim_macro ) + { + if( prim_macro->mapExposure( aParent ) == false ) // = is negative + return true; + } + + return false; +} + + +/** GetShapeDim + * Calculate a value that can be used to evaluate the size of text + * when displaying the D-Code of an item + * due to the complexity of a shape using many primitives + * one cannot calculate the "size" of a shape (only abounding box) + * but most of aperture macro are using one or few primitives + * and the "dimension" of the shape is the diameter of the primitive + * (or the max diameter of primitives) + * @return a dimension, or -1 if no dim to calculate + */ +int APERTURE_MACRO::GetShapeDim( GERBER_DRAW_ITEM* aParent ) +{ + int dim = -1; + for( AM_PRIMITIVES::iterator prim_macro = primitives.begin(); + prim_macro != primitives.end(); ++prim_macro ) + { + int pdim = prim_macro->GetShapeDim( aParent ); + if( dim < pdim ) + dim = pdim; + } + + return dim; +} + + +/** + * function GetLocalParam + * Usually, parameters are defined inside the aperture primitive + * using immediate mode or defered mode. + * in defered mode the value is defined in a DCODE that want to use the aperture macro. + * But some parameters are defined outside the aperture primitive + * and are local to the aperture macro + * @return the value of a defered parameter defined inside the aperture macro + * @param aParamId = the param id (defined by $3 or $5 ..) to evaluate + */ +double APERTURE_MACRO::GetLocalParam( const D_CODE* aDcode, unsigned aParamId ) const +{ + // find parameter descr. + const AM_PARAM * param = NULL; + for( unsigned ii = 0; ii < m_localparamStack.size(); ii ++ ) + { + if( m_localparamStack[ii].GetIndex() == aParamId ) + { + param = &m_localparamStack[ii]; + break; + } + } + if ( param == NULL ) // not found + return 0.0; + // Evaluate parameter + double value = param->GetValue( aDcode ); + return value; +} diff --git a/gerbview/class_gerbview_layer_widget.cpp b/gerbview/class_gerbview_layer_widget.cpp index 75ef570b62..aee403118c 100644 --- a/gerbview/class_gerbview_layer_widget.cpp +++ b/gerbview/class_gerbview_layer_widget.cpp @@ -1,290 +1,290 @@ -/* - * This program source code file is part of KICAD, a free EDA CAD application. - * - * Copyright (C) 2004-2010 Jean-Pierre Charras, jean-pierre.charras@gpisa-lab.inpg.fr - * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck - * Copyright (C) 2010 Kicad Developers, see change_log.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 - */ - - -/*********************************************************/ -/* class_gerbview_layer_widget.cpp - gerbview layers manager. */ -/*********************************************************/ - -#include "fctsys.h" -#include "common.h" -#include "class_drawpanel.h" -#include "pcbstruct.h" -#include "macros.h" -#include "class_layer_box_selector.h" - -#include "gerbview.h" -#include "class_GERBER.h" -#include "layer_widget.h" -#include "class_gerbview_layer_widget.h" - - -/* - * Class GERBER_LAYER_WIDGET - * is here to implement the abtract functions of LAYER_WIDGET so they - * may be tied into the GERBVIEW_FRAME's data and so we can add a popup - * menu which is specific to PCBNEW's needs. - */ - - -GERBER_LAYER_WIDGET::GERBER_LAYER_WIDGET( GERBVIEW_FRAME* aParent, wxWindow* aFocusOwner, - int aPointSize ) : - LAYER_WIDGET( aParent, aFocusOwner, aPointSize ), - myframe( aParent ) -{ - ReFillRender(); - - // Update default tabs labels for gerbview - SetLayersManagerTabsText( ); - - //------------------------------------------------------ - // handle the popup menu over the layer window. - m_LayerScrolledWindow->Connect( wxEVT_RIGHT_DOWN, - wxMouseEventHandler( GERBER_LAYER_WIDGET::onRightDownLayers ), NULL, this ); - - // since Popupmenu() calls this->ProcessEvent() we must call this->Connect() - // and not m_LayerScrolledWindow->Connect() - Connect( ID_SHOW_ALL_COPPERS, ID_SHOW_NO_COPPERS, wxEVT_COMMAND_MENU_SELECTED, - wxCommandEventHandler( GERBER_LAYER_WIDGET::onPopupSelection ), NULL, this ); - - // install the right click handler into each control at end of ReFill() - // using installRightLayerClickHandler -} - -/** - * Function SetLayersManagerTabsText - * Update the layer manager tabs labels - * Useful when changing Language or to set labels to a non default value - */ -void GERBER_LAYER_WIDGET::SetLayersManagerTabsText( ) -{ - m_notebook->SetPageText(0, _("Layer") ); - m_notebook->SetPageText(1, _("Render") ); -} - -/** - * Function ReFillRender - * Rebuild Render for instance after the config is read - */ -void GERBER_LAYER_WIDGET::ReFillRender() -{ - BOARD* board = myframe->GetBoard(); - ClearRenderRows(); - - // Fixed "Rendering" tab rows within the LAYER_WIDGET, only the initial color - // is changed before appending to the LAYER_WIDGET. This is an automatic variable - // not a static variable, change the color & state after copying from code to renderRows - // on the stack. - LAYER_WIDGET::ROW renderRows[2] = { - -#define RR LAYER_WIDGET::ROW // Render Row abreviation to reduce source width - - // text id color tooltip checked - RR( _( "Grid" ), GERBER_GRID_VISIBLE, WHITE, _( "Show the (x,y) grid dots" ) ), - RR( _( "DCodes" ), DCODES_VISIBLE, WHITE, _( "Show DCodes identification" ) ), - }; - - for( unsigned row=0; rowGetVisibleElementColor( renderRows[row].id ); - } - renderRows[row].state = board->IsElementVisible( renderRows[row].id ); - } - - AppendRenderRows( renderRows, DIM(renderRows) ); -} - -void GERBER_LAYER_WIDGET::installRightLayerClickHandler() -{ - int rowCount = GetLayerRowCount(); - for( int row=0; rowConnect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( - GERBER_LAYER_WIDGET::onRightDownLayers ), NULL, this ); - } - } -} - - -void GERBER_LAYER_WIDGET::onRightDownLayers( wxMouseEvent& event ) -{ - wxMenu menu; - - // menu text is capitalized: - // http://library.gnome.org/devel/hig-book/2.20/design-text-labels.html.en#layout-capitalization - menu.Append( new wxMenuItem( &menu, ID_SHOW_ALL_COPPERS, - _("Show All Layers") ) ); - - menu.Append( new wxMenuItem( &menu, ID_SHOW_NO_COPPERS, - _( "Hide All Layers" ) ) ); - - PopupMenu( &menu ); - - passOnFocus(); -} - -void GERBER_LAYER_WIDGET::onPopupSelection( wxCommandEvent& event ) -{ - int rowCount; - int menuId = event.GetId(); - bool visible = (menuId == ID_SHOW_ALL_COPPERS) ? true : false;; - int visibleLayers = 0; - - switch( menuId ) - { - case ID_SHOW_ALL_COPPERS: - case ID_SHOW_NO_COPPERS: - rowCount = GetLayerRowCount(); - for( int row=0; row < rowCount; ++row ) - { - wxCheckBox* cb = (wxCheckBox*) getLayerComp( row, 3 ); - cb->SetValue( visible ); - if( visible ) - visibleLayers |= (1 << row); - else - visibleLayers &= ~(1 << row); - } - - myframe->GetBoard()->SetVisibleLayers( visibleLayers ); - myframe->DrawPanel->Refresh(); - break; - } -} - - - -void GERBER_LAYER_WIDGET::ReFill() -{ - BOARD* brd = myframe->GetBoard(); - int layer; - ClearLayerRows(); - for( layer = 0; layer < LAYER_COUNT; layer++ ) - { - wxString msg; - msg.Printf( _("Layer %d"), layer+1 ); - AppendLayerRow( LAYER_WIDGET::ROW( msg, layer, - brd->GetLayerColor( layer ), wxEmptyString, true ) ); - } - - installRightLayerClickHandler(); -} - -//------------------------------------------------ - -void GERBER_LAYER_WIDGET::OnLayerColorChange( int aLayer, int aColor ) -{ - myframe->GetBoard()->SetLayerColor( aLayer, aColor ); - myframe->m_SelLayerBox->ResyncBitmapOnly(); - myframe->DrawPanel->Refresh(); -} - -bool GERBER_LAYER_WIDGET::OnLayerSelect( int aLayer ) -{ - // the layer change from the GERBER_LAYER_WIDGET can be denied by returning - // false from this function. - int layer = myframe->getActiveLayer( ); - myframe->setActiveLayer( aLayer, false ); - myframe->syncLayerBox(); - if( layer != myframe->getActiveLayer( ) ) - myframe->DrawPanel->Refresh(); - - return true; -} - -void GERBER_LAYER_WIDGET::OnLayerVisible( int aLayer, bool isVisible, bool isFinal ) -{ - BOARD* brd = myframe->GetBoard(); - int visibleLayers = brd->GetVisibleLayers(); - - if( isVisible ) - visibleLayers |= (1 << aLayer); - else - visibleLayers &= ~(1 << aLayer); - - brd->SetVisibleLayers( visibleLayers ); - - if( isFinal ) - myframe->DrawPanel->Refresh(); -} - -void GERBER_LAYER_WIDGET::OnRenderColorChange( int aId, int aColor ) -{ - myframe->GetBoard()->SetVisibleElementColor( aId, aColor ); - myframe->DrawPanel->Refresh(); -} - -void GERBER_LAYER_WIDGET::OnRenderEnable( int aId, bool isEnabled ) -{ - BOARD* brd = myframe->GetBoard(); - brd->SetElementVisibility( aId, isEnabled ); - - myframe->DrawPanel->Refresh(); -} - -//----------------------------------------------- - -/* - * Virtual Function useAlternateBitmap - * return true if bitmaps shown in Render layer list - * must be alternate bitmaps, or false to use "normal" bitmaps - */ -bool GERBER_LAYER_WIDGET::useAlternateBitmap(int aRow) -{ - bool inUse = false; - GERBER_IMAGE* gerber = g_GERBER_List[aRow]; - - if( gerber != NULL && gerber->m_InUse ) - inUse = true; - - return inUse; -} - -/** - * Function UpdateLayerIcons - * Update the layer manager icons (layers only) - * Useful when loading a file or clearing a layer because they change - */ -void GERBER_LAYER_WIDGET::UpdateLayerIcons() -{ - int row_count = GetLayerRowCount(); - for( int row = 0; row < row_count ; row++ ) - { - wxStaticBitmap* bm = (wxStaticBitmap*) getLayerComp( row, 0 ); - if( bm == NULL) - continue; - - if( row == m_CurrentRow ) - bm->SetBitmap( useAlternateBitmap(row) ? *m_RightArrowAlternateBitmap : *m_RightArrowBitmap ); - else - bm->SetBitmap( useAlternateBitmap(row) ? *m_BlankAlternateBitmap : *m_BlankBitmap ); - } -} +/* + * This program source code file is part of KICAD, a free EDA CAD application. + * + * Copyright (C) 2004-2010 Jean-Pierre Charras, jean-pierre.charras@gpisa-lab.inpg.fr + * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2010 Kicad Developers, see change_log.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 + */ + + +/*********************************************************/ +/* class_gerbview_layer_widget.cpp - gerbview layers manager. */ +/*********************************************************/ + +#include "fctsys.h" +#include "common.h" +#include "class_drawpanel.h" +#include "pcbstruct.h" +#include "macros.h" +#include "class_layer_box_selector.h" + +#include "gerbview.h" +#include "class_GERBER.h" +#include "layer_widget.h" +#include "class_gerbview_layer_widget.h" + + +/* + * Class GERBER_LAYER_WIDGET + * is here to implement the abtract functions of LAYER_WIDGET so they + * may be tied into the GERBVIEW_FRAME's data and so we can add a popup + * menu which is specific to PCBNEW's needs. + */ + + +GERBER_LAYER_WIDGET::GERBER_LAYER_WIDGET( GERBVIEW_FRAME* aParent, wxWindow* aFocusOwner, + int aPointSize ) : + LAYER_WIDGET( aParent, aFocusOwner, aPointSize ), + myframe( aParent ) +{ + ReFillRender(); + + // Update default tabs labels for gerbview + SetLayersManagerTabsText( ); + + //------------------------------------------------------ + // handle the popup menu over the layer window. + m_LayerScrolledWindow->Connect( wxEVT_RIGHT_DOWN, + wxMouseEventHandler( GERBER_LAYER_WIDGET::onRightDownLayers ), NULL, this ); + + // since Popupmenu() calls this->ProcessEvent() we must call this->Connect() + // and not m_LayerScrolledWindow->Connect() + Connect( ID_SHOW_ALL_COPPERS, ID_SHOW_NO_COPPERS, wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler( GERBER_LAYER_WIDGET::onPopupSelection ), NULL, this ); + + // install the right click handler into each control at end of ReFill() + // using installRightLayerClickHandler +} + +/** + * Function SetLayersManagerTabsText + * Update the layer manager tabs labels + * Useful when changing Language or to set labels to a non default value + */ +void GERBER_LAYER_WIDGET::SetLayersManagerTabsText( ) +{ + m_notebook->SetPageText(0, _("Layer") ); + m_notebook->SetPageText(1, _("Render") ); +} + +/** + * Function ReFillRender + * Rebuild Render for instance after the config is read + */ +void GERBER_LAYER_WIDGET::ReFillRender() +{ + BOARD* board = myframe->GetBoard(); + ClearRenderRows(); + + // Fixed "Rendering" tab rows within the LAYER_WIDGET, only the initial color + // is changed before appending to the LAYER_WIDGET. This is an automatic variable + // not a static variable, change the color & state after copying from code to renderRows + // on the stack. + LAYER_WIDGET::ROW renderRows[2] = { + +#define RR LAYER_WIDGET::ROW // Render Row abreviation to reduce source width + + // text id color tooltip checked + RR( _( "Grid" ), GERBER_GRID_VISIBLE, WHITE, _( "Show the (x,y) grid dots" ) ), + RR( _( "DCodes" ), DCODES_VISIBLE, WHITE, _( "Show DCodes identification" ) ), + }; + + for( unsigned row=0; rowGetVisibleElementColor( renderRows[row].id ); + } + renderRows[row].state = board->IsElementVisible( renderRows[row].id ); + } + + AppendRenderRows( renderRows, DIM(renderRows) ); +} + +void GERBER_LAYER_WIDGET::installRightLayerClickHandler() +{ + int rowCount = GetLayerRowCount(); + for( int row=0; rowConnect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( + GERBER_LAYER_WIDGET::onRightDownLayers ), NULL, this ); + } + } +} + + +void GERBER_LAYER_WIDGET::onRightDownLayers( wxMouseEvent& event ) +{ + wxMenu menu; + + // menu text is capitalized: + // http://library.gnome.org/devel/hig-book/2.20/design-text-labels.html.en#layout-capitalization + menu.Append( new wxMenuItem( &menu, ID_SHOW_ALL_COPPERS, + _("Show All Layers") ) ); + + menu.Append( new wxMenuItem( &menu, ID_SHOW_NO_COPPERS, + _( "Hide All Layers" ) ) ); + + PopupMenu( &menu ); + + passOnFocus(); +} + +void GERBER_LAYER_WIDGET::onPopupSelection( wxCommandEvent& event ) +{ + int rowCount; + int menuId = event.GetId(); + bool visible = (menuId == ID_SHOW_ALL_COPPERS) ? true : false;; + int visibleLayers = 0; + + switch( menuId ) + { + case ID_SHOW_ALL_COPPERS: + case ID_SHOW_NO_COPPERS: + rowCount = GetLayerRowCount(); + for( int row=0; row < rowCount; ++row ) + { + wxCheckBox* cb = (wxCheckBox*) getLayerComp( row, 3 ); + cb->SetValue( visible ); + if( visible ) + visibleLayers |= (1 << row); + else + visibleLayers &= ~(1 << row); + } + + myframe->GetBoard()->SetVisibleLayers( visibleLayers ); + myframe->DrawPanel->Refresh(); + break; + } +} + + + +void GERBER_LAYER_WIDGET::ReFill() +{ + BOARD* brd = myframe->GetBoard(); + int layer; + ClearLayerRows(); + for( layer = 0; layer < LAYER_COUNT; layer++ ) + { + wxString msg; + msg.Printf( _("Layer %d"), layer+1 ); + AppendLayerRow( LAYER_WIDGET::ROW( msg, layer, + brd->GetLayerColor( layer ), wxEmptyString, true ) ); + } + + installRightLayerClickHandler(); +} + +//------------------------------------------------ + +void GERBER_LAYER_WIDGET::OnLayerColorChange( int aLayer, int aColor ) +{ + myframe->GetBoard()->SetLayerColor( aLayer, aColor ); + myframe->m_SelLayerBox->ResyncBitmapOnly(); + myframe->DrawPanel->Refresh(); +} + +bool GERBER_LAYER_WIDGET::OnLayerSelect( int aLayer ) +{ + // the layer change from the GERBER_LAYER_WIDGET can be denied by returning + // false from this function. + int layer = myframe->getActiveLayer( ); + myframe->setActiveLayer( aLayer, false ); + myframe->syncLayerBox(); + if( layer != myframe->getActiveLayer( ) ) + myframe->DrawPanel->Refresh(); + + return true; +} + +void GERBER_LAYER_WIDGET::OnLayerVisible( int aLayer, bool isVisible, bool isFinal ) +{ + BOARD* brd = myframe->GetBoard(); + int visibleLayers = brd->GetVisibleLayers(); + + if( isVisible ) + visibleLayers |= (1 << aLayer); + else + visibleLayers &= ~(1 << aLayer); + + brd->SetVisibleLayers( visibleLayers ); + + if( isFinal ) + myframe->DrawPanel->Refresh(); +} + +void GERBER_LAYER_WIDGET::OnRenderColorChange( int aId, int aColor ) +{ + myframe->GetBoard()->SetVisibleElementColor( aId, aColor ); + myframe->DrawPanel->Refresh(); +} + +void GERBER_LAYER_WIDGET::OnRenderEnable( int aId, bool isEnabled ) +{ + BOARD* brd = myframe->GetBoard(); + brd->SetElementVisibility( aId, isEnabled ); + + myframe->DrawPanel->Refresh(); +} + +//----------------------------------------------- + +/* + * Virtual Function useAlternateBitmap + * return true if bitmaps shown in Render layer list + * must be alternate bitmaps, or false to use "normal" bitmaps + */ +bool GERBER_LAYER_WIDGET::useAlternateBitmap(int aRow) +{ + bool inUse = false; + GERBER_IMAGE* gerber = g_GERBER_List[aRow]; + + if( gerber != NULL && gerber->m_InUse ) + inUse = true; + + return inUse; +} + +/** + * Function UpdateLayerIcons + * Update the layer manager icons (layers only) + * Useful when loading a file or clearing a layer because they change + */ +void GERBER_LAYER_WIDGET::UpdateLayerIcons() +{ + int row_count = GetLayerRowCount(); + for( int row = 0; row < row_count ; row++ ) + { + wxStaticBitmap* bm = (wxStaticBitmap*) getLayerComp( row, 0 ); + if( bm == NULL) + continue; + + if( row == m_CurrentRow ) + bm->SetBitmap( useAlternateBitmap(row) ? *m_RightArrowAlternateBitmap : *m_RightArrowBitmap ); + else + bm->SetBitmap( useAlternateBitmap(row) ? *m_BlankAlternateBitmap : *m_BlankBitmap ); + } +} diff --git a/gerbview/events_called_functions.cpp b/gerbview/events_called_functions.cpp index 320e545b35..d54867d7f1 100644 --- a/gerbview/events_called_functions.cpp +++ b/gerbview/events_called_functions.cpp @@ -1,298 +1,298 @@ -/** - * @file events_called_functions.cpp - * @brief Gerbview command event functions. - */ - -#include "fctsys.h" -#include "appl_wxstruct.h" -#include "class_drawpanel.h" -#include "confirm.h" -#include "common.h" -#include "gestfich.h" - -#include "gerbview.h" -#include "kicad_device_context.h" -#include "gerbview_id.h" -#include "class_GERBER.h" -#include "dialog_helpers.h" -#include "class_DCodeSelectionbox.h" -#include "class_gerbview_layer_widget.h" - - -// Event table: - -BEGIN_EVENT_TABLE( GERBVIEW_FRAME, PCB_BASE_FRAME ) - EVT_CLOSE( GERBVIEW_FRAME::OnCloseWindow ) - EVT_SIZE( GERBVIEW_FRAME::OnSize ) - - EVT_TOOL( wxID_FILE, GERBVIEW_FRAME::Files_io ) - EVT_TOOL( ID_GERBVIEW_ERASE_ALL, GERBVIEW_FRAME::Files_io ) - EVT_TOOL( ID_GERBVIEW_LOAD_DRILL_FILE, GERBVIEW_FRAME::Files_io ) - EVT_TOOL( ID_GERBVIEW_LOAD_DCODE_FILE, GERBVIEW_FRAME::Files_io ) - EVT_TOOL( ID_NEW_BOARD, GERBVIEW_FRAME::Files_io ) - - // Menu Files: - EVT_MENU( wxID_FILE, GERBVIEW_FRAME::Files_io ) - EVT_MENU( ID_NEW_BOARD, GERBVIEW_FRAME::Files_io ) - EVT_MENU( ID_GEN_PLOT, GERBVIEW_FRAME::ToPlotter ) - EVT_MENU( ID_GERBVIEW_EXPORT_TO_PCBNEW, GERBVIEW_FRAME::ExportDataInPcbnewFormat ) - - EVT_MENU_RANGE( wxID_FILE1, wxID_FILE9, GERBVIEW_FRAME::OnGbrFileHistory ) - EVT_MENU_RANGE( ID_GERBVIEW_DRILL_FILE1, ID_GERBVIEW_DRILL_FILE9, - GERBVIEW_FRAME::OnDrlFileHistory ) - - EVT_MENU( wxID_EXIT, GERBVIEW_FRAME::OnQuit ) - - // menu Preferences - EVT_MENU_RANGE( ID_PREFERENCES_HOTKEY_START, ID_PREFERENCES_HOTKEY_END, - GERBVIEW_FRAME::Process_Config ) - - EVT_MENU( ID_MENU_GERBVIEW_SHOW_HIDE_LAYERS_MANAGER_DIALOG, - GERBVIEW_FRAME::OnSelectOptionToolbar ) - EVT_MENU( wxID_PREFERENCES, GERBVIEW_FRAME::InstallGerberOptionsDialog ) - - EVT_MENU_RANGE( ID_LANGUAGE_CHOICE, ID_LANGUAGE_CHOICE_END, EDA_DRAW_FRAME::SetLanguage ) - - // menu Postprocess - EVT_MENU( ID_GERBVIEW_SHOW_LIST_DCODES, GERBVIEW_FRAME::Process_Special_Functions ) - EVT_MENU( ID_GERBVIEW_SHOW_SOURCE, GERBVIEW_FRAME::OnShowGerberSourceFile ) - EVT_MENU( ID_MENU_GERBVIEW_SELECT_PREFERED_EDITOR, - EDA_BASE_FRAME::OnSelectPreferredEditor ) - - // menu Miscellaneous - EVT_MENU( ID_GERBVIEW_GLOBAL_DELETE, GERBVIEW_FRAME::Process_Special_Functions ) - - // Menu Help - EVT_MENU( wxID_HELP, EDA_DRAW_FRAME::GetKicadHelp ) - EVT_MENU( wxID_ABOUT, EDA_DRAW_FRAME::GetKicadAbout ) - - EVT_TOOL( wxID_CUT, GERBVIEW_FRAME::Process_Special_Functions ) - EVT_TOOL( wxID_COPY, GERBVIEW_FRAME::Process_Special_Functions ) - EVT_TOOL( wxID_PASTE, GERBVIEW_FRAME::Process_Special_Functions ) - EVT_TOOL( wxID_UNDO, GERBVIEW_FRAME::Process_Special_Functions ) - EVT_TOOL( wxID_PRINT, GERBVIEW_FRAME::ToPrinter ) - EVT_COMBOBOX( ID_TOOLBARH_GERBVIEW_SELECT_ACTIVE_LAYER, - GERBVIEW_FRAME::OnSelectActiveLayer ) - - EVT_SELECT_DCODE( ID_TOOLBARH_GERBER_SELECT_ACTIVE_DCODE, GERBVIEW_FRAME::OnSelectActiveDCode ) - - // Vertical toolbar: - EVT_TOOL( ID_NO_TOOL_SELECTED, GERBVIEW_FRAME::Process_Special_Functions ) - - EVT_MENU_RANGE( ID_POPUP_GENERAL_START_RANGE, ID_POPUP_GENERAL_END_RANGE, - GERBVIEW_FRAME::Process_Special_Functions ) - - // Option toolbar - EVT_TOOL( ID_TB_OPTIONS_SHOW_POLYGONS_SKETCH, GERBVIEW_FRAME::OnSelectOptionToolbar ) - EVT_TOOL( ID_TB_OPTIONS_SHOW_FLASHED_ITEMS_SKETCH, GERBVIEW_FRAME::OnSelectOptionToolbar ) - EVT_TOOL( ID_TB_OPTIONS_SHOW_LINES_SKETCH, GERBVIEW_FRAME::OnSelectOptionToolbar ) - EVT_TOOL( ID_TB_OPTIONS_SHOW_LAYERS_MANAGER_VERTICAL_TOOLBAR, - GERBVIEW_FRAME::OnSelectOptionToolbar ) - EVT_TOOL( ID_TB_OPTIONS_SHOW_DCODES, GERBVIEW_FRAME::OnSelectOptionToolbar ) - EVT_TOOL_RANGE( ID_TB_OPTIONS_SHOW_GBR_MODE_0, ID_TB_OPTIONS_SHOW_GBR_MODE_2, - GERBVIEW_FRAME::OnSelectDisplayMode ) - - EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_FLASHED_ITEMS_SKETCH, - GERBVIEW_FRAME::OnUpdateFlashedItemsDrawMode ) - EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_LINES_SKETCH, GERBVIEW_FRAME::OnUpdateLinesDrawMode ) - EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_POLYGONS_SKETCH, GERBVIEW_FRAME::OnUpdatePolygonsDrawMode ) - EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_DCODES, GERBVIEW_FRAME::OnUpdateShowDCodes ) - EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_LAYERS_MANAGER_VERTICAL_TOOLBAR, - GERBVIEW_FRAME::OnUpdateShowLayerManager ) - - EVT_UPDATE_UI( ID_TOOLBARH_GERBER_SELECT_ACTIVE_DCODE, GERBVIEW_FRAME::OnUpdateSelectDCode ) - EVT_UPDATE_UI( ID_TOOLBARH_GERBVIEW_SELECT_ACTIVE_LAYER, - GERBVIEW_FRAME::OnUpdateLayerSelectBox ) - EVT_UPDATE_UI_RANGE( ID_TB_OPTIONS_SHOW_GBR_MODE_0, ID_TB_OPTIONS_SHOW_GBR_MODE_2, - GERBVIEW_FRAME::OnUpdateDrawMode ) - -END_EVENT_TABLE() - - -/* Handles the selection of tools, menu, and popup menu commands. - */ -void GERBVIEW_FRAME::Process_Special_Functions( wxCommandEvent& event ) -{ - int id = event.GetId(); - - switch( id ) - { - case wxID_CUT: - case wxID_COPY: - case ID_POPUP_DELETE_BLOCK: - case ID_POPUP_PLACE_BLOCK: - case ID_POPUP_ZOOM_BLOCK: - break; - - case ID_POPUP_CANCEL_CURRENT_COMMAND: - DrawPanel->EndMouseCapture(); - - if( GetScreen()->m_BlockLocate.m_Command != BLOCK_IDLE ) - { - /* Should not be executed, except bug */ - GetScreen()->m_BlockLocate.m_Command = BLOCK_IDLE; - GetScreen()->m_BlockLocate.m_State = STATE_NO_BLOCK; - GetScreen()->m_BlockLocate.ClearItemsList(); - } - - if( GetToolId() == ID_NO_TOOL_SELECTED ) - SetToolID( ID_NO_TOOL_SELECTED, DrawPanel->GetDefaultCursor(), wxEmptyString ); - else - DrawPanel->SetCursor( DrawPanel->GetCurrentCursor() ); - break; - - default: - DrawPanel->EndMouseCapture(); - break; - } - - INSTALL_UNBUFFERED_DC( dc, DrawPanel ); - - switch( id ) - { - case ID_GERBVIEW_GLOBAL_DELETE: - Erase_Current_Layer( true ); - ClearMsgPanel(); - break; - - case ID_NO_TOOL_SELECTED: - SetToolID( ID_NO_TOOL_SELECTED, DrawPanel->GetDefaultCursor(), wxEmptyString ); - break; - - case ID_POPUP_CLOSE_CURRENT_TOOL: - SetToolID( ID_NO_TOOL_SELECTED, DrawPanel->GetDefaultCursor(), wxEmptyString ); - break; - - case ID_POPUP_CANCEL_CURRENT_COMMAND: - break; - - case ID_GERBVIEW_SHOW_LIST_DCODES: - Liste_D_Codes(); - break; - - case ID_POPUP_PLACE_BLOCK: - GetScreen()->m_BlockLocate.m_Command = BLOCK_MOVE; - DrawPanel->m_AutoPAN_Request = FALSE; - HandleBlockPlace( &dc ); - break; - - case ID_POPUP_ZOOM_BLOCK: - GetScreen()->m_BlockLocate.m_Command = BLOCK_ZOOM; - GetScreen()->m_BlockLocate.SetMessageBlock( this ); - HandleBlockEnd( &dc ); - break; - - case ID_POPUP_DELETE_BLOCK: - GetScreen()->m_BlockLocate.m_Command = BLOCK_DELETE; - GetScreen()->m_BlockLocate.SetMessageBlock( this ); - HandleBlockEnd( &dc ); - break; - - default: - wxFAIL_MSG( wxT( "GERBVIEW_FRAME::Process_Special_Functions error" ) ); - break; - } -} - - -/* Selects the active DCode for the current active layer. - * Items using this DCode are hightlighted - */ -void GERBVIEW_FRAME::OnSelectActiveDCode( wxCommandEvent& event ) -{ - GERBER_IMAGE* gerber_image = g_GERBER_List[getActiveLayer()]; - if( gerber_image ) - { - int tool = m_DCodeSelector->GetSelectedDCodeId(); - if( tool != gerber_image->m_Selected_Tool ) - { - gerber_image->m_Selected_Tool = tool; - DrawPanel->Refresh(); - } - } -} - -/* Selects the active layer: - * - if a file is loaded, it is loaded in this layer - * _ this layer is displayed on top of other layers - */ -void GERBVIEW_FRAME::OnSelectActiveLayer( wxCommandEvent& event ) -{ - int layer = getActiveLayer(); - - setActiveLayer( event.GetSelection() ); - if( layer != getActiveLayer() ) - DrawPanel->Refresh(); -} - - -/* Call preferred editor to show (and edit) the gerber source file - * loaded in the active layer - */ -void GERBVIEW_FRAME::OnShowGerberSourceFile( wxCommandEvent& event ) -{ - int layer = getActiveLayer(); - GERBER_IMAGE* gerber_layer = g_GERBER_List[layer]; - - if( gerber_layer ) - { - wxString editorname = wxGetApp().GetEditorName(); - if( !editorname.IsEmpty() ) - { - wxFileName fn( gerber_layer->m_FileName ); - ExecuteFile( this, editorname, QuoteFullPath( fn ) ); - } - else - { - wxMessageBox( _( "No editor defined. Please select one" ) ); - } - } -} - - -/* Function OnSelectDisplayMode: called to select display mode - * (fast display, or exact mode with stacked images or with transparency - */ -void GERBVIEW_FRAME::OnSelectDisplayMode( wxCommandEvent& event ) -{ - int oldMode = GetDisplayMode(); - - switch( event.GetId() ) - { - case ID_TB_OPTIONS_SHOW_GBR_MODE_0: - SetDisplayMode( 0 ); - break; - - case ID_TB_OPTIONS_SHOW_GBR_MODE_1: - SetDisplayMode( 1 ); - break; - - case ID_TB_OPTIONS_SHOW_GBR_MODE_2: - SetDisplayMode( 2 ); - break; - } - - if( GetDisplayMode() != oldMode ) - DrawPanel->Refresh(); -} - -void GERBVIEW_FRAME::OnQuit( wxCommandEvent& event ) -{ - Close( true ); -} - -/** - * Function SetLanguage - * called on a language menu selection - * Update Layer manager title and tabs texts - */ -void GERBVIEW_FRAME::SetLanguage( wxCommandEvent& event ) -{ - EDA_DRAW_FRAME::SetLanguage( event ); - m_LayersManager->SetLayersManagerTabsText(); - wxAuiPaneInfo& pane_info = m_auimgr.GetPane( m_LayersManager ); - pane_info.Caption( _( "Visibles" ) ); - m_auimgr.Update(); - - ReFillLayerWidget(); -} +/** + * @file events_called_functions.cpp + * @brief Gerbview command event functions. + */ + +#include "fctsys.h" +#include "appl_wxstruct.h" +#include "class_drawpanel.h" +#include "confirm.h" +#include "common.h" +#include "gestfich.h" + +#include "gerbview.h" +#include "kicad_device_context.h" +#include "gerbview_id.h" +#include "class_GERBER.h" +#include "dialog_helpers.h" +#include "class_DCodeSelectionbox.h" +#include "class_gerbview_layer_widget.h" + + +// Event table: + +BEGIN_EVENT_TABLE( GERBVIEW_FRAME, PCB_BASE_FRAME ) + EVT_CLOSE( GERBVIEW_FRAME::OnCloseWindow ) + EVT_SIZE( GERBVIEW_FRAME::OnSize ) + + EVT_TOOL( wxID_FILE, GERBVIEW_FRAME::Files_io ) + EVT_TOOL( ID_GERBVIEW_ERASE_ALL, GERBVIEW_FRAME::Files_io ) + EVT_TOOL( ID_GERBVIEW_LOAD_DRILL_FILE, GERBVIEW_FRAME::Files_io ) + EVT_TOOL( ID_GERBVIEW_LOAD_DCODE_FILE, GERBVIEW_FRAME::Files_io ) + EVT_TOOL( ID_NEW_BOARD, GERBVIEW_FRAME::Files_io ) + + // Menu Files: + EVT_MENU( wxID_FILE, GERBVIEW_FRAME::Files_io ) + EVT_MENU( ID_NEW_BOARD, GERBVIEW_FRAME::Files_io ) + EVT_MENU( ID_GEN_PLOT, GERBVIEW_FRAME::ToPlotter ) + EVT_MENU( ID_GERBVIEW_EXPORT_TO_PCBNEW, GERBVIEW_FRAME::ExportDataInPcbnewFormat ) + + EVT_MENU_RANGE( wxID_FILE1, wxID_FILE9, GERBVIEW_FRAME::OnGbrFileHistory ) + EVT_MENU_RANGE( ID_GERBVIEW_DRILL_FILE1, ID_GERBVIEW_DRILL_FILE9, + GERBVIEW_FRAME::OnDrlFileHistory ) + + EVT_MENU( wxID_EXIT, GERBVIEW_FRAME::OnQuit ) + + // menu Preferences + EVT_MENU_RANGE( ID_PREFERENCES_HOTKEY_START, ID_PREFERENCES_HOTKEY_END, + GERBVIEW_FRAME::Process_Config ) + + EVT_MENU( ID_MENU_GERBVIEW_SHOW_HIDE_LAYERS_MANAGER_DIALOG, + GERBVIEW_FRAME::OnSelectOptionToolbar ) + EVT_MENU( wxID_PREFERENCES, GERBVIEW_FRAME::InstallGerberOptionsDialog ) + + EVT_MENU_RANGE( ID_LANGUAGE_CHOICE, ID_LANGUAGE_CHOICE_END, EDA_DRAW_FRAME::SetLanguage ) + + // menu Postprocess + EVT_MENU( ID_GERBVIEW_SHOW_LIST_DCODES, GERBVIEW_FRAME::Process_Special_Functions ) + EVT_MENU( ID_GERBVIEW_SHOW_SOURCE, GERBVIEW_FRAME::OnShowGerberSourceFile ) + EVT_MENU( ID_MENU_GERBVIEW_SELECT_PREFERED_EDITOR, + EDA_BASE_FRAME::OnSelectPreferredEditor ) + + // menu Miscellaneous + EVT_MENU( ID_GERBVIEW_GLOBAL_DELETE, GERBVIEW_FRAME::Process_Special_Functions ) + + // Menu Help + EVT_MENU( wxID_HELP, EDA_DRAW_FRAME::GetKicadHelp ) + EVT_MENU( wxID_ABOUT, EDA_DRAW_FRAME::GetKicadAbout ) + + EVT_TOOL( wxID_CUT, GERBVIEW_FRAME::Process_Special_Functions ) + EVT_TOOL( wxID_COPY, GERBVIEW_FRAME::Process_Special_Functions ) + EVT_TOOL( wxID_PASTE, GERBVIEW_FRAME::Process_Special_Functions ) + EVT_TOOL( wxID_UNDO, GERBVIEW_FRAME::Process_Special_Functions ) + EVT_TOOL( wxID_PRINT, GERBVIEW_FRAME::ToPrinter ) + EVT_COMBOBOX( ID_TOOLBARH_GERBVIEW_SELECT_ACTIVE_LAYER, + GERBVIEW_FRAME::OnSelectActiveLayer ) + + EVT_SELECT_DCODE( ID_TOOLBARH_GERBER_SELECT_ACTIVE_DCODE, GERBVIEW_FRAME::OnSelectActiveDCode ) + + // Vertical toolbar: + EVT_TOOL( ID_NO_TOOL_SELECTED, GERBVIEW_FRAME::Process_Special_Functions ) + + EVT_MENU_RANGE( ID_POPUP_GENERAL_START_RANGE, ID_POPUP_GENERAL_END_RANGE, + GERBVIEW_FRAME::Process_Special_Functions ) + + // Option toolbar + EVT_TOOL( ID_TB_OPTIONS_SHOW_POLYGONS_SKETCH, GERBVIEW_FRAME::OnSelectOptionToolbar ) + EVT_TOOL( ID_TB_OPTIONS_SHOW_FLASHED_ITEMS_SKETCH, GERBVIEW_FRAME::OnSelectOptionToolbar ) + EVT_TOOL( ID_TB_OPTIONS_SHOW_LINES_SKETCH, GERBVIEW_FRAME::OnSelectOptionToolbar ) + EVT_TOOL( ID_TB_OPTIONS_SHOW_LAYERS_MANAGER_VERTICAL_TOOLBAR, + GERBVIEW_FRAME::OnSelectOptionToolbar ) + EVT_TOOL( ID_TB_OPTIONS_SHOW_DCODES, GERBVIEW_FRAME::OnSelectOptionToolbar ) + EVT_TOOL_RANGE( ID_TB_OPTIONS_SHOW_GBR_MODE_0, ID_TB_OPTIONS_SHOW_GBR_MODE_2, + GERBVIEW_FRAME::OnSelectDisplayMode ) + + EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_FLASHED_ITEMS_SKETCH, + GERBVIEW_FRAME::OnUpdateFlashedItemsDrawMode ) + EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_LINES_SKETCH, GERBVIEW_FRAME::OnUpdateLinesDrawMode ) + EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_POLYGONS_SKETCH, GERBVIEW_FRAME::OnUpdatePolygonsDrawMode ) + EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_DCODES, GERBVIEW_FRAME::OnUpdateShowDCodes ) + EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_LAYERS_MANAGER_VERTICAL_TOOLBAR, + GERBVIEW_FRAME::OnUpdateShowLayerManager ) + + EVT_UPDATE_UI( ID_TOOLBARH_GERBER_SELECT_ACTIVE_DCODE, GERBVIEW_FRAME::OnUpdateSelectDCode ) + EVT_UPDATE_UI( ID_TOOLBARH_GERBVIEW_SELECT_ACTIVE_LAYER, + GERBVIEW_FRAME::OnUpdateLayerSelectBox ) + EVT_UPDATE_UI_RANGE( ID_TB_OPTIONS_SHOW_GBR_MODE_0, ID_TB_OPTIONS_SHOW_GBR_MODE_2, + GERBVIEW_FRAME::OnUpdateDrawMode ) + +END_EVENT_TABLE() + + +/* Handles the selection of tools, menu, and popup menu commands. + */ +void GERBVIEW_FRAME::Process_Special_Functions( wxCommandEvent& event ) +{ + int id = event.GetId(); + + switch( id ) + { + case wxID_CUT: + case wxID_COPY: + case ID_POPUP_DELETE_BLOCK: + case ID_POPUP_PLACE_BLOCK: + case ID_POPUP_ZOOM_BLOCK: + break; + + case ID_POPUP_CANCEL_CURRENT_COMMAND: + DrawPanel->EndMouseCapture(); + + if( GetScreen()->m_BlockLocate.m_Command != BLOCK_IDLE ) + { + /* Should not be executed, except bug */ + GetScreen()->m_BlockLocate.m_Command = BLOCK_IDLE; + GetScreen()->m_BlockLocate.m_State = STATE_NO_BLOCK; + GetScreen()->m_BlockLocate.ClearItemsList(); + } + + if( GetToolId() == ID_NO_TOOL_SELECTED ) + SetToolID( ID_NO_TOOL_SELECTED, DrawPanel->GetDefaultCursor(), wxEmptyString ); + else + DrawPanel->SetCursor( DrawPanel->GetCurrentCursor() ); + break; + + default: + DrawPanel->EndMouseCapture(); + break; + } + + INSTALL_UNBUFFERED_DC( dc, DrawPanel ); + + switch( id ) + { + case ID_GERBVIEW_GLOBAL_DELETE: + Erase_Current_Layer( true ); + ClearMsgPanel(); + break; + + case ID_NO_TOOL_SELECTED: + SetToolID( ID_NO_TOOL_SELECTED, DrawPanel->GetDefaultCursor(), wxEmptyString ); + break; + + case ID_POPUP_CLOSE_CURRENT_TOOL: + SetToolID( ID_NO_TOOL_SELECTED, DrawPanel->GetDefaultCursor(), wxEmptyString ); + break; + + case ID_POPUP_CANCEL_CURRENT_COMMAND: + break; + + case ID_GERBVIEW_SHOW_LIST_DCODES: + Liste_D_Codes(); + break; + + case ID_POPUP_PLACE_BLOCK: + GetScreen()->m_BlockLocate.m_Command = BLOCK_MOVE; + DrawPanel->m_AutoPAN_Request = FALSE; + HandleBlockPlace( &dc ); + break; + + case ID_POPUP_ZOOM_BLOCK: + GetScreen()->m_BlockLocate.m_Command = BLOCK_ZOOM; + GetScreen()->m_BlockLocate.SetMessageBlock( this ); + HandleBlockEnd( &dc ); + break; + + case ID_POPUP_DELETE_BLOCK: + GetScreen()->m_BlockLocate.m_Command = BLOCK_DELETE; + GetScreen()->m_BlockLocate.SetMessageBlock( this ); + HandleBlockEnd( &dc ); + break; + + default: + wxFAIL_MSG( wxT( "GERBVIEW_FRAME::Process_Special_Functions error" ) ); + break; + } +} + + +/* Selects the active DCode for the current active layer. + * Items using this DCode are hightlighted + */ +void GERBVIEW_FRAME::OnSelectActiveDCode( wxCommandEvent& event ) +{ + GERBER_IMAGE* gerber_image = g_GERBER_List[getActiveLayer()]; + if( gerber_image ) + { + int tool = m_DCodeSelector->GetSelectedDCodeId(); + if( tool != gerber_image->m_Selected_Tool ) + { + gerber_image->m_Selected_Tool = tool; + DrawPanel->Refresh(); + } + } +} + +/* Selects the active layer: + * - if a file is loaded, it is loaded in this layer + * _ this layer is displayed on top of other layers + */ +void GERBVIEW_FRAME::OnSelectActiveLayer( wxCommandEvent& event ) +{ + int layer = getActiveLayer(); + + setActiveLayer( event.GetSelection() ); + if( layer != getActiveLayer() ) + DrawPanel->Refresh(); +} + + +/* Call preferred editor to show (and edit) the gerber source file + * loaded in the active layer + */ +void GERBVIEW_FRAME::OnShowGerberSourceFile( wxCommandEvent& event ) +{ + int layer = getActiveLayer(); + GERBER_IMAGE* gerber_layer = g_GERBER_List[layer]; + + if( gerber_layer ) + { + wxString editorname = wxGetApp().GetEditorName(); + if( !editorname.IsEmpty() ) + { + wxFileName fn( gerber_layer->m_FileName ); + ExecuteFile( this, editorname, QuoteFullPath( fn ) ); + } + else + { + wxMessageBox( _( "No editor defined. Please select one" ) ); + } + } +} + + +/* Function OnSelectDisplayMode: called to select display mode + * (fast display, or exact mode with stacked images or with transparency + */ +void GERBVIEW_FRAME::OnSelectDisplayMode( wxCommandEvent& event ) +{ + int oldMode = GetDisplayMode(); + + switch( event.GetId() ) + { + case ID_TB_OPTIONS_SHOW_GBR_MODE_0: + SetDisplayMode( 0 ); + break; + + case ID_TB_OPTIONS_SHOW_GBR_MODE_1: + SetDisplayMode( 1 ); + break; + + case ID_TB_OPTIONS_SHOW_GBR_MODE_2: + SetDisplayMode( 2 ); + break; + } + + if( GetDisplayMode() != oldMode ) + DrawPanel->Refresh(); +} + +void GERBVIEW_FRAME::OnQuit( wxCommandEvent& event ) +{ + Close( true ); +} + +/** + * Function SetLanguage + * called on a language menu selection + * Update Layer manager title and tabs texts + */ +void GERBVIEW_FRAME::SetLanguage( wxCommandEvent& event ) +{ + EDA_DRAW_FRAME::SetLanguage( event ); + m_LayersManager->SetLayersManagerTabsText(); + wxAuiPaneInfo& pane_info = m_auimgr.GetPane( m_LayersManager ); + pane_info.Caption( _( "Visibles" ) ); + m_auimgr.Update(); + + ReFillLayerWidget(); +} diff --git a/gerbview/toolbars_gerber.cpp b/gerbview/toolbars_gerber.cpp index 5fd8f6618a..8f61722b41 100644 --- a/gerbview/toolbars_gerber.cpp +++ b/gerbview/toolbars_gerber.cpp @@ -42,16 +42,16 @@ void GERBVIEW_FRAME::ReCreateHToolbar( void ) _( "Print layers" ) ); m_HToolBar->AddSeparator(); - msg = AddHotkeyName( _( "Zoom in" ), s_Gerbview_Hokeys_Descr, HK_ZOOM_IN, false ); + msg = AddHotkeyName( _( "Zoom in" ), s_Gerbview_Hokeys_Descr, HK_ZOOM_IN, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_IN, wxEmptyString, KiBitmap( zoom_in_xpm ), msg ); - msg = AddHotkeyName( _( "Zoom out" ), s_Gerbview_Hokeys_Descr, HK_ZOOM_OUT, false ); + msg = AddHotkeyName( _( "Zoom out" ), s_Gerbview_Hokeys_Descr, HK_ZOOM_OUT, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_OUT, wxEmptyString, KiBitmap( zoom_out_xpm ), msg ); - msg = AddHotkeyName( _( "Redraw view" ), s_Gerbview_Hokeys_Descr, HK_ZOOM_REDRAW, false ); + msg = AddHotkeyName( _( "Redraw view" ), s_Gerbview_Hokeys_Descr, HK_ZOOM_REDRAW, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_REDRAW, wxEmptyString, KiBitmap( zoom_redraw_xpm ), msg ); - msg = AddHotkeyName( _( "Zoom auto" ), s_Gerbview_Hokeys_Descr, HK_ZOOM_AUTO, false ); + msg = AddHotkeyName( _( "Zoom auto" ), s_Gerbview_Hokeys_Descr, HK_ZOOM_AUTO, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_PAGE, wxEmptyString, KiBitmap( zoom_fit_in_page_xpm ), msg ); m_HToolBar->AddSeparator(); diff --git a/include/hotkeys_basic.h b/include/hotkeys_basic.h index 337c6dc705..0096384e27 100644 --- a/include/hotkeys_basic.h +++ b/include/hotkeys_basic.h @@ -14,7 +14,7 @@ class EDA_DRAW_FRAME; -/* Class to handle hotkey commnands. hotkeys have a default value +/* Class to handle hotkey commands. hotkeys have a default value * This class allows the real key code changed by user(from a key code list file) */ class Ki_HotkeyInfo @@ -93,6 +93,20 @@ wxString ReturnKeyNameFromCommandId( Ki_HotkeyInfo** aList, int aCommandI */ int ReturnKeyCodeFromKeyName( const wxString& keyname ); +/* An helper enum for AddHotkeyName function + * In menus we can an a hot key, or an accelerator , or sometimes just a comment + * Hot keys can perform actions using the current mouse cursor position + * Accelerators performs the same action as the associated menu + * A comment is used in tool tips for some tools (zoom ..) + * to show the hot key that perfoms this action + */ +enum HOTKEY_ACTION_TYPE +{ + IS_HOTKEY, + IS_ACCELERATOR, + IS_COMMENT +}; + /** * Function AddHotkeyName * Add the key name from the Command id value ( m_Idcommand member value) @@ -105,7 +119,7 @@ int ReturnKeyCodeFromKeyName( const wxString& keyname ); */ wxString AddHotkeyName( const wxString& aText, Ki_HotkeyInfo** aList, int aCommandId, - bool aIsShortCut = true); + HOTKEY_ACTION_TYPE aShortCutType = IS_HOTKEY); /** * Function AddHotkeyName @@ -120,7 +134,7 @@ wxString AddHotkeyName( const wxString& aText, Ki_HotkeyInfo** aList, wxString AddHotkeyName( const wxString& aText, struct Ki_HotkeyInfoSectionDescriptor* aDescrList, int aCommandId, - bool aIsShortCut = true); + HOTKEY_ACTION_TYPE aShortCutType = IS_HOTKEY ); /** * Function DisplayHotkeyList diff --git a/pcbnew/class_netinfo.h b/pcbnew/class_netinfo.h index fee01f1e6a..2c05f89e0f 100644 --- a/pcbnew/class_netinfo.h +++ b/pcbnew/class_netinfo.h @@ -1,401 +1,401 @@ -/** - * @file class_netinfo.h - */ - -/* - * Classes to handle info on nets - */ - -#ifndef __CLASSES_NETINFO__ -#define __CLASSES_NETINFO__ - -#include "class_netclass.h" - - -class LINE_READER; -class EDA_DRAW_PANEL; -class EDA_DRAW_FRAME; -class NETINFO_ITEM; -class D_PAD; -class BOARD; -class BOARD_ITEM; - - -/* Class RATSNEST_ITEM: describes a ratsnest line: a straight line connecting 2 pads */ - -/*****************************/ -/* flags for a RATSNEST_ITEM */ -/*****************************/ -#define CH_VISIBLE 1 /* Visible */ -#define CH_UNROUTABLE 2 /* Don't use autorouter. */ -#define CH_ROUTE_REQ 4 /* Must be routed by the autorouter. */ -#define CH_ACTIF 8 /* Not routed. */ -#define LOCAL_RATSNEST_ITEM 0x8000 /* Line between two pads of a single module. */ - -class RATSNEST_ITEM -{ -private: - int m_NetCode; // netcode ( = 1.. n , 0 is the value used for not connected items) - -public: - int m_Status; // State: see previous defines (CH_ ...) - D_PAD* m_PadStart; // pointer to the starting pad - D_PAD* m_PadEnd; // pointer to ending pad - int m_Lenght; // length of the line (used in some calculations) - - RATSNEST_ITEM(); - - /** - * Function GetNet - * @return int - the net code. - */ - int GetNet() const - { - return m_NetCode; - } - - - void SetNet( int aNetCode ) - { - m_NetCode = aNetCode; - } - - - /** - * Function Draw - */ - void Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int aDrawMode, const wxPoint& offset ); -}; - - -/***************************************************************/ -/******************* class NETINFO *****************************/ -/***************************************************************/ - -class NETINFO_LIST -{ -private: - BOARD* m_Parent; - std::vector m_NetBuffer; // nets buffer list (name, design constraints .. - -public: - std::vector m_PadsFullList; // Entry for a sorted pad list (used in ratsnest - // calculations) - -public: NETINFO_LIST( BOARD* aParent ); - ~NETINFO_LIST(); - - /** - * Function GetItem - * @param aNetcode = netcode to identify a given NETINFO_ITEM - * @return a NETINFO_ITEM pointer to the selected NETINFO_ITEM by its - * netcode, or NULL if not found - */ - NETINFO_ITEM* GetNetItem( int aNetcode ); - - /** - * Function GetCount - * @return the number of nets ( always >= 1 ) - * becuse the first net is the "not connected" net and always exists - */ - unsigned GetCount() { return m_NetBuffer.size(); } - - /** - * Function Append - * adds \a aNewElement to the end of the list. - */ - void AppendNet( NETINFO_ITEM* aNewElement ); - - /** - * Function DeleteData - * delete the list of nets (and free memory) - */ - void DeleteData(); - - /** - * Function BuildListOfNets - * Build or rebuild the list of NETINFO_ITEM m_NetBuffer - * The list is sorted by names. - */ - void BuildListOfNets(); - - /** - * Function GetPadsCount - * @return the number of pads in board - */ - unsigned GetPadsCount() - { - return m_PadsFullList.size(); - } - - - /** - * Function GetPad - * @return the pad idx from m_PadsFullList - */ - D_PAD* GetPad( unsigned aIdx ) - { - if( aIdx < m_PadsFullList.size() ) - return m_PadsFullList[aIdx]; - else - return NULL; - } - - -private: - - /** - * Function Build_Pads_Full_List - * Create the pad list - * initialise: - * m_Pads (list of pads) - * set m_Status_Pcb = LISTE_PAD_OK; - * and clear for all pads in list the m_SubRatsnest member; - * clear m_Pcb->m_FullRatsnest - */ - void Build_Pads_Full_List(); -}; - - -/** - * Class NETINFO_ITEM - * handles the data for a net - */ -class NETINFO_ITEM -{ -private: - int m_NetCode; // this is a number equivalent to the net name - // Used for fast comparisons in ratsnest and DRC computations. - - wxString m_Netname; // Full net name like /mysheet/mysubsheet/vout - // used by eeschema - - wxString m_ShortNetname; // short net name, like vout from - // /mysheet/mysubsheet/vout - - wxString m_NetClassName; // Net Class name. if void this is equivalent - // to "default" (the first - // item of the net classes list - - NETCLASS* m_NetClass; - - -public: - int m_NbNodes; // Pads count for this net - int m_NbLink; // Ratsnets count for this net - int m_NbNoconn; // Ratsnets remaining to route count - int m_Flag; // used in some calculations. Had no - // special meaning - - std::vector m_ListPad; // List of pads connected to this net - - unsigned m_RatsnestStartIdx; /* Starting point of ratsnests of this - * net (included) in a general buffer of - * ratsnest (a vector - * buffer) */ - - unsigned m_RatsnestEndIdx; // Ending point of ratsnests of this net - // (excluded) in this buffer - - NETINFO_ITEM( BOARD_ITEM* aParent ); - ~NETINFO_ITEM(); - - /** - * Function SetClass - * sets \a aNetclass into this NET - */ - void SetClass( const NETCLASS* aNetClass ) - { - m_NetClass = (NETCLASS*) aNetClass; - - if( aNetClass ) - m_NetClassName = aNetClass->GetName(); - else - m_NetClassName = NETCLASS::Default; - } - - - NETCLASS* GetNetClass() - { - return m_NetClass; - } - - - /** - * Function GetClassName - * returns the class name - */ - const wxString& GetClassName() const - { - return m_NetClassName; - } - - -#if 1 - - /** - * Function GetTrackWidth - * returns the width of tracks used to route this net. - */ - int GetTrackWidth() - { - wxASSERT( m_NetClass ); - return m_NetClass->GetTrackWidth(); - } - - /** - * Function GetViaSize - * returns the size of vias used to route this net - */ - int GetViaSize() - { - wxASSERT( m_NetClass ); - return m_NetClass->GetViaDiameter(); - } - - - /** - * Function GetMicroViaSize - * returns the size of vias used to route this net - */ - int GetMicroViaSize() - { - wxASSERT( m_NetClass ); - return m_NetClass->GetuViaDiameter(); - } - - - /** - * Function GetViaDrillSize - * returns the size of via drills used to route this net - */ - int GetViaDrillSize() - { - wxASSERT( m_NetClass ); - return m_NetClass->GetViaDrill(); - } - - - /** - * Function GetViaDrillSize - * returns the size of via drills used to route this net - */ - int GetMicroViaDrillSize() - { - wxASSERT( m_NetClass ); - return m_NetClass->GetuViaDrill(); - } - - -#if 0 - - /** - * Function GetViaMinSize - * returns the Minimum value for via sizes (used in DRC) - */ - int GetViaMinSize() - { - wxASSERT( m_NetClass ); - return m_NetClass->GetViaMinSize(); - } - - -#endif - - /** - * Function GetClearance - * returns the clearance when routing near aBoardItem - */ - int GetClearance( BOARD_ITEM* aBoardItem ) - { - wxASSERT( m_NetClass ); - return m_NetClass->GetClearance(); - } - - -#endif - - /* Reading and writing data on files */ - int ReadDescr( LINE_READER* aReader ); - - /** - * Function Save - * writes the data structures for this object out to a FILE in "*.brd" - * format. - * @param aFile The FILE to write to. - * @return bool - true if success writing else false. - */ - bool Save( FILE* aFile ) const; - - - /** - * Function Draw - * @todo we actually could show a NET, simply show all the tracks and - * a pads or net name on pad and vias - */ - void Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int aDrawMode, const wxPoint& offset ); - - - /** - * Function GetNet - * @return int - the netcode - */ - int GetNet() const { return m_NetCode; } - - void SetNet( int aNetCode ) { m_NetCode = aNetCode; } - - int GetNodesCount() const { return m_ListPad.size(); } - - /** - * Function GetNetname - * @return const wxString * , a pointer to the full netname - */ - wxString GetNetname() const { return m_Netname; } - - /** - * Function GetShortNetname - * @return const wxString * , a pointer to the short netname - */ - wxString GetShortNetname() const { return m_ShortNetname; } - - /** - * Function SetNetname - * @param aNetname : the new netname - */ - void SetNetname( const wxString& aNetname ); - - -/** - * Function DisplayInfo - * has knowledge about the frame and how and where to put status information - * about this object into the frame's message panel. - * Is virtual from EDA_ITEM. - * @param frame A EDA_DRAW_FRAME in which to print status information. - */ - void DisplayInfo( EDA_DRAW_FRAME* frame ); -}; - - -/***********************************************************/ -/* Description of a trace point for monitoring connections */ -/***********************************************************/ -#define START_ON_PAD 0x10 -#define END_ON_PAD 0x20 -#define START_ON_TRACK 0x40 -#define END_ON_TRACK 0x80 - - -/* Status bit (OR'ed bits) for class BOARD member .m_Status_Pcb */ -enum StatusPcbFlags { - LISTE_PAD_OK = 1, /* Pad list is Ok */ - LISTE_RATSNEST_ITEM_OK = 2, /* General Ratsnest is Ok */ - RATSNEST_ITEM_LOCAL_OK = 4, /* current MODULE ratsnest is Ok */ - CONNEXION_OK = 8, /* List of connections exists. */ - NET_CODES_OK = 0x10, /* Bit indicating that Netcode is OK, - * do not change net name. */ - DO_NOT_SHOW_GENERAL_RASTNEST = 0x20 /* Do not display the general - * ratsnest (used in module moves) */ -}; - - -#endif // __CLASSES_NETINFO__ +/** + * @file class_netinfo.h + */ + +/* + * Classes to handle info on nets + */ + +#ifndef __CLASSES_NETINFO__ +#define __CLASSES_NETINFO__ + +#include "class_netclass.h" + + +class LINE_READER; +class EDA_DRAW_PANEL; +class EDA_DRAW_FRAME; +class NETINFO_ITEM; +class D_PAD; +class BOARD; +class BOARD_ITEM; + + +/* Class RATSNEST_ITEM: describes a ratsnest line: a straight line connecting 2 pads */ + +/*****************************/ +/* flags for a RATSNEST_ITEM */ +/*****************************/ +#define CH_VISIBLE 1 /* Visible */ +#define CH_UNROUTABLE 2 /* Don't use autorouter. */ +#define CH_ROUTE_REQ 4 /* Must be routed by the autorouter. */ +#define CH_ACTIF 8 /* Not routed. */ +#define LOCAL_RATSNEST_ITEM 0x8000 /* Line between two pads of a single module. */ + +class RATSNEST_ITEM +{ +private: + int m_NetCode; // netcode ( = 1.. n , 0 is the value used for not connected items) + +public: + int m_Status; // State: see previous defines (CH_ ...) + D_PAD* m_PadStart; // pointer to the starting pad + D_PAD* m_PadEnd; // pointer to ending pad + int m_Lenght; // length of the line (used in some calculations) + + RATSNEST_ITEM(); + + /** + * Function GetNet + * @return int - the net code. + */ + int GetNet() const + { + return m_NetCode; + } + + + void SetNet( int aNetCode ) + { + m_NetCode = aNetCode; + } + + + /** + * Function Draw + */ + void Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int aDrawMode, const wxPoint& offset ); +}; + + +/***************************************************************/ +/******************* class NETINFO *****************************/ +/***************************************************************/ + +class NETINFO_LIST +{ +private: + BOARD* m_Parent; + std::vector m_NetBuffer; // nets buffer list (name, design constraints .. + +public: + std::vector m_PadsFullList; // Entry for a sorted pad list (used in ratsnest + // calculations) + +public: NETINFO_LIST( BOARD* aParent ); + ~NETINFO_LIST(); + + /** + * Function GetItem + * @param aNetcode = netcode to identify a given NETINFO_ITEM + * @return a NETINFO_ITEM pointer to the selected NETINFO_ITEM by its + * netcode, or NULL if not found + */ + NETINFO_ITEM* GetNetItem( int aNetcode ); + + /** + * Function GetCount + * @return the number of nets ( always >= 1 ) + * becuse the first net is the "not connected" net and always exists + */ + unsigned GetCount() { return m_NetBuffer.size(); } + + /** + * Function Append + * adds \a aNewElement to the end of the list. + */ + void AppendNet( NETINFO_ITEM* aNewElement ); + + /** + * Function DeleteData + * delete the list of nets (and free memory) + */ + void DeleteData(); + + /** + * Function BuildListOfNets + * Build or rebuild the list of NETINFO_ITEM m_NetBuffer + * The list is sorted by names. + */ + void BuildListOfNets(); + + /** + * Function GetPadsCount + * @return the number of pads in board + */ + unsigned GetPadsCount() + { + return m_PadsFullList.size(); + } + + + /** + * Function GetPad + * @return the pad idx from m_PadsFullList + */ + D_PAD* GetPad( unsigned aIdx ) + { + if( aIdx < m_PadsFullList.size() ) + return m_PadsFullList[aIdx]; + else + return NULL; + } + + +private: + + /** + * Function Build_Pads_Full_List + * Create the pad list + * initialise: + * m_Pads (list of pads) + * set m_Status_Pcb = LISTE_PAD_OK; + * and clear for all pads in list the m_SubRatsnest member; + * clear m_Pcb->m_FullRatsnest + */ + void Build_Pads_Full_List(); +}; + + +/** + * Class NETINFO_ITEM + * handles the data for a net + */ +class NETINFO_ITEM +{ +private: + int m_NetCode; // this is a number equivalent to the net name + // Used for fast comparisons in ratsnest and DRC computations. + + wxString m_Netname; // Full net name like /mysheet/mysubsheet/vout + // used by eeschema + + wxString m_ShortNetname; // short net name, like vout from + // /mysheet/mysubsheet/vout + + wxString m_NetClassName; // Net Class name. if void this is equivalent + // to "default" (the first + // item of the net classes list + + NETCLASS* m_NetClass; + + +public: + int m_NbNodes; // Pads count for this net + int m_NbLink; // Ratsnets count for this net + int m_NbNoconn; // Ratsnets remaining to route count + int m_Flag; // used in some calculations. Had no + // special meaning + + std::vector m_ListPad; // List of pads connected to this net + + unsigned m_RatsnestStartIdx; /* Starting point of ratsnests of this + * net (included) in a general buffer of + * ratsnest (a vector + * buffer) */ + + unsigned m_RatsnestEndIdx; // Ending point of ratsnests of this net + // (excluded) in this buffer + + NETINFO_ITEM( BOARD_ITEM* aParent ); + ~NETINFO_ITEM(); + + /** + * Function SetClass + * sets \a aNetclass into this NET + */ + void SetClass( const NETCLASS* aNetClass ) + { + m_NetClass = (NETCLASS*) aNetClass; + + if( aNetClass ) + m_NetClassName = aNetClass->GetName(); + else + m_NetClassName = NETCLASS::Default; + } + + + NETCLASS* GetNetClass() + { + return m_NetClass; + } + + + /** + * Function GetClassName + * returns the class name + */ + const wxString& GetClassName() const + { + return m_NetClassName; + } + + +#if 1 + + /** + * Function GetTrackWidth + * returns the width of tracks used to route this net. + */ + int GetTrackWidth() + { + wxASSERT( m_NetClass ); + return m_NetClass->GetTrackWidth(); + } + + /** + * Function GetViaSize + * returns the size of vias used to route this net + */ + int GetViaSize() + { + wxASSERT( m_NetClass ); + return m_NetClass->GetViaDiameter(); + } + + + /** + * Function GetMicroViaSize + * returns the size of vias used to route this net + */ + int GetMicroViaSize() + { + wxASSERT( m_NetClass ); + return m_NetClass->GetuViaDiameter(); + } + + + /** + * Function GetViaDrillSize + * returns the size of via drills used to route this net + */ + int GetViaDrillSize() + { + wxASSERT( m_NetClass ); + return m_NetClass->GetViaDrill(); + } + + + /** + * Function GetViaDrillSize + * returns the size of via drills used to route this net + */ + int GetMicroViaDrillSize() + { + wxASSERT( m_NetClass ); + return m_NetClass->GetuViaDrill(); + } + + +#if 0 + + /** + * Function GetViaMinSize + * returns the Minimum value for via sizes (used in DRC) + */ + int GetViaMinSize() + { + wxASSERT( m_NetClass ); + return m_NetClass->GetViaMinSize(); + } + + +#endif + + /** + * Function GetClearance + * returns the clearance when routing near aBoardItem + */ + int GetClearance( BOARD_ITEM* aBoardItem ) + { + wxASSERT( m_NetClass ); + return m_NetClass->GetClearance(); + } + + +#endif + + /* Reading and writing data on files */ + int ReadDescr( LINE_READER* aReader ); + + /** + * Function Save + * writes the data structures for this object out to a FILE in "*.brd" + * format. + * @param aFile The FILE to write to. + * @return bool - true if success writing else false. + */ + bool Save( FILE* aFile ) const; + + + /** + * Function Draw + * @todo we actually could show a NET, simply show all the tracks and + * a pads or net name on pad and vias + */ + void Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int aDrawMode, const wxPoint& offset ); + + + /** + * Function GetNet + * @return int - the netcode + */ + int GetNet() const { return m_NetCode; } + + void SetNet( int aNetCode ) { m_NetCode = aNetCode; } + + int GetNodesCount() const { return m_ListPad.size(); } + + /** + * Function GetNetname + * @return const wxString * , a pointer to the full netname + */ + wxString GetNetname() const { return m_Netname; } + + /** + * Function GetShortNetname + * @return const wxString * , a pointer to the short netname + */ + wxString GetShortNetname() const { return m_ShortNetname; } + + /** + * Function SetNetname + * @param aNetname : the new netname + */ + void SetNetname( const wxString& aNetname ); + + +/** + * Function DisplayInfo + * has knowledge about the frame and how and where to put status information + * about this object into the frame's message panel. + * Is virtual from EDA_ITEM. + * @param frame A EDA_DRAW_FRAME in which to print status information. + */ + void DisplayInfo( EDA_DRAW_FRAME* frame ); +}; + + +/***********************************************************/ +/* Description of a trace point for monitoring connections */ +/***********************************************************/ +#define START_ON_PAD 0x10 +#define END_ON_PAD 0x20 +#define START_ON_TRACK 0x40 +#define END_ON_TRACK 0x80 + + +/* Status bit (OR'ed bits) for class BOARD member .m_Status_Pcb */ +enum StatusPcbFlags { + LISTE_PAD_OK = 1, /* Pad list is Ok */ + LISTE_RATSNEST_ITEM_OK = 2, /* General Ratsnest is Ok */ + RATSNEST_ITEM_LOCAL_OK = 4, /* current MODULE ratsnest is Ok */ + CONNEXION_OK = 8, /* List of connections exists. */ + NET_CODES_OK = 0x10, /* Bit indicating that Netcode is OK, + * do not change net name. */ + DO_NOT_SHOW_GENERAL_RASTNEST = 0x20 /* Do not display the general + * ratsnest (used in module moves) */ +}; + + +#endif // __CLASSES_NETINFO__ diff --git a/pcbnew/class_pcb_layer_widget.cpp b/pcbnew/class_pcb_layer_widget.cpp index c714620c43..3b2dff067b 100644 --- a/pcbnew/class_pcb_layer_widget.cpp +++ b/pcbnew/class_pcb_layer_widget.cpp @@ -1,373 +1,373 @@ -/* - * This program source code file is part of KICAD, a free EDA CAD application. - * - * Copyright (C) 2004-2010 Jean-Pierre Charras, jean-pierre.charras@gpisa-lab.inpg.fr - * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck - * Copyright (C) 2010 Kicad Developers, see change_log.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 - */ - - -/******************************************************/ -/* class_pcb_layer_widget.cpp - Pcbnew layers manager */ -/******************************************************/ - -#include "fctsys.h" -#include "appl_wxstruct.h" -#include "class_drawpanel.h" -#include "confirm.h" -#include "wxPcbStruct.h" -#include "pcbstruct.h" // enum PCB_VISIBLE -#include "layer_widget.h" -#include "macros.h" -#include "pcbcommon.h" - -#include "class_board.h" -#include "class_pcb_layer_widget.h" - -#include "pcbnew.h" -#include "collectors.h" -#include "pcbnew_id.h" - - -/** - * Class PCB_LAYER_WIDGET - * is here to implement the abtract functions of LAYER_WIDGET so they - * may be tied into the PCB_EDIT_FRAME's data and so we can add a popup - * menu which is specific to PCBNEW's needs. - */ - - -PCB_LAYER_WIDGET::PCB_LAYER_WIDGET( PCB_EDIT_FRAME* aParent, wxWindow* aFocusOwner, int aPointSize ) : - LAYER_WIDGET( aParent, aFocusOwner, aPointSize ), - myframe( aParent ) -{ - ReFillRender(); - - // Update default tabs labels for gerbview - SetLayersManagerTabsText( ); - - //------------------------------------------------------ - // handle the popup menu over the layer window. - m_LayerScrolledWindow->Connect( wxEVT_RIGHT_DOWN, - wxMouseEventHandler( PCB_LAYER_WIDGET::onRightDownLayers ), NULL, this ); - - // since Popupmenu() calls this->ProcessEvent() we must call this->Connect() - // and not m_LayerScrolledWindow->Connect() - Connect( ID_SHOW_ALL_COPPERS, ID_SHOW_NO_COPPERS, wxEVT_COMMAND_MENU_SELECTED, - wxCommandEventHandler( PCB_LAYER_WIDGET::onPopupSelection ), NULL, this ); - - // install the right click handler into each control at end of ReFill() - // using installRightLayerClickHandler -} - - -void PCB_LAYER_WIDGET::installRightLayerClickHandler() -{ - int rowCount = GetLayerRowCount(); - for( int row=0; rowConnect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( - PCB_LAYER_WIDGET::onRightDownLayers ), NULL, this ); - } - } -} - - -void PCB_LAYER_WIDGET::onRightDownLayers( wxMouseEvent& event ) -{ - wxMenu menu; - - // menu text is capitalized: - // http://library.gnome.org/devel/hig-book/2.20/design-text-labels.html.en#layout-capitalization - menu.Append( new wxMenuItem( &menu, ID_SHOW_ALL_COPPERS, - _("Show All Copper Layers") ) ); - - menu.Append( new wxMenuItem( &menu, ID_SHOW_NO_COPPERS, - _( "Hide All Copper Layers" ) ) ); - - PopupMenu( &menu ); - - passOnFocus(); -} - -void PCB_LAYER_WIDGET::onPopupSelection( wxCommandEvent& event ) -{ - int rowCount; - int menuId = event.GetId(); - bool visible; - - switch( menuId ) - { - case ID_SHOW_ALL_COPPERS: - visible = true; - goto L_change_coppers; - - case ID_SHOW_NO_COPPERS: - visible = false; - L_change_coppers: - int lastCu = -1; - rowCount = GetLayerRowCount(); - for( int row=rowCount-1; row>=0; --row ) - { - wxCheckBox* cb = (wxCheckBox*) getLayerComp( row, 3 ); - int layer = getDecodedId( cb->GetId() ); - if( IsValidCopperLayerIndex( layer ) ) - { - lastCu = row; - break; - } - } - - for( int row=0; rowGetId() ); - - if( IsValidCopperLayerIndex( layer ) ) - { - cb->SetValue( visible ); - - bool isLastCopperLayer = (row==lastCu); - - OnLayerVisible( layer, visible, isLastCopperLayer ); - - if( isLastCopperLayer ) - break; - } - } - break; - } -} - -/** - * Function SetLayersManagerTabsText - * Update the layer manager tabs labels - * Useful when changing Language or to set labels to a non default value - */ -void PCB_LAYER_WIDGET::SetLayersManagerTabsText( ) -{ - m_notebook->SetPageText(0, _("Layer") ); - m_notebook->SetPageText(1, _("Render") ); -} - -/** - * Function ReFillRender - * Rebuild Render for instance after the config is read - */ -void PCB_LAYER_WIDGET::ReFillRender() -{ - BOARD* board = myframe->GetBoard(); - ClearRenderRows(); - // Fixed "Rendering" tab rows within the LAYER_WIDGET, only the initial color - // is changed before appending to the LAYER_WIDGET. This is an automatic variable - // not a static variable, change the color & state after copying from code to renderRows - // on the stack. - LAYER_WIDGET::ROW renderRows[16] = { - -#define RR LAYER_WIDGET::ROW // Render Row abreviation to reduce source width - - // text id color tooltip checked - RR( _( "Through Via" ), VIA_THROUGH_VISIBLE, WHITE, _( "Show through vias" ) ), - RR( _( "Bl/Buried Via" ), VIA_BBLIND_VISIBLE, WHITE, _( "Show blind or buried vias" ) ), - RR( _( "Micro Via" ), VIA_MICROVIA_VISIBLE, WHITE, _( "Show micro vias") ), - RR( _( "Ratsnest" ), RATSNEST_VISIBLE, WHITE, _( "Show unconnected nets as a ratsnest") ), - - RR( _( "Pads Front" ), PAD_FR_VISIBLE, WHITE, _( "Show footprint pads on board's front" ) ), - RR( _( "Pads Back" ), PAD_BK_VISIBLE, WHITE, _( "Show footprint pads on board's back" ) ), - - RR( _( "Text Front" ), MOD_TEXT_FR_VISIBLE, WHITE, _( "Show footprint text on board's back" ) ), - RR( _( "Text Back" ), MOD_TEXT_BK_VISIBLE, WHITE, _( "Show footprint text on board's back" ) ), - RR( _( "Hidden Text" ), MOD_TEXT_INVISIBLE, WHITE, _( "Show footprint text marked as invisible" ) ), - - RR( _( "Anchors" ), ANCHOR_VISIBLE, WHITE, _( "Show footprint and text origins as a cross" ) ), - RR( _( "Grid" ), GRID_VISIBLE, WHITE, _( "Show the (x,y) grid dots" ) ), - RR( _( "No-Connects" ), NO_CONNECTS_VISIBLE, -1, _( "Show a marker on pads which have no net connected" ) ), - RR( _( "Modules Front" ), MOD_FR_VISIBLE, -1, _( "Show footprints that are on board's front") ), - RR( _( "Modules Back" ), MOD_BK_VISIBLE, -1, _( "Show footprints that are on board's back") ), - RR( _( "Values" ), MOD_VALUES_VISIBLE, -1, _( "Show footprint's values") ), - RR( _( "References" ), MOD_REFERENCES_VISIBLE, -1, _( "Show footprint's references") ), - }; - - for( unsigned row=0; rowGetVisibleElementColor( renderRows[row].id ); - } - renderRows[row].state = board->IsElementVisible( renderRows[row].id ); - } - - AppendRenderRows( renderRows, DIM(renderRows) ); -} - -void PCB_LAYER_WIDGET::ReFill() -{ - BOARD* brd = myframe->GetBoard(); - int layer; - - int enabledLayers = brd->GetEnabledLayers(); - -// m_Layers->Freeze(); // no screen updates until done modifying - - ClearLayerRows(); - - // show all coppers first, with front on top, back on bottom, then technical layers - - layer = LAYER_N_FRONT; - if( enabledLayers & (1 << layer) ) - { - AppendLayerRow( LAYER_WIDGET::ROW( - brd->GetLayerName( layer ), layer, brd->GetLayerColor( layer ), _("Front copper layer"), true ) ); - } - - for( layer = LAYER_N_FRONT-1; layer >= 1; --layer ) - { - if( enabledLayers & (1 << layer) ) - { - AppendLayerRow( LAYER_WIDGET::ROW( - brd->GetLayerName( layer ), layer, brd->GetLayerColor( layer ), _("An innner copper layer"), true ) ); - } - } - - layer = LAYER_N_BACK; - if( enabledLayers & (1 << layer) ) - { - AppendLayerRow( LAYER_WIDGET::ROW( - brd->GetLayerName( layer ), layer, brd->GetLayerColor( layer ), _("Back copper layer"), true ) ); - } - - // technical layers are shown in this order: - static const struct { - int layerId; - wxString tooltip; - } techLayerSeq[] = { - { ADHESIVE_N_FRONT, _( "Adhesive on board's front" ) }, - { ADHESIVE_N_BACK, _( "Adhesive on board's back" ) }, - { SOLDERPASTE_N_FRONT, _( "Solder paste on board's front" )}, - { SOLDERPASTE_N_BACK, _( "Solder paste on board's back" ) }, - { SILKSCREEN_N_FRONT, _( "Silkscreen on board's front" ) }, - { SILKSCREEN_N_BACK, _( "Silkscreen on board's back" ) }, - { SOLDERMASK_N_FRONT, _( "Solder mask on board's front" ) }, - { SOLDERMASK_N_BACK, _( "Solder mask on board's back" ) }, - { DRAW_N, _( "Explanatory drawings" ) }, - { COMMENT_N, _( "Explanatory comments" ) }, - { ECO1_N, _( "TDB" ) }, - { ECO2_N, _( "TBD" ) }, - { EDGE_N, _( "Board's perimeter definition" ) }, - }; - - for( unsigned i=0; iGetLayerName( layer ), layer, brd->GetLayerColor( layer ), - techLayerSeq[i].tooltip, true ) ); - } - - installRightLayerClickHandler(); - -// m_Layers->Thaw(); -} - -//------------------------------------------------ - -void PCB_LAYER_WIDGET::OnLayerColorChange( int aLayer, int aColor ) -{ - myframe->GetBoard()->SetLayerColor( aLayer, aColor ); - myframe->ReCreateLayerBox( NULL ); - myframe->DrawPanel->Refresh(); -} - -bool PCB_LAYER_WIDGET::OnLayerSelect( int aLayer ) -{ - // the layer change from the PCB_LAYER_WIDGET can be denied by returning - // false from this function. - myframe->setActiveLayer( aLayer, false ); - - if(DisplayOpt.ContrastModeDisplay) - myframe->DrawPanel->Refresh(); - - return true; -} - -void PCB_LAYER_WIDGET::OnLayerVisible( int aLayer, bool isVisible, bool isFinal ) -{ - BOARD* brd = myframe->GetBoard(); - - int visibleLayers = brd->GetVisibleLayers(); - - if( isVisible ) - visibleLayers |= (1 << aLayer); - else - visibleLayers &= ~(1 << aLayer); - - brd->SetVisibleLayers( visibleLayers ); - - if( isFinal ) - myframe->DrawPanel->Refresh(); -} - -void PCB_LAYER_WIDGET::OnRenderColorChange( int aId, int aColor ) -{ - myframe->GetBoard()->SetVisibleElementColor( aId, aColor ); - myframe->DrawPanel->Refresh(); -} - -void PCB_LAYER_WIDGET::OnRenderEnable( int aId, bool isEnabled ) -{ - BOARD* brd = myframe->GetBoard(); - - /* @todo: - - move: - - GRID_VISIBLE, ? maybe not this one - into m_VisibleElements and get rid of globals. - */ - - switch( aId ) - { - // see todo above, don't really want anything except IsElementVisible() here. - - case GRID_VISIBLE: - // @todo, make read/write accessors for grid control so the write accessor can fire updates to - // grid state listeners. I think the grid state should be kept in the BOARD. - brd->SetElementVisibility( aId, isEnabled ); // set visibilty flag also in list, and myframe->m_Draw_Grid - break; - - default: - brd->SetElementVisibility( aId, isEnabled ); - } - - myframe->DrawPanel->Refresh(); -} - -//----------------------------------------------- - - +/* + * This program source code file is part of KICAD, a free EDA CAD application. + * + * Copyright (C) 2004-2010 Jean-Pierre Charras, jean-pierre.charras@gpisa-lab.inpg.fr + * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2010 Kicad Developers, see change_log.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 + */ + + +/******************************************************/ +/* class_pcb_layer_widget.cpp - Pcbnew layers manager */ +/******************************************************/ + +#include "fctsys.h" +#include "appl_wxstruct.h" +#include "class_drawpanel.h" +#include "confirm.h" +#include "wxPcbStruct.h" +#include "pcbstruct.h" // enum PCB_VISIBLE +#include "layer_widget.h" +#include "macros.h" +#include "pcbcommon.h" + +#include "class_board.h" +#include "class_pcb_layer_widget.h" + +#include "pcbnew.h" +#include "collectors.h" +#include "pcbnew_id.h" + + +/** + * Class PCB_LAYER_WIDGET + * is here to implement the abtract functions of LAYER_WIDGET so they + * may be tied into the PCB_EDIT_FRAME's data and so we can add a popup + * menu which is specific to PCBNEW's needs. + */ + + +PCB_LAYER_WIDGET::PCB_LAYER_WIDGET( PCB_EDIT_FRAME* aParent, wxWindow* aFocusOwner, int aPointSize ) : + LAYER_WIDGET( aParent, aFocusOwner, aPointSize ), + myframe( aParent ) +{ + ReFillRender(); + + // Update default tabs labels for gerbview + SetLayersManagerTabsText( ); + + //------------------------------------------------------ + // handle the popup menu over the layer window. + m_LayerScrolledWindow->Connect( wxEVT_RIGHT_DOWN, + wxMouseEventHandler( PCB_LAYER_WIDGET::onRightDownLayers ), NULL, this ); + + // since Popupmenu() calls this->ProcessEvent() we must call this->Connect() + // and not m_LayerScrolledWindow->Connect() + Connect( ID_SHOW_ALL_COPPERS, ID_SHOW_NO_COPPERS, wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler( PCB_LAYER_WIDGET::onPopupSelection ), NULL, this ); + + // install the right click handler into each control at end of ReFill() + // using installRightLayerClickHandler +} + + +void PCB_LAYER_WIDGET::installRightLayerClickHandler() +{ + int rowCount = GetLayerRowCount(); + for( int row=0; rowConnect( wxEVT_RIGHT_DOWN, wxMouseEventHandler( + PCB_LAYER_WIDGET::onRightDownLayers ), NULL, this ); + } + } +} + + +void PCB_LAYER_WIDGET::onRightDownLayers( wxMouseEvent& event ) +{ + wxMenu menu; + + // menu text is capitalized: + // http://library.gnome.org/devel/hig-book/2.20/design-text-labels.html.en#layout-capitalization + menu.Append( new wxMenuItem( &menu, ID_SHOW_ALL_COPPERS, + _("Show All Copper Layers") ) ); + + menu.Append( new wxMenuItem( &menu, ID_SHOW_NO_COPPERS, + _( "Hide All Copper Layers" ) ) ); + + PopupMenu( &menu ); + + passOnFocus(); +} + +void PCB_LAYER_WIDGET::onPopupSelection( wxCommandEvent& event ) +{ + int rowCount; + int menuId = event.GetId(); + bool visible; + + switch( menuId ) + { + case ID_SHOW_ALL_COPPERS: + visible = true; + goto L_change_coppers; + + case ID_SHOW_NO_COPPERS: + visible = false; + L_change_coppers: + int lastCu = -1; + rowCount = GetLayerRowCount(); + for( int row=rowCount-1; row>=0; --row ) + { + wxCheckBox* cb = (wxCheckBox*) getLayerComp( row, 3 ); + int layer = getDecodedId( cb->GetId() ); + if( IsValidCopperLayerIndex( layer ) ) + { + lastCu = row; + break; + } + } + + for( int row=0; rowGetId() ); + + if( IsValidCopperLayerIndex( layer ) ) + { + cb->SetValue( visible ); + + bool isLastCopperLayer = (row==lastCu); + + OnLayerVisible( layer, visible, isLastCopperLayer ); + + if( isLastCopperLayer ) + break; + } + } + break; + } +} + +/** + * Function SetLayersManagerTabsText + * Update the layer manager tabs labels + * Useful when changing Language or to set labels to a non default value + */ +void PCB_LAYER_WIDGET::SetLayersManagerTabsText( ) +{ + m_notebook->SetPageText(0, _("Layer") ); + m_notebook->SetPageText(1, _("Render") ); +} + +/** + * Function ReFillRender + * Rebuild Render for instance after the config is read + */ +void PCB_LAYER_WIDGET::ReFillRender() +{ + BOARD* board = myframe->GetBoard(); + ClearRenderRows(); + // Fixed "Rendering" tab rows within the LAYER_WIDGET, only the initial color + // is changed before appending to the LAYER_WIDGET. This is an automatic variable + // not a static variable, change the color & state after copying from code to renderRows + // on the stack. + LAYER_WIDGET::ROW renderRows[16] = { + +#define RR LAYER_WIDGET::ROW // Render Row abreviation to reduce source width + + // text id color tooltip checked + RR( _( "Through Via" ), VIA_THROUGH_VISIBLE, WHITE, _( "Show through vias" ) ), + RR( _( "Bl/Buried Via" ), VIA_BBLIND_VISIBLE, WHITE, _( "Show blind or buried vias" ) ), + RR( _( "Micro Via" ), VIA_MICROVIA_VISIBLE, WHITE, _( "Show micro vias") ), + RR( _( "Ratsnest" ), RATSNEST_VISIBLE, WHITE, _( "Show unconnected nets as a ratsnest") ), + + RR( _( "Pads Front" ), PAD_FR_VISIBLE, WHITE, _( "Show footprint pads on board's front" ) ), + RR( _( "Pads Back" ), PAD_BK_VISIBLE, WHITE, _( "Show footprint pads on board's back" ) ), + + RR( _( "Text Front" ), MOD_TEXT_FR_VISIBLE, WHITE, _( "Show footprint text on board's back" ) ), + RR( _( "Text Back" ), MOD_TEXT_BK_VISIBLE, WHITE, _( "Show footprint text on board's back" ) ), + RR( _( "Hidden Text" ), MOD_TEXT_INVISIBLE, WHITE, _( "Show footprint text marked as invisible" ) ), + + RR( _( "Anchors" ), ANCHOR_VISIBLE, WHITE, _( "Show footprint and text origins as a cross" ) ), + RR( _( "Grid" ), GRID_VISIBLE, WHITE, _( "Show the (x,y) grid dots" ) ), + RR( _( "No-Connects" ), NO_CONNECTS_VISIBLE, -1, _( "Show a marker on pads which have no net connected" ) ), + RR( _( "Modules Front" ), MOD_FR_VISIBLE, -1, _( "Show footprints that are on board's front") ), + RR( _( "Modules Back" ), MOD_BK_VISIBLE, -1, _( "Show footprints that are on board's back") ), + RR( _( "Values" ), MOD_VALUES_VISIBLE, -1, _( "Show footprint's values") ), + RR( _( "References" ), MOD_REFERENCES_VISIBLE, -1, _( "Show footprint's references") ), + }; + + for( unsigned row=0; rowGetVisibleElementColor( renderRows[row].id ); + } + renderRows[row].state = board->IsElementVisible( renderRows[row].id ); + } + + AppendRenderRows( renderRows, DIM(renderRows) ); +} + +void PCB_LAYER_WIDGET::ReFill() +{ + BOARD* brd = myframe->GetBoard(); + int layer; + + int enabledLayers = brd->GetEnabledLayers(); + +// m_Layers->Freeze(); // no screen updates until done modifying + + ClearLayerRows(); + + // show all coppers first, with front on top, back on bottom, then technical layers + + layer = LAYER_N_FRONT; + if( enabledLayers & (1 << layer) ) + { + AppendLayerRow( LAYER_WIDGET::ROW( + brd->GetLayerName( layer ), layer, brd->GetLayerColor( layer ), _("Front copper layer"), true ) ); + } + + for( layer = LAYER_N_FRONT-1; layer >= 1; --layer ) + { + if( enabledLayers & (1 << layer) ) + { + AppendLayerRow( LAYER_WIDGET::ROW( + brd->GetLayerName( layer ), layer, brd->GetLayerColor( layer ), _("An innner copper layer"), true ) ); + } + } + + layer = LAYER_N_BACK; + if( enabledLayers & (1 << layer) ) + { + AppendLayerRow( LAYER_WIDGET::ROW( + brd->GetLayerName( layer ), layer, brd->GetLayerColor( layer ), _("Back copper layer"), true ) ); + } + + // technical layers are shown in this order: + static const struct { + int layerId; + wxString tooltip; + } techLayerSeq[] = { + { ADHESIVE_N_FRONT, _( "Adhesive on board's front" ) }, + { ADHESIVE_N_BACK, _( "Adhesive on board's back" ) }, + { SOLDERPASTE_N_FRONT, _( "Solder paste on board's front" )}, + { SOLDERPASTE_N_BACK, _( "Solder paste on board's back" ) }, + { SILKSCREEN_N_FRONT, _( "Silkscreen on board's front" ) }, + { SILKSCREEN_N_BACK, _( "Silkscreen on board's back" ) }, + { SOLDERMASK_N_FRONT, _( "Solder mask on board's front" ) }, + { SOLDERMASK_N_BACK, _( "Solder mask on board's back" ) }, + { DRAW_N, _( "Explanatory drawings" ) }, + { COMMENT_N, _( "Explanatory comments" ) }, + { ECO1_N, _( "TDB" ) }, + { ECO2_N, _( "TBD" ) }, + { EDGE_N, _( "Board's perimeter definition" ) }, + }; + + for( unsigned i=0; iGetLayerName( layer ), layer, brd->GetLayerColor( layer ), + techLayerSeq[i].tooltip, true ) ); + } + + installRightLayerClickHandler(); + +// m_Layers->Thaw(); +} + +//------------------------------------------------ + +void PCB_LAYER_WIDGET::OnLayerColorChange( int aLayer, int aColor ) +{ + myframe->GetBoard()->SetLayerColor( aLayer, aColor ); + myframe->ReCreateLayerBox( NULL ); + myframe->DrawPanel->Refresh(); +} + +bool PCB_LAYER_WIDGET::OnLayerSelect( int aLayer ) +{ + // the layer change from the PCB_LAYER_WIDGET can be denied by returning + // false from this function. + myframe->setActiveLayer( aLayer, false ); + + if(DisplayOpt.ContrastModeDisplay) + myframe->DrawPanel->Refresh(); + + return true; +} + +void PCB_LAYER_WIDGET::OnLayerVisible( int aLayer, bool isVisible, bool isFinal ) +{ + BOARD* brd = myframe->GetBoard(); + + int visibleLayers = brd->GetVisibleLayers(); + + if( isVisible ) + visibleLayers |= (1 << aLayer); + else + visibleLayers &= ~(1 << aLayer); + + brd->SetVisibleLayers( visibleLayers ); + + if( isFinal ) + myframe->DrawPanel->Refresh(); +} + +void PCB_LAYER_WIDGET::OnRenderColorChange( int aId, int aColor ) +{ + myframe->GetBoard()->SetVisibleElementColor( aId, aColor ); + myframe->DrawPanel->Refresh(); +} + +void PCB_LAYER_WIDGET::OnRenderEnable( int aId, bool isEnabled ) +{ + BOARD* brd = myframe->GetBoard(); + + /* @todo: + + move: + + GRID_VISIBLE, ? maybe not this one + into m_VisibleElements and get rid of globals. + */ + + switch( aId ) + { + // see todo above, don't really want anything except IsElementVisible() here. + + case GRID_VISIBLE: + // @todo, make read/write accessors for grid control so the write accessor can fire updates to + // grid state listeners. I think the grid state should be kept in the BOARD. + brd->SetElementVisibility( aId, isEnabled ); // set visibilty flag also in list, and myframe->m_Draw_Grid + break; + + default: + brd->SetElementVisibility( aId, isEnabled ); + } + + myframe->DrawPanel->Refresh(); +} + +//----------------------------------------------- + + diff --git a/pcbnew/drc_marker_functions.cpp b/pcbnew/drc_marker_functions.cpp index 4d3e1609dc..dbacf718e7 100644 --- a/pcbnew/drc_marker_functions.cpp +++ b/pcbnew/drc_marker_functions.cpp @@ -1,175 +1,175 @@ -/* - * drc_marker_functions.cpp - */ -/* - * This program source code file is part of KICAD, a free EDA CAD application. - * - * Copyright (C) 2010 Dick Hollenbeck, dick@softplc.com - * Copyright (C) 2004-2010 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.fr - * Copyright (C) 2007 Kicad Developers, see change_log.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 - */ - - -/* Methods of class DRC to initialize drc markers with messages - * according to items and error ode -*/ - -#include "fctsys.h" -#include "common.h" -#include "pcbnew.h" -#include "class_board_design_settings.h" - -#include "drc_stuff.h" -#include "class_pad.h" -#include "class_track.h" -#include "class_zone.h" -#include "class_marker_pcb.h" - - -MARKER_PCB* DRC::fillMarker( TRACK* aTrack, BOARD_ITEM* aItem, int aErrorCode, MARKER_PCB* fillMe ) -{ - wxString textA = aTrack->GetSelectMenuText(); - wxString textB; - - wxPoint position; - wxPoint posB; - - if( aItem ) // aItem might be NULL - { - textB = aItem->GetSelectMenuText(); - posB = aItem->GetPosition(); - - if( aItem->Type() == TYPE_PAD ) - position = aItem->GetPosition(); - - else if( aItem->Type() == TYPE_VIA ) - position = aItem->GetPosition(); - - else if( aItem->Type() == TYPE_TRACK ) - { - TRACK* track = (TRACK*) aItem; - wxPoint endPos = track->m_End; - - // either of aItem's start or end will be used for the marker position - // first assume start, then switch at end if needed. decision made on - // distance from end of aTrack. - position = track->m_Start; - - double dToEnd = hypot( endPos.x - aTrack->m_End.x, - endPos.y - aTrack->m_End.y ); - double dToStart = hypot( position.x - aTrack->m_End.x, - position.y - aTrack->m_End.y ); - - if( dToEnd < dToStart ) - position = endPos; - } - } - else - position = aTrack->GetPosition(); - - if( fillMe ) - { - if( aItem ) - fillMe->SetData( aErrorCode, position, - textA, aTrack->GetPosition(), - textB, posB ); - else - fillMe->SetData( aErrorCode, position, - textA, aTrack->GetPosition() ); - } - else - { - if( aItem ) - fillMe = new MARKER_PCB( aErrorCode, position, - textA, aTrack->GetPosition(), - textB, posB ); - else - fillMe = new MARKER_PCB( aErrorCode, position, - textA, aTrack->GetPosition() ); - } - - return fillMe; -} - - -MARKER_PCB* DRC::fillMarker( D_PAD* aPad, D_PAD* bPad, int aErrorCode, MARKER_PCB* fillMe ) -{ - wxString textA = aPad->GetSelectMenuText(); - wxString textB = bPad->GetSelectMenuText(); - - wxPoint posA = aPad->GetPosition(); - wxPoint posB = bPad->GetPosition(); - - if( fillMe ) - fillMe->SetData( aErrorCode, posA, textA, posA, textB, posB ); - else - fillMe = new MARKER_PCB( aErrorCode, posA, textA, posA, textB, posB ); - - return fillMe; -} - - -MARKER_PCB* DRC::fillMarker( ZONE_CONTAINER* aArea, int aErrorCode, MARKER_PCB* fillMe ) -{ - wxString textA = aArea->GetSelectMenuText(); - - wxPoint posA = aArea->GetPosition(); - - if( fillMe ) - fillMe->SetData( aErrorCode, posA, textA, posA ); - else - fillMe = new MARKER_PCB( aErrorCode, posA, textA, posA ); - - return fillMe; -} - - -MARKER_PCB* DRC::fillMarker( const ZONE_CONTAINER* aArea, - const wxPoint& aPos, - int aErrorCode, - MARKER_PCB* fillMe ) -{ - wxString textA = aArea->GetSelectMenuText(); - - wxPoint posA = aPos; - - if( fillMe ) - fillMe->SetData( aErrorCode, posA, textA, posA ); - else - fillMe = new MARKER_PCB( aErrorCode, posA, textA, posA ); - - return fillMe; -} - - -MARKER_PCB* DRC::fillMarker( int aErrorCode, const wxString& aMessage, MARKER_PCB* fillMe ) -{ - wxPoint posA; // not displayed - - if( fillMe ) - fillMe->SetData( aErrorCode, posA, aMessage, posA ); - else - fillMe = new MARKER_PCB( aErrorCode, posA, aMessage, posA ); - - fillMe->SetShowNoCoordinate(); - - return fillMe; -} - +/* + * drc_marker_functions.cpp + */ +/* + * This program source code file is part of KICAD, a free EDA CAD application. + * + * Copyright (C) 2010 Dick Hollenbeck, dick@softplc.com + * Copyright (C) 2004-2010 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.fr + * Copyright (C) 2007 Kicad Developers, see change_log.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 + */ + + +/* Methods of class DRC to initialize drc markers with messages + * according to items and error ode +*/ + +#include "fctsys.h" +#include "common.h" +#include "pcbnew.h" +#include "class_board_design_settings.h" + +#include "drc_stuff.h" +#include "class_pad.h" +#include "class_track.h" +#include "class_zone.h" +#include "class_marker_pcb.h" + + +MARKER_PCB* DRC::fillMarker( TRACK* aTrack, BOARD_ITEM* aItem, int aErrorCode, MARKER_PCB* fillMe ) +{ + wxString textA = aTrack->GetSelectMenuText(); + wxString textB; + + wxPoint position; + wxPoint posB; + + if( aItem ) // aItem might be NULL + { + textB = aItem->GetSelectMenuText(); + posB = aItem->GetPosition(); + + if( aItem->Type() == TYPE_PAD ) + position = aItem->GetPosition(); + + else if( aItem->Type() == TYPE_VIA ) + position = aItem->GetPosition(); + + else if( aItem->Type() == TYPE_TRACK ) + { + TRACK* track = (TRACK*) aItem; + wxPoint endPos = track->m_End; + + // either of aItem's start or end will be used for the marker position + // first assume start, then switch at end if needed. decision made on + // distance from end of aTrack. + position = track->m_Start; + + double dToEnd = hypot( endPos.x - aTrack->m_End.x, + endPos.y - aTrack->m_End.y ); + double dToStart = hypot( position.x - aTrack->m_End.x, + position.y - aTrack->m_End.y ); + + if( dToEnd < dToStart ) + position = endPos; + } + } + else + position = aTrack->GetPosition(); + + if( fillMe ) + { + if( aItem ) + fillMe->SetData( aErrorCode, position, + textA, aTrack->GetPosition(), + textB, posB ); + else + fillMe->SetData( aErrorCode, position, + textA, aTrack->GetPosition() ); + } + else + { + if( aItem ) + fillMe = new MARKER_PCB( aErrorCode, position, + textA, aTrack->GetPosition(), + textB, posB ); + else + fillMe = new MARKER_PCB( aErrorCode, position, + textA, aTrack->GetPosition() ); + } + + return fillMe; +} + + +MARKER_PCB* DRC::fillMarker( D_PAD* aPad, D_PAD* bPad, int aErrorCode, MARKER_PCB* fillMe ) +{ + wxString textA = aPad->GetSelectMenuText(); + wxString textB = bPad->GetSelectMenuText(); + + wxPoint posA = aPad->GetPosition(); + wxPoint posB = bPad->GetPosition(); + + if( fillMe ) + fillMe->SetData( aErrorCode, posA, textA, posA, textB, posB ); + else + fillMe = new MARKER_PCB( aErrorCode, posA, textA, posA, textB, posB ); + + return fillMe; +} + + +MARKER_PCB* DRC::fillMarker( ZONE_CONTAINER* aArea, int aErrorCode, MARKER_PCB* fillMe ) +{ + wxString textA = aArea->GetSelectMenuText(); + + wxPoint posA = aArea->GetPosition(); + + if( fillMe ) + fillMe->SetData( aErrorCode, posA, textA, posA ); + else + fillMe = new MARKER_PCB( aErrorCode, posA, textA, posA ); + + return fillMe; +} + + +MARKER_PCB* DRC::fillMarker( const ZONE_CONTAINER* aArea, + const wxPoint& aPos, + int aErrorCode, + MARKER_PCB* fillMe ) +{ + wxString textA = aArea->GetSelectMenuText(); + + wxPoint posA = aPos; + + if( fillMe ) + fillMe->SetData( aErrorCode, posA, textA, posA ); + else + fillMe = new MARKER_PCB( aErrorCode, posA, textA, posA ); + + return fillMe; +} + + +MARKER_PCB* DRC::fillMarker( int aErrorCode, const wxString& aMessage, MARKER_PCB* fillMe ) +{ + wxPoint posA; // not displayed + + if( fillMe ) + fillMe->SetData( aErrorCode, posA, aMessage, posA ); + else + fillMe = new MARKER_PCB( aErrorCode, posA, aMessage, posA ); + + fillMe->SetShowNoCoordinate(); + + return fillMe; +} + diff --git a/pcbnew/menubar_pcbframe.cpp b/pcbnew/menubar_pcbframe.cpp index 7040dc0ae3..cec069507a 100644 --- a/pcbnew/menubar_pcbframe.cpp +++ b/pcbnew/menubar_pcbframe.cpp @@ -44,11 +44,11 @@ void PCB_EDIT_FRAME::ReCreateMenuBar() filesMenu->Append( item ); // Open - item = new wxMenuItem( filesMenu, ID_LOAD_FILE, - _( "&Open\tCtrl+O" ), - _( "Delete current board and load new board" ) ); - SET_BITMAP( KiBitmap( open_document_xpm ) ); - filesMenu->Append( item ); + text = AddHotkeyName( _( "&Open" ), g_Board_Editor_Hokeys_Descr, + HK_LOAD_BOARD ); + AddMenuItem( filesMenu, ID_LOAD_FILE, text, + _( "Delete current board and load new board" ), + KiBitmap( open_document_xpm ) ); // Load Recent submenu static wxMenu* openRecentMenu; @@ -78,11 +78,11 @@ void PCB_EDIT_FRAME::ReCreateMenuBar() filesMenu->AppendSeparator(); // Save - item = new wxMenuItem( filesMenu, ID_SAVE_BOARD, - _( "&Save\tCtrl+S" ), - _( "Save current board" ) ); - SET_BITMAP( KiBitmap( save_xpm ) ); - filesMenu->Append( item ); + text = AddHotkeyName( _( "&Save" ), g_Board_Editor_Hokeys_Descr, + HK_SAVE_BOARD ); + AddMenuItem( filesMenu, ID_SAVE_BOARD, text, + _( "Save current board" ), + KiBitmap( save_xpm ) ); // Save As item = new wxMenuItem( filesMenu, ID_SAVE_BOARD_AS, @@ -204,7 +204,7 @@ void PCB_EDIT_FRAME::ReCreateMenuBar() // Print item = new wxMenuItem( filesMenu, wxID_PRINT, - _( "&Print\tCtrl+P" ), + _( "&Print" ), _( "Print board" ) ); SET_BITMAP( KiBitmap( print_button_xpm ) ); filesMenu->Append( item ); @@ -336,20 +336,23 @@ void PCB_EDIT_FRAME::ReCreateMenuBar() * for Zoom in and Zoom out sub menus */ // Zoom In - text = AddHotkeyName( _( "Zoom In" ), g_Pcbnew_Editor_Hokeys_Descr, HK_ZOOM_IN, false ); + text = AddHotkeyName( _( "Zoom In" ), g_Pcbnew_Editor_Hokeys_Descr, + HK_ZOOM_IN, IS_ACCELERATOR ); item = new wxMenuItem( viewMenu, ID_ZOOM_IN, text, HELP_ZOOM_IN, wxITEM_NORMAL ); SET_BITMAP( KiBitmap( zoom_in_xpm ) ); viewMenu->Append( item ); // Zoom Out - text = AddHotkeyName( _( "Zoom Out" ), g_Pcbnew_Editor_Hokeys_Descr, HK_ZOOM_OUT, false ); + text = AddHotkeyName( _( "Zoom Out" ), g_Pcbnew_Editor_Hokeys_Descr, + HK_ZOOM_OUT, IS_ACCELERATOR ); item = new wxMenuItem( viewMenu, ID_ZOOM_OUT, text, HELP_ZOOM_OUT, wxITEM_NORMAL ); SET_BITMAP( KiBitmap( zoom_out_xpm ) ); viewMenu->Append( item ); // Fit on Screen - text = AddHotkeyName( _( "Fit on Screen" ), g_Pcbnew_Editor_Hokeys_Descr, HK_ZOOM_AUTO ); + text = AddHotkeyName( _( "Fit on Screen" ), g_Pcbnew_Editor_Hokeys_Descr, + HK_ZOOM_AUTO ); item = new wxMenuItem( viewMenu, ID_ZOOM_PAGE, text, HELP_ZOOM_FIT, wxITEM_NORMAL ); SET_BITMAP( KiBitmap( zoom_fit_in_page_xpm ) ); @@ -361,8 +364,7 @@ void PCB_EDIT_FRAME::ReCreateMenuBar() text = AddHotkeyName( _( "Redraw" ), g_Pcbnew_Editor_Hokeys_Descr, HK_ZOOM_REDRAW ); item = new wxMenuItem( viewMenu, ID_ZOOM_REDRAW, text, - HELP_ZOOM_REDRAW, - wxITEM_NORMAL ); + HELP_ZOOM_REDRAW, wxITEM_NORMAL ); SET_BITMAP( KiBitmap( zoom_redraw_xpm ) ); viewMenu->Append( item ); viewMenu->AppendSeparator(); @@ -387,7 +389,7 @@ void PCB_EDIT_FRAME::ReCreateMenuBar() wxMenu* placeMenu = new wxMenu; // Module - text = AddHotkeyName( _( "Module" ), g_Pcbnew_Editor_Hokeys_Descr, HK_ADD_MODULE, false ); + text = AddHotkeyName( _( "Module" ), g_Pcbnew_Editor_Hokeys_Descr, HK_ADD_MODULE, IS_ACCELERATOR ); item = new wxMenuItem( placeMenu, ID_PCB_MODULE_BUTT, text, _( "Add modules" ), wxITEM_NORMAL ); @@ -395,7 +397,7 @@ void PCB_EDIT_FRAME::ReCreateMenuBar() placeMenu->Append( item ); // Track - text = AddHotkeyName( _( "Track" ), g_Pcbnew_Editor_Hokeys_Descr, HK_ADD_NEW_TRACK, false ); + text = AddHotkeyName( _( "Track" ), g_Pcbnew_Editor_Hokeys_Descr, HK_ADD_NEW_TRACK, IS_ACCELERATOR ); item = new wxMenuItem( placeMenu, ID_TRACK_BUTT, text, _( "Add tracks and vias" ), wxITEM_NORMAL ); diff --git a/pcbnew/tool_modedit.cpp b/pcbnew/tool_modedit.cpp index 90fae97228..51d9c3e4b5 100644 --- a/pcbnew/tool_modedit.cpp +++ b/pcbnew/tool_modedit.cpp @@ -87,16 +87,16 @@ void FOOTPRINT_EDIT_FRAME::ReCreateHToolbar() _( "Print module" ) ); m_HToolBar->AddSeparator(); - msg = AddHotkeyName( _( "Zoom in" ), g_Module_Editor_Hokeys_Descr, HK_ZOOM_IN, false ); + msg = AddHotkeyName( _( "Zoom in" ), g_Module_Editor_Hokeys_Descr, HK_ZOOM_IN, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_IN, wxEmptyString, KiBitmap( zoom_in_xpm ), msg ); - msg = AddHotkeyName( _( "Zoom out" ), g_Module_Editor_Hokeys_Descr, HK_ZOOM_OUT, false ); + msg = AddHotkeyName( _( "Zoom out" ), g_Module_Editor_Hokeys_Descr, HK_ZOOM_OUT, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_OUT, wxEmptyString, KiBitmap( zoom_out_xpm ), msg ); - msg = AddHotkeyName( _( "Redraw view" ), g_Module_Editor_Hokeys_Descr, HK_ZOOM_REDRAW, false ); + msg = AddHotkeyName( _( "Redraw view" ), g_Module_Editor_Hokeys_Descr, HK_ZOOM_REDRAW, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_REDRAW, wxEmptyString, KiBitmap( zoom_redraw_xpm ), msg ); - msg = AddHotkeyName( _( "Zoom auto" ), g_Module_Editor_Hokeys_Descr, HK_ZOOM_AUTO, false ); + msg = AddHotkeyName( _( "Zoom auto" ), g_Module_Editor_Hokeys_Descr, HK_ZOOM_AUTO, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_PAGE, wxEmptyString, KiBitmap( zoom_fit_in_page_xpm ), msg ); m_HToolBar->AddSeparator(); diff --git a/pcbnew/tool_pcb.cpp b/pcbnew/tool_pcb.cpp index a4e3dc350d..095c3d47e8 100644 --- a/pcbnew/tool_pcb.cpp +++ b/pcbnew/tool_pcb.cpp @@ -217,9 +217,9 @@ void PCB_EDIT_FRAME::ReCreateHToolbar() #endif m_HToolBar->AddSeparator(); - msg = AddHotkeyName( HELP_UNDO, g_Board_Editor_Hokeys_Descr, HK_UNDO, false ); + msg = AddHotkeyName( HELP_UNDO, g_Board_Editor_Hokeys_Descr, HK_UNDO, IS_COMMENT ); m_HToolBar->AddTool( wxID_UNDO, wxEmptyString, KiBitmap( undo_xpm ), HELP_UNDO ); - msg = AddHotkeyName( HELP_REDO, g_Board_Editor_Hokeys_Descr, HK_REDO, false ); + msg = AddHotkeyName( HELP_REDO, g_Board_Editor_Hokeys_Descr, HK_REDO, IS_COMMENT ); m_HToolBar->AddTool( wxID_REDO, wxEmptyString, KiBitmap( redo_xpm ), HELP_REDO ); m_HToolBar->AddSeparator(); @@ -229,20 +229,20 @@ void PCB_EDIT_FRAME::ReCreateHToolbar() _( "Plot (HPGL, PostScript, or GERBER format)" ) ); m_HToolBar->AddSeparator(); - msg = AddHotkeyName( HELP_ZOOM_IN, g_Board_Editor_Hokeys_Descr, HK_ZOOM_IN, false ); + msg = AddHotkeyName( HELP_ZOOM_IN, g_Board_Editor_Hokeys_Descr, HK_ZOOM_IN, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_IN, wxEmptyString, KiBitmap( zoom_in_xpm ), msg ); - msg = AddHotkeyName( HELP_ZOOM_OUT, g_Board_Editor_Hokeys_Descr, HK_ZOOM_OUT, false ); + msg = AddHotkeyName( HELP_ZOOM_OUT, g_Board_Editor_Hokeys_Descr, HK_ZOOM_OUT, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_OUT, wxEmptyString, KiBitmap( zoom_out_xpm ), msg ); - msg = AddHotkeyName( HELP_ZOOM_REDRAW, g_Board_Editor_Hokeys_Descr, HK_ZOOM_REDRAW, false ); + msg = AddHotkeyName( HELP_ZOOM_REDRAW, g_Board_Editor_Hokeys_Descr, HK_ZOOM_REDRAW, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_REDRAW, wxEmptyString, KiBitmap( zoom_redraw_xpm ), msg ); - msg = AddHotkeyName( HELP_ZOOM_FIT, g_Board_Editor_Hokeys_Descr, HK_ZOOM_AUTO, false ); + msg = AddHotkeyName( HELP_ZOOM_FIT, g_Board_Editor_Hokeys_Descr, HK_ZOOM_AUTO, IS_COMMENT ); m_HToolBar->AddTool( ID_ZOOM_PAGE, wxEmptyString, KiBitmap( zoom_fit_in_page_xpm ), msg ); m_HToolBar->AddSeparator(); - msg = AddHotkeyName( HELP_FIND, g_Board_Editor_Hokeys_Descr, HK_FIND_ITEM, false ); + msg = AddHotkeyName( HELP_FIND, g_Board_Editor_Hokeys_Descr, HK_FIND_ITEM, IS_COMMENT ); m_HToolBar->AddTool( ID_FIND_ITEMS, wxEmptyString, KiBitmap( find_xpm ), msg ); m_HToolBar->AddSeparator(); diff --git a/pcbnew/zones_convert_to_polygons_aux_functions.cpp b/pcbnew/zones_convert_to_polygons_aux_functions.cpp index f896d042ff..e23707786f 100644 --- a/pcbnew/zones_convert_to_polygons_aux_functions.cpp +++ b/pcbnew/zones_convert_to_polygons_aux_functions.cpp @@ -1,162 +1,162 @@ -/** - * @file zones_convert_to_polygons_aux_functions.cpp - */ - -#include "fctsys.h" -#include "polygons_defs.h" -#include "PolyLine.h" -#include "wxPcbStruct.h" -#include "trigo.h" - -#include "class_board.h" -#include "class_module.h" -#include "class_zone.h" - -#include "pcbnew.h" -#include "zones.h" - - -/** - * Function BuildUnconnectedThermalStubsPolygonList - * Creates a set of polygons corresponding to stubs created by thermal shapes on pads - * which are not connected to a zone (dangling bridges) - * @param aCornerBuffer = a std::vector where to store polygons - * @param aPcb = the board. - * @param aZone = a pointer to the ZONE_CONTAINER to examine. - * @param aArcCorrection = a pointer to the ZONE_CONTAINER to examine. - * @param aRoundPadThermalRotation = the rotation in 1.0 degree for thermal stubs in round pads - */ - -void BuildUnconnectedThermalStubsPolygonList( std::vector& aCornerBuffer, - BOARD* aPcb, - ZONE_CONTAINER* aZone, - double aArcCorrection, - int aRoundPadThermalRotation ) -{ - std::vector corners_buffer; // a local polygon buffer to store one stub - corners_buffer.reserve( 4 ); - wxPoint ptTest[4]; - - int zone_clearance = aZone->m_ZoneClearance; - - EDA_RECT item_boundingbox; - EDA_RECT zone_boundingbox = aZone->GetBoundingBox(); - int biggest_clearance = aPcb->GetBiggestClearanceValue(); - biggest_clearance = MAX( biggest_clearance, zone_clearance ); - zone_boundingbox.Inflate( biggest_clearance ); - - // half size of the pen used to draw/plot zones outlines - int pen_radius = aZone->m_ZoneMinThickness / 2; - - // Calculate thermal bridge half width - int thermbridgeWidth = aZone->m_ThermalReliefCopperBridgeValue / 2; - for( MODULE* module = aPcb->m_Modules; module; module = module->Next() ) - { - for( D_PAD* pad = module->m_Pads; pad != NULL; pad = pad->Next() ) - { - // check - if( !pad->IsOnLayer( aZone->GetLayer() ) ) - continue; - if( pad->GetNet() != aZone->GetNet() ) - continue; - - item_boundingbox = pad->GetBoundingBox(); - item_boundingbox.Inflate( aZone->m_ThermalReliefGapValue ); - if( !( item_boundingbox.Intersects( zone_boundingbox ) ) ) - continue; - - // Thermal bridges are like a segment from a starting point inside the pad - // to an ending point outside the pad - wxPoint startpoint, endpoint; - endpoint.x = ( pad->m_Size.x / 2 ) + aZone->m_ThermalReliefGapValue; - endpoint.y = ( pad->m_Size.y / 2 ) + aZone->m_ThermalReliefGapValue; - - int copperThickness = aZone->m_ThermalReliefCopperBridgeValue - aZone->m_ZoneMinThickness; - if( copperThickness < 0 ) - copperThickness = 0; - - startpoint.x = min( pad->m_Size.x, copperThickness ); - startpoint.y = min( pad->m_Size.y, copperThickness ); - startpoint.x /= 2; - startpoint.y /= 2; - - // This is CIRCLE pad tweak (for circle pads the thermal stubs are at 45 deg) - int fAngle = pad->m_Orient; - if( pad->m_PadShape == PAD_CIRCLE ) - { - endpoint.x = (int) ( endpoint.x * aArcCorrection ); - endpoint.y = endpoint.x; - fAngle = aRoundPadThermalRotation; - } - - // contour line width has to be taken into calculation to avoid "thermal stub bleed" - endpoint.x += pen_radius; - endpoint.y += pen_radius; - // compute north, south, west and east points for zone connection. - ptTest[0] = wxPoint( 0, endpoint.y ); // lower point - ptTest[1] = wxPoint( 0, -endpoint.y ); // upper point - ptTest[2] = wxPoint( endpoint.x, 0 ); // right point - ptTest[3] = wxPoint( -endpoint.x, 0 ); // left point - - // Test all sides - for( int i = 0; i < 4; i++ ) - { - // rotate point - RotatePoint( &ptTest[i], fAngle ); - - // translate point - ptTest[i] += pad->ReturnShapePos(); - if( aZone->HitTestFilledArea( ptTest[i] ) ) - continue; - - corners_buffer.clear(); - - // polygons are rectangles with width of copper bridge value - switch( i ) - { - case 0: // lower stub - corners_buffer.push_back( wxPoint( -thermbridgeWidth, endpoint.y ) ); - corners_buffer.push_back( wxPoint( +thermbridgeWidth, endpoint.y ) ); - corners_buffer.push_back( wxPoint( +thermbridgeWidth, startpoint.y ) ); - corners_buffer.push_back( wxPoint( -thermbridgeWidth, startpoint.y ) ); - break; - - case 1: // upper stub - corners_buffer.push_back( wxPoint( -thermbridgeWidth, -endpoint.y ) ); - corners_buffer.push_back( wxPoint( +thermbridgeWidth, -endpoint.y ) ); - corners_buffer.push_back( wxPoint( +thermbridgeWidth, -startpoint.y ) ); - corners_buffer.push_back( wxPoint( -thermbridgeWidth, -startpoint.y ) ); - break; - - case 2: // right stub - corners_buffer.push_back( wxPoint( endpoint.x, -thermbridgeWidth ) ); - corners_buffer.push_back( wxPoint( endpoint.x, thermbridgeWidth ) ); - corners_buffer.push_back( wxPoint( +startpoint.x, thermbridgeWidth ) ); - corners_buffer.push_back( wxPoint( +startpoint.x, -thermbridgeWidth ) ); - break; - - case 3: // left stub - corners_buffer.push_back( wxPoint( -endpoint.x, -thermbridgeWidth ) ); - corners_buffer.push_back( wxPoint( -endpoint.x, thermbridgeWidth ) ); - corners_buffer.push_back( wxPoint( -startpoint.x, thermbridgeWidth ) ); - corners_buffer.push_back( wxPoint( -startpoint.x, -thermbridgeWidth ) ); - break; - } - - - // add computed polygon to list - for( unsigned ic = 0; ic < corners_buffer.size(); ic++ ) - { - wxPoint cpos = corners_buffer[ic]; - RotatePoint( &cpos, fAngle ); // Rotate according to module orientation - cpos += pad->ReturnShapePos(); // Shift origin to position - CPolyPt corner; - corner.x = cpos.x; - corner.y = cpos.y; - corner.end_contour = ( ic < (corners_buffer.size() - 1) ) ? 0 : 1; - aCornerBuffer.push_back( corner ); - } - } - } - } -} +/** + * @file zones_convert_to_polygons_aux_functions.cpp + */ + +#include "fctsys.h" +#include "polygons_defs.h" +#include "PolyLine.h" +#include "wxPcbStruct.h" +#include "trigo.h" + +#include "class_board.h" +#include "class_module.h" +#include "class_zone.h" + +#include "pcbnew.h" +#include "zones.h" + + +/** + * Function BuildUnconnectedThermalStubsPolygonList + * Creates a set of polygons corresponding to stubs created by thermal shapes on pads + * which are not connected to a zone (dangling bridges) + * @param aCornerBuffer = a std::vector where to store polygons + * @param aPcb = the board. + * @param aZone = a pointer to the ZONE_CONTAINER to examine. + * @param aArcCorrection = a pointer to the ZONE_CONTAINER to examine. + * @param aRoundPadThermalRotation = the rotation in 1.0 degree for thermal stubs in round pads + */ + +void BuildUnconnectedThermalStubsPolygonList( std::vector& aCornerBuffer, + BOARD* aPcb, + ZONE_CONTAINER* aZone, + double aArcCorrection, + int aRoundPadThermalRotation ) +{ + std::vector corners_buffer; // a local polygon buffer to store one stub + corners_buffer.reserve( 4 ); + wxPoint ptTest[4]; + + int zone_clearance = aZone->m_ZoneClearance; + + EDA_RECT item_boundingbox; + EDA_RECT zone_boundingbox = aZone->GetBoundingBox(); + int biggest_clearance = aPcb->GetBiggestClearanceValue(); + biggest_clearance = MAX( biggest_clearance, zone_clearance ); + zone_boundingbox.Inflate( biggest_clearance ); + + // half size of the pen used to draw/plot zones outlines + int pen_radius = aZone->m_ZoneMinThickness / 2; + + // Calculate thermal bridge half width + int thermbridgeWidth = aZone->m_ThermalReliefCopperBridgeValue / 2; + for( MODULE* module = aPcb->m_Modules; module; module = module->Next() ) + { + for( D_PAD* pad = module->m_Pads; pad != NULL; pad = pad->Next() ) + { + // check + if( !pad->IsOnLayer( aZone->GetLayer() ) ) + continue; + if( pad->GetNet() != aZone->GetNet() ) + continue; + + item_boundingbox = pad->GetBoundingBox(); + item_boundingbox.Inflate( aZone->m_ThermalReliefGapValue ); + if( !( item_boundingbox.Intersects( zone_boundingbox ) ) ) + continue; + + // Thermal bridges are like a segment from a starting point inside the pad + // to an ending point outside the pad + wxPoint startpoint, endpoint; + endpoint.x = ( pad->m_Size.x / 2 ) + aZone->m_ThermalReliefGapValue; + endpoint.y = ( pad->m_Size.y / 2 ) + aZone->m_ThermalReliefGapValue; + + int copperThickness = aZone->m_ThermalReliefCopperBridgeValue - aZone->m_ZoneMinThickness; + if( copperThickness < 0 ) + copperThickness = 0; + + startpoint.x = min( pad->m_Size.x, copperThickness ); + startpoint.y = min( pad->m_Size.y, copperThickness ); + startpoint.x /= 2; + startpoint.y /= 2; + + // This is CIRCLE pad tweak (for circle pads the thermal stubs are at 45 deg) + int fAngle = pad->m_Orient; + if( pad->m_PadShape == PAD_CIRCLE ) + { + endpoint.x = (int) ( endpoint.x * aArcCorrection ); + endpoint.y = endpoint.x; + fAngle = aRoundPadThermalRotation; + } + + // contour line width has to be taken into calculation to avoid "thermal stub bleed" + endpoint.x += pen_radius; + endpoint.y += pen_radius; + // compute north, south, west and east points for zone connection. + ptTest[0] = wxPoint( 0, endpoint.y ); // lower point + ptTest[1] = wxPoint( 0, -endpoint.y ); // upper point + ptTest[2] = wxPoint( endpoint.x, 0 ); // right point + ptTest[3] = wxPoint( -endpoint.x, 0 ); // left point + + // Test all sides + for( int i = 0; i < 4; i++ ) + { + // rotate point + RotatePoint( &ptTest[i], fAngle ); + + // translate point + ptTest[i] += pad->ReturnShapePos(); + if( aZone->HitTestFilledArea( ptTest[i] ) ) + continue; + + corners_buffer.clear(); + + // polygons are rectangles with width of copper bridge value + switch( i ) + { + case 0: // lower stub + corners_buffer.push_back( wxPoint( -thermbridgeWidth, endpoint.y ) ); + corners_buffer.push_back( wxPoint( +thermbridgeWidth, endpoint.y ) ); + corners_buffer.push_back( wxPoint( +thermbridgeWidth, startpoint.y ) ); + corners_buffer.push_back( wxPoint( -thermbridgeWidth, startpoint.y ) ); + break; + + case 1: // upper stub + corners_buffer.push_back( wxPoint( -thermbridgeWidth, -endpoint.y ) ); + corners_buffer.push_back( wxPoint( +thermbridgeWidth, -endpoint.y ) ); + corners_buffer.push_back( wxPoint( +thermbridgeWidth, -startpoint.y ) ); + corners_buffer.push_back( wxPoint( -thermbridgeWidth, -startpoint.y ) ); + break; + + case 2: // right stub + corners_buffer.push_back( wxPoint( endpoint.x, -thermbridgeWidth ) ); + corners_buffer.push_back( wxPoint( endpoint.x, thermbridgeWidth ) ); + corners_buffer.push_back( wxPoint( +startpoint.x, thermbridgeWidth ) ); + corners_buffer.push_back( wxPoint( +startpoint.x, -thermbridgeWidth ) ); + break; + + case 3: // left stub + corners_buffer.push_back( wxPoint( -endpoint.x, -thermbridgeWidth ) ); + corners_buffer.push_back( wxPoint( -endpoint.x, thermbridgeWidth ) ); + corners_buffer.push_back( wxPoint( -startpoint.x, thermbridgeWidth ) ); + corners_buffer.push_back( wxPoint( -startpoint.x, -thermbridgeWidth ) ); + break; + } + + + // add computed polygon to list + for( unsigned ic = 0; ic < corners_buffer.size(); ic++ ) + { + wxPoint cpos = corners_buffer[ic]; + RotatePoint( &cpos, fAngle ); // Rotate according to module orientation + cpos += pad->ReturnShapePos(); // Shift origin to position + CPolyPt corner; + corner.x = cpos.x; + corner.y = cpos.y; + corner.end_contour = ( ic < (corners_buffer.size() - 1) ) ? 0 : 1; + aCornerBuffer.push_back( corner ); + } + } + } + } +}