From 46fcb07bcb92a281c60b6b0e0523afc45a6342ea Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Sat, 23 Apr 2011 21:01:41 +0200 Subject: [PATCH] Gerbview: export_to_pcbnew enhancement and fixes. --- gerbview/CMakeLists.txt | 1 + gerbview/class_gerber_draw_item.cpp | 2 +- gerbview/export_to_pcbnew.cpp | 389 ++++++++++++++++++---------- gerbview/select_layers_to_pcb.cpp | 220 ++++++---------- 4 files changed, 325 insertions(+), 287 deletions(-) diff --git a/gerbview/CMakeLists.txt b/gerbview/CMakeLists.txt index f198295a5a..10c235b360 100644 --- a/gerbview/CMakeLists.txt +++ b/gerbview/CMakeLists.txt @@ -17,6 +17,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} set(DIALOGS_SRCS dialogs/gerbview_dialog_display_options_frame_base.cpp dialogs/gerbview_dialog_display_options_frame.cpp + dialogs/dialog_layers_select_to_pcb_base.cpp dialogs/dialog_print_using_printer.cpp dialogs/dialog_print_using_printer_base.cpp ) diff --git a/gerbview/class_gerber_draw_item.cpp b/gerbview/class_gerber_draw_item.cpp index ec0f679ea8..eb2d182aa9 100644 --- a/gerbview/class_gerber_draw_item.cpp +++ b/gerbview/class_gerber_draw_item.cpp @@ -419,7 +419,7 @@ void GERBER_DRAW_ITEM::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode, break; case GBR_ARC: - // Currently, arcs plotted witha rectangular aperture are not supported. + // Currently, arcs plotted with a rectangular aperture are not supported. // a round pen only is expected. #if 0 // for arc debug only GRLine( &aPanel->m_ClipBox, aDC, GetABPosition( m_Start ), diff --git a/gerbview/export_to_pcbnew.cpp b/gerbview/export_to_pcbnew.cpp index 8d0bed9f70..18948b342c 100644 --- a/gerbview/export_to_pcbnew.cpp +++ b/gerbview/export_to_pcbnew.cpp @@ -10,13 +10,50 @@ #include "confirm.h" #include "kicad_string.h" #include "gestfich.h" +#include "trigo.h" #include "gerbview.h" #include "class_board_design_settings.h" #include "class_gerber_draw_item.h" -static int SavePcbFormatAscii( GERBVIEW_FRAME* frame, - FILE* File, int* LayerLookUpTable ); + +/* A helper class to export a Gerber set of files to Pcbnew +*/ +class GBR_TO_PCB_EXPORTER +{ + GERBVIEW_FRAME* m_gerbview_frame; // the maint gerber frame + FILE * m_file; // .brd file to write to + BOARD* m_pcb; // the board to populate and export + +public: + GBR_TO_PCB_EXPORTER(GERBVIEW_FRAME * aFrame, FILE * aFile ); + ~GBR_TO_PCB_EXPORTER(); + bool ExportPcb( int* LayerLookUpTable ); + +private: + bool WriteSetup( ); // Write the SETUP section data file + bool WriteGeneralDescrPcb( ); + void export_non_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ); + void export_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ); + void export_flashed_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ); + void export_segline_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ); + void export_segarc_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ); + void cleanBoard(); +}; + +GBR_TO_PCB_EXPORTER::GBR_TO_PCB_EXPORTER( GERBVIEW_FRAME * aFrame, FILE * aFile ) +{ + m_gerbview_frame = aFrame; + m_file = aFile; + m_pcb = NULL; +} + +GBR_TO_PCB_EXPORTER::~GBR_TO_PCB_EXPORTER() +{ + // the destructor should destroy all owned sub-objects + delete m_pcb; +} + /* Export data in pcbnew format @@ -45,8 +82,6 @@ void GERBVIEW_FRAME::ExportDataInPcbnewFormat( wxCommandEvent& event ) wxString PcbExt( wxT( ".brd" ) ); - FILE* dest; - msg = wxT( "*" ) + PcbExt; FullFileName = EDA_FileSelector( _( "Board file name:" ), wxEmptyString, @@ -68,143 +103,24 @@ void GERBVIEW_FRAME::ExportDataInPcbnewFormat( wxCommandEvent& event ) if( !IsOK( this, _( "Ok to change the existing file ?" ) ) ) return; } - dest = wxFopen( FullFileName, wxT( "wt" ) ); - if( dest == 0 ) + FILE * file = wxFopen( FullFileName, wxT( "wt" ) ); + if( file == NULL ) { msg = _( "Unable to create " ) + FullFileName; DisplayError( this, msg ); return; } GetScreen()->SetFileName( FullFileName ); - SavePcbFormatAscii( this, dest, LayerLookUpTable ); - fclose( dest ); + GBR_TO_PCB_EXPORTER gbr_exporter( this, file ); + gbr_exporter.ExportPcb( LayerLookUpTable ); + fclose( file ); } } - -static int WriteSetup( FILE* File, BOARD* Pcb ) +void GBR_TO_PCB_EXPORTER::cleanBoard() { - char text[1024]; - - fprintf( File, "$SETUP\n" ); - sprintf( text, "InternalUnit %f INCH\n", 1.0 / PCB_INTERNAL_UNIT ); - fprintf( File, "%s", text ); - - fprintf( File, "Layers %d\n", Pcb->GetCopperLayerCount() ); - - fprintf( File, "$EndSETUP\n\n" ); - return 1; -} - - -static bool WriteGeneralDescrPcb( BOARD* Pcb, FILE* File ) -{ - int NbLayers; - - /* Print the copper layer count */ - NbLayers = Pcb->GetCopperLayerCount(); - fprintf( File, "$GENERAL\n" ); - fprintf( File, "LayerCount %d\n", NbLayers ); - - /* Compute and print the board bounding box */ - Pcb->ComputeBoundingBox(); - fprintf( File, "Di %d %d %d %d\n", - Pcb->m_BoundaryBox.GetX(), Pcb->m_BoundaryBox.GetY(), - Pcb->m_BoundaryBox.GetRight(), - Pcb->m_BoundaryBox.GetBottom() ); - - fprintf( File, "$EndGENERAL\n\n" ); - return TRUE; -} - - -/* Routine to save the board - * @param frame = pointer to the main frame - * @param File = FILE * pointer to an already opened file - * @param LayerLookUpTable = look up table: pcbnew layer for each gerber layer - * @return 1 if OK, 0 if fail - */ -static int SavePcbFormatAscii( GERBVIEW_FRAME* frame, FILE* aFile, - int* LayerLookUpTable ) -{ - char line[256]; - BOARD* gerberPcb = frame->GetBoard(); - BOARD* pcb; - - wxBeginBusyCursor(); - - // create an image of gerber data - pcb = new BOARD( NULL, frame ); - BOARD_ITEM* item = gerberPcb->m_Drawings; - for( ; item; item = item->Next() ) - { - GERBER_DRAW_ITEM* gerb_item = (GERBER_DRAW_ITEM*) item; - int layer = gerb_item->GetLayer(); - int pcb_layer_number = LayerLookUpTable[layer]; - if( pcb_layer_number < 0 || pcb_layer_number > LAST_NO_COPPER_LAYER ) - continue; - - if( pcb_layer_number > LAST_COPPER_LAYER ) - { - DRAWSEGMENT* drawitem = new DRAWSEGMENT( pcb, TYPE_DRAWSEGMENT ); - - drawitem->SetLayer( pcb_layer_number ); - drawitem->m_Start = gerb_item->m_Start; - drawitem->m_End = gerb_item->m_End; - drawitem->m_Width = gerb_item->m_Size.x; - - if( gerb_item->m_Shape == GBR_ARC ) - { - double cx = gerb_item->m_ArcCentre.x; - double cy = gerb_item->m_ArcCentre.y; - double a = atan2( gerb_item->m_Start.y - cy, - gerb_item->m_Start.x - cx ); - double b = atan2( gerb_item->m_End.y - cy, gerb_item->m_End.x - cx ); - - drawitem->m_Shape = S_ARC; - drawitem->m_Angle = (int) fmod( - (a - b) / M_PI * 1800.0 + 3600.0, 3600.0 ); - drawitem->m_Start.x = (int) cx; - drawitem->m_Start.y = (int) cy; - } - - pcb->Add( drawitem ); - } - else - { - TRACK* newtrack; - - // replace spots with vias when possible - if( gerb_item->m_Shape == GBR_SPOT_CIRCLE - || gerb_item->m_Shape == GBR_SPOT_RECT - || gerb_item->m_Shape == GBR_SPOT_OVAL ) - { - newtrack = new SEGVIA( pcb ); - - // A spot is found, and can be a via: change it to via, and - // delete other - // spots at same location - newtrack->m_Shape = VIA_THROUGH; - newtrack->SetLayer( 0x0F ); // Layers are 0 to 15 (Cu/Cmp) - newtrack->SetDrillDefault(); - newtrack->m_Start = newtrack->m_End = gerb_item->m_Start; - newtrack->m_Width = (gerb_item->m_Size.x + gerb_item->m_Size.y) / 2; - } - else // a true TRACK - { - newtrack = new TRACK( pcb ); - newtrack->SetLayer( pcb_layer_number ); - newtrack->m_Start = gerb_item->m_Start; - newtrack->m_End = gerb_item->m_End; - newtrack->m_Width = gerb_item->m_Size.x; - } - - pcb->Add( newtrack ); - } - } - // delete redundant vias - for( TRACK * track = pcb->m_Track; track; track = track->Next() ) + for( TRACK * track = m_pcb->m_Track; track; track = track->Next() ) { if( track->m_Shape != VIA_THROUGH ) continue; @@ -226,24 +142,211 @@ static int SavePcbFormatAscii( GERBVIEW_FRAME* frame, FILE* aFile, delete alt_track; } } +} - // Switch the locale to standard C (needed to print floating point numbers - // like 1.3) +bool GBR_TO_PCB_EXPORTER::WriteSetup( ) +{ + fprintf( m_file, "$SETUP\n" ); + fprintf( m_file, "InternalUnit %f INCH\n", 1.0 / PCB_INTERNAL_UNIT ); + + fprintf( m_file, "Layers %d\n", m_pcb->GetCopperLayerCount() ); + + fprintf( m_file, "$EndSETUP\n\n" ); + return true; +} + + +bool GBR_TO_PCB_EXPORTER::WriteGeneralDescrPcb( ) +{ + int nbLayers; + + /* Print the copper layer count */ + nbLayers = m_pcb->GetCopperLayerCount(); + if( nbLayers <= 1 ) // Minimal layers count in Pcbnew is 2 + { + nbLayers = 2; + m_pcb->SetCopperLayerCount(2); + } + fprintf( m_file, "$GENERAL\n" ); + fprintf( m_file, "encoding utf-8\n"); + fprintf( m_file, "LayerCount %d\n", nbLayers ); + + /* Compute and print the board bounding box */ + m_pcb->ComputeBoundingBox(); + fprintf( m_file, "Di %d %d %d %d\n", + m_pcb->m_BoundaryBox.GetX(), m_pcb->m_BoundaryBox.GetY(), + m_pcb->m_BoundaryBox.GetRight(), + m_pcb->m_BoundaryBox.GetBottom() ); + + fprintf( m_file, "$EndGENERAL\n\n" ); + return true; +} + + +/* Routine to save the board + * @param frame = pointer to the main frame + * @param File = FILE * pointer to an already opened file + * @param LayerLookUpTable = look up table: pcbnew layer for each gerber layer + * @return 1 if OK, 0 if fail + */ +bool GBR_TO_PCB_EXPORTER::ExportPcb( int* LayerLookUpTable ) +{ + char line[256]; + BOARD* gerberPcb = m_gerbview_frame->GetBoard(); + + // create an image of gerber data + m_pcb = new BOARD( NULL, m_gerbview_frame ); + BOARD_ITEM* item = gerberPcb->m_Drawings; + for( ; item; item = item->Next() ) + { + GERBER_DRAW_ITEM* gerb_item = (GERBER_DRAW_ITEM*) item; + int layer = gerb_item->GetLayer(); + int pcb_layer_number = LayerLookUpTable[layer]; + if( pcb_layer_number < 0 || pcb_layer_number > LAST_NO_COPPER_LAYER ) + continue; + + if( pcb_layer_number > LAST_COPPER_LAYER ) + export_non_copper_item( gerb_item, pcb_layer_number ); + + else + export_copper_item( gerb_item, pcb_layer_number ); + } + + cleanBoard(); + + // Switch the locale to standard C (needed to print floating point numbers) SetLocaleTo_C_standard(); - // write the PCB heading - fprintf( aFile, "PCBNEW-BOARD Version %d date %s\n\n", g_CurrentVersionPCB, + // write PCB header + fprintf( m_file, "PCBNEW-BOARD Version %d date %s\n\n", g_CurrentVersionPCB, DateAndTime( line ) ); - WriteGeneralDescrPcb( pcb, aFile ); - WriteSetup( aFile, pcb ); + WriteGeneralDescrPcb( ); + WriteSetup( ); - // write the useful part of the pcb - pcb->Save( aFile ); - - // the destructor should destroy all owned sub-objects - delete pcb; + // write items on file + m_pcb->Save( m_file ); SetLocaleTo_Default(); // revert to the current locale - wxEndBusyCursor(); - return 1; + return true; +} + +void GBR_TO_PCB_EXPORTER::export_non_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ) +{ + DRAWSEGMENT* drawitem = new DRAWSEGMENT( m_pcb, TYPE_DRAWSEGMENT ); + + drawitem->SetLayer( aLayer ); + drawitem->m_Start = aGbrItem->m_Start; + drawitem->m_End = aGbrItem->m_End; + drawitem->m_Width = aGbrItem->m_Size.x; + + if( aGbrItem->m_Shape == GBR_ARC ) + { + double a = atan2( (double)( aGbrItem->m_Start.y - aGbrItem->m_ArcCentre.y), + (double)( aGbrItem->m_Start.x - aGbrItem->m_ArcCentre.x ) ); + double b = atan2( (double)( aGbrItem->m_End.y - aGbrItem->m_ArcCentre.y ), + (double)( aGbrItem->m_End.x - aGbrItem->m_ArcCentre.x ) ); + + drawitem->m_Shape = S_ARC; + drawitem->m_Angle = wxRound( (a - b) / M_PI * 1800.0 ); + drawitem->m_Start = aGbrItem->m_ArcCentre; + if( drawitem->m_Angle < 0 ) + { + NEGATE( drawitem->m_Angle ); + drawitem->m_End = aGbrItem->m_Start; + } + } + + m_pcb->Add( drawitem ); +} + +void GBR_TO_PCB_EXPORTER::export_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ) +{ + switch( aGbrItem->m_Shape ) + { + case GBR_SPOT_CIRCLE: + case GBR_SPOT_RECT: + case GBR_SPOT_OVAL: + // replace spots with vias when possible + export_flashed_copper_item( aGbrItem, aLayer ); + break; + + case GBR_ARC: +// export_segarc_copper_item( aGbrItem, aLayer ); + break; + + default: + export_segline_copper_item( aGbrItem, aLayer ); + break; + } +} + +void GBR_TO_PCB_EXPORTER::export_segline_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ) +{ + TRACK * newtrack = new TRACK( m_pcb ); + newtrack->SetLayer( aLayer ); + newtrack->m_Start = aGbrItem->m_Start; + newtrack->m_End = aGbrItem->m_End; + newtrack->m_Width = aGbrItem->m_Size.x; + m_pcb->Add( newtrack ); +} + +void GBR_TO_PCB_EXPORTER::export_segarc_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ) +{ + double a = atan2( (double)( aGbrItem->m_Start.y - aGbrItem->m_ArcCentre.y ), + (double)( aGbrItem->m_Start.x - aGbrItem->m_ArcCentre.x ) ); + double b = atan2( (double)( aGbrItem->m_End.y - aGbrItem->m_ArcCentre.y ), + (double)( aGbrItem->m_End.x - aGbrItem->m_ArcCentre.x ) ); + + int arc_angle = wxRound( ( (a - b) / M_PI * 1800.0 ) ); + wxPoint start = aGbrItem->m_Start; + wxPoint end = aGbrItem->m_End; + /* Because Pcbnew does not know arcs in tracks, + * approximate arc by segments (16 segment per 360 deg) + */ + #define DELTA 3600/16 + if( arc_angle < 0 ) + { + NEGATE( arc_angle ); + EXCHG( start, end ); + } + wxPoint curr_start = start; + for( int rot = DELTA; rot < (arc_angle - DELTA); rot += DELTA ) + { + TRACK * newtrack = new TRACK( m_pcb ); + newtrack->SetLayer( aLayer ); + newtrack->m_Start = curr_start; + wxPoint curr_end = start; + RotatePoint( &curr_end, aGbrItem->m_ArcCentre, rot ); + newtrack->m_End = curr_end; + newtrack->m_Width = aGbrItem->m_Size.x; + m_pcb->Add( newtrack ); + curr_start = curr_end; + } + if( end != curr_start ) + { + TRACK * newtrack = new TRACK( m_pcb ); + newtrack->SetLayer( aLayer ); + newtrack->m_Start = curr_start; + newtrack->m_End = end; + newtrack->m_Width = aGbrItem->m_Size.x; + m_pcb->Add( newtrack ); + } +} + + +/* + * creates a via from a flashed gerber item. + * Flashed items are usually pads or vias, so we try to export all of them + * using vias + */ +void GBR_TO_PCB_EXPORTER::export_flashed_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer ) +{ + SEGVIA * newtrack = new SEGVIA( m_pcb ); + + newtrack->m_Shape = VIA_THROUGH; + newtrack->SetLayer( 0x0F ); // Layers are 0 to 15 (Cu/Cmp) + newtrack->SetDrillDefault(); + newtrack->m_Start = newtrack->m_End = aGbrItem->m_Start; + newtrack->m_Width = (aGbrItem->m_Size.x + aGbrItem->m_Size.y) / 2; + m_pcb->Add( newtrack ); } diff --git a/gerbview/select_layers_to_pcb.cpp b/gerbview/select_layers_to_pcb.cpp index ef234349f3..ec8e9819f2 100644 --- a/gerbview/select_layers_to_pcb.cpp +++ b/gerbview/select_layers_to_pcb.cpp @@ -2,16 +2,19 @@ /* Dialog frame to choose gerber layers and pcb layers */ /*******************************************************/ -/* select_layers_to_pcb.cpp */ +/** + * @file select_layers_to_pcb.cpp + */ #include "fctsys.h" #include "common.h" #include "gerbview.h" #include "class_board_design_settings.h" #include "class_GERBER.h" - #include "wx/statline.h" +#include "dialogs/dialog_layers_select_to_pcb_base.h" + #define LAYER_UNSELECTED NB_LAYERS static int ButtonTable[32]; // Indexes buttons to Gerber layers @@ -25,23 +28,18 @@ enum swap_layer_id { }; -class SWAP_LAYERS_DIALOG : public wxDialog +class LAYERS_TABLE_DIALOG : public LAYERS_TABLE_DIALOG_BASE { private: GERBVIEW_FRAME* m_Parent; - wxBoxSizer* OuterBoxSizer; - wxBoxSizer* MainBoxSizer; - wxFlexGridSizer* FlexColumnBoxSizer; wxStaticText* label; wxButton* Button; wxStaticText* text; - wxStaticLine* Line; - wxStdDialogButtonSizer* StdDialogButtonSizer; public: - SWAP_LAYERS_DIALOG( GERBVIEW_FRAME* parent ); - ~SWAP_LAYERS_DIALOG() {}; + LAYERS_TABLE_DIALOG( GERBVIEW_FRAME* parent ); + ~LAYERS_TABLE_DIALOG() {}; private: void OnSelectLayer( wxCommandEvent& event ); @@ -52,12 +50,10 @@ private: }; -BEGIN_EVENT_TABLE( SWAP_LAYERS_DIALOG, wxDialog ) +BEGIN_EVENT_TABLE( LAYERS_TABLE_DIALOG, wxDialog ) EVT_COMMAND_RANGE( ID_BUTTON_0, ID_BUTTON_0 + 31, wxEVT_COMMAND_BUTTON_CLICKED, - SWAP_LAYERS_DIALOG::OnSelectLayer ) - EVT_BUTTON( wxID_OK, SWAP_LAYERS_DIALOG::OnOkClick ) - EVT_BUTTON( wxID_CANCEL, SWAP_LAYERS_DIALOG::OnCancelClick ) + LAYERS_TABLE_DIALOG::OnSelectLayer ) END_EVENT_TABLE() @@ -67,30 +63,24 @@ END_EVENT_TABLE() */ int* GERBVIEW_FRAME::InstallDialogLayerPairChoice( ) { - SWAP_LAYERS_DIALOG* frame = new SWAP_LAYERS_DIALOG( this ); + LAYERS_TABLE_DIALOG* frame = new LAYERS_TABLE_DIALOG( this ); int ii = frame->ShowModal(); frame->Destroy(); - if( ii >= 0 ) + if( ii == wxID_OK ) return LayerLookUpTable; else return NULL; } -SWAP_LAYERS_DIALOG::SWAP_LAYERS_DIALOG( GERBVIEW_FRAME* parent ) : - wxDialog( parent, -1, _( "Layer selection:" ), wxPoint( -1, -1 ), - wxDefaultSize, wxDEFAULT_DIALOG_STYLE | MAYBE_RESIZE_BORDER ) +LAYERS_TABLE_DIALOG::LAYERS_TABLE_DIALOG( GERBVIEW_FRAME* parent ) : + LAYERS_TABLE_DIALOG_BASE( parent ) { - OuterBoxSizer = NULL; - MainBoxSizer = NULL; - FlexColumnBoxSizer = NULL; label = NULL; Button = NULL; text = NULL; - Line = NULL; - StdDialogButtonSizer = NULL; m_Parent = parent; @@ -118,113 +108,90 @@ SWAP_LAYERS_DIALOG::SWAP_LAYERS_DIALOG( GERBVIEW_FRAME* parent ) : // buttons should be some other size in that version. // Compute a reasonable number of copper layers - int pcb_layer_number = 0; + int pcb_copper_layer_count = 0; for( ii = 0; ii < 32; ii++ ) { if( g_GERBER_List[ii] != NULL ) - pcb_layer_number++; + pcb_copper_layer_count++; // Specify the default value for each member of these arrays. ButtonTable[ii] = -1; LayerLookUpTable[ii] = LAYER_UNSELECTED; } - m_Parent->GetBoard()->SetCopperLayerCount(pcb_layer_number); - pcb_layer_number = 0; + // Ensure we have at least 2 copper layers and NB_COPPER_LAYERS copper layers max + if( pcb_copper_layer_count < 2 ) + pcb_copper_layer_count = 2; + if( pcb_copper_layer_count > NB_COPPER_LAYERS ) + pcb_copper_layer_count = NB_COPPER_LAYERS; + m_Parent->GetBoard()->SetCopperLayerCount(pcb_copper_layer_count); + + int pcb_layer_num = 0; for( nb_items = 0, ii = 0; ii < 32; ii++ ) { if( g_GERBER_List[ii] == NULL ) continue; - if( (pcb_layer_number == m_Parent->GetBoard()->GetCopperLayerCount() - 1) + if( (pcb_layer_num == m_Parent->GetBoard()->GetCopperLayerCount() - 1) && (m_Parent->GetBoard()->GetCopperLayerCount() > 1) ) - pcb_layer_number = LAYER_N_FRONT; + pcb_layer_num = LAYER_N_FRONT; ButtonTable[nb_items] = ii; - LayerLookUpTable[ii] = pcb_layer_number; + LayerLookUpTable[ii] = pcb_layer_num; nb_items++; - pcb_layer_number++; + pcb_layer_num++; } - OuterBoxSizer = new wxBoxSizer( wxVERTICAL ); - SetSizer( OuterBoxSizer ); - - MainBoxSizer = new wxBoxSizer( wxHORIZONTAL ); - OuterBoxSizer->Add( MainBoxSizer, 1, wxGROW | wxLEFT | wxRIGHT | wxTOP, 5 ); + if( nb_items <= 16 ) + m_staticlineSep->Hide(); + wxFlexGridSizer* flexColumnBoxSizer = m_flexLeftColumnBoxSizer; for( ii = 0; ii < nb_items; ii++ ) { - // If more than 16 Gerber layers are used, provide a vertical line to - // separate the two FlexGrid sizers - if( (nb_items > 16) && (ii == 16) ) - { - Line = new wxStaticLine( this, -1, wxDefaultPosition, wxDefaultSize, - wxLI_VERTICAL ); - MainBoxSizer->Add( Line, 0, wxGROW | wxLEFT | wxRIGHT, 5 ); - } + // Each Gerber layer has an associated static text string (to + // identify that layer), a button (for invoking a child dialog + // box to change which pcbnew layer that the Gerber layer is + // mapped to), and a second static text string (to depict which + // pcbnew layer that the Gerber layer has been mapped to). Each + // of those items are placed into the left hand column, middle + // column, and right hand column (respectively) of the Flexgrid + // sizer, and the color of the second text string is set to + // fuchsia or blue (to respectively indicate whether the Gerber + // layer has been mapped to a pcbnew layer or is not being + // exported at all). (Experimentation has shown that if a text + // control is used to depict which pcbnew layer that each Gerber + // layer is mapped to (instead of a static text string), then + // those controls do not behave in a fully satisfactory manner + // in the Linux version. Even when the read-only attribute is + // specified for all of those controls, they can still be selected + // when the arrow keys or Tab key is used to step through all of + // the controls within the dialog box, and directives to set the + // foreground color of the text of each such control to blue (to + // indicate that the text is of a read-only nature) are disregarded. + // Specify a FlexGrid sizer with an appropriate number of rows + // and three columns. If nb_items < 16, then the number of rows + // is nb_items; otherwise, the number of rows is 16 (with two + // separate columns of controls being used if nb_items > 16). - // Provide a separate FlexGrid sizer for every sixteen sets of controls - if( ii % 16 == 0 ) - { - // Each Gerber layer has an associated static text string (to - // identify that layer), a button (for invoking a child dialog - // box to change which pcbnew layer that the Gerber layer is - // mapped to), and a second static text string (to depict which - // pcbnew layer that the Gerber layer has been mapped to). Each - // of those items are placed into the left hand column, middle - // column, and right hand column (respectively) of the Flexgrid - // sizer, and the color of the second text string is set to - // fuchsia or blue (to respectively indicate whether the Gerber - // layer has been mapped to a pcbnew layer or is not being - // exported at all). (Experimentation has shown that if a text - // control is used to depict which pcbnew layer that each Gerber - // layer is mapped to (instead of a static text string), then - // those controls do not behave in a fully satisfactory manner - // in the Linux version. Even when the read-only attribute is - // specified for all of those controls, they can still be selected - // when the arrow keys or Tab key is used to step through all of - // the controls within the dialog box, and directives to set the - // foreground color of the text of each such control to blue (to - // indicate that the text is of a read-only nature) are disregarded. - // Specify a FlexGrid sizer with an appropriate number of rows - // and three columns. If nb_items < 16, then the number of rows - // is nb_items; otherwise, the number of rows is 16 (with two - // separate columns of controls being used if nb_items > 16). - - if( nb_items < 16 ) - FlexColumnBoxSizer = new wxFlexGridSizer( nb_items, 4, 0, 0 ); - else - FlexColumnBoxSizer = new wxFlexGridSizer( 16, 4, 0, 0 ); - - // Specify that all of the rows can be expanded. - for( int jj = 0; jj < MIN( nb_items, 16 ); jj++ ) - { - FlexColumnBoxSizer->AddGrowableRow( jj ); - } - - // Specify that (just) the right-hand column can be expanded. - FlexColumnBoxSizer->AddGrowableCol( 2 ); - - MainBoxSizer->Add( FlexColumnBoxSizer, 1, wxGROW | wxTOP, 5 ); - } + if( ii == 16 ) + flexColumnBoxSizer = m_flexRightColumnBoxSizer; // Provide a text string to identify the Gerber layer - msg = _( "Layer " ); - msg << ButtonTable[ii] + 1; + msg.Printf( _( "Layer %d" ), ButtonTable[ii] + 1 ); label = new wxStaticText( this, wxID_STATIC, msg, wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT ); - FlexColumnBoxSizer->Add( label, 0, + flexColumnBoxSizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | - wxALL, 5 ); + wxRIGHT|wxLEFT, 5 ); /* Add file name and extension without path. */ wxFileName fn( g_GERBER_List[ii]->m_FileName ); label = new wxStaticText( this, wxID_STATIC, fn.GetFullName(), wxDefaultPosition, wxDefaultSize ); - FlexColumnBoxSizer->Add( label, 0, + flexColumnBoxSizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | - wxALL, 5 ); + wxRIGHT|wxLEFT, 5 ); // Provide a button for this layer (which will invoke a child dialog box) item_ID = ID_BUTTON_0 + ii; @@ -232,9 +199,9 @@ SWAP_LAYERS_DIALOG::SWAP_LAYERS_DIALOG( GERBVIEW_FRAME* parent ) : Button = new wxButton( this, item_ID, wxT( "..." ), wxDefaultPosition, wxSize( w, h ), 0 ); - FlexColumnBoxSizer->Add( Button, 0, + flexColumnBoxSizer->Add( Button, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | - wxALL, 5 ); + wxRIGHT|wxLEFT, 5 ); // Provide another text string to specify which pcbnew layer that this // Gerber layer is initially mapped to, and set the initial text to @@ -273,57 +240,20 @@ SWAP_LAYERS_DIALOG::SWAP_LAYERS_DIALOG( GERBVIEW_FRAME* parent ) : wxDefaultSize, 0 ); } text->SetMinSize( goodSize ); - FlexColumnBoxSizer->Add( text, 1, - wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, + flexColumnBoxSizer->Add( text, 1, + wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxRIGHT| wxLEFT, 5 ); layer_list[ii] = text; } - // If required, provide spacers to occupy otherwise blank cells within the - // second FlexGrid sizer. (As it incorporates three columns, three spacers - // are thus required for each otherwise unused row.) - if( 16 < nb_items && nb_items < 32 ) - { - for( ii = 4 * nb_items; ii < 96; ii++ ) - { - FlexColumnBoxSizer->Add( 5, h, 0, - wxALIGN_CENTER_HORIZONTAL | - wxALIGN_CENTER_VERTICAL | wxLEFT | - wxRIGHT | wxBOTTOM, 5 ); - } - } - - // Provide a line to separate the controls which have been provided so far - // from the OK and Cancel buttons (which will be provided after this line) - Line = new wxStaticLine( this, -1, wxDefaultPosition, wxDefaultSize, - wxLI_HORIZONTAL ); - OuterBoxSizer->Add( Line, 0, wxGROW | wxLEFT | wxRIGHT | wxTOP, 5 ); - - // Provide a StdDialogButtonSizer to accommodate the OK and Cancel buttons; - // using that type of sizer results in those buttons being automatically - // located in positions appropriate for each (OS) version of KiCad. - StdDialogButtonSizer = new wxStdDialogButtonSizer; - OuterBoxSizer->Add( StdDialogButtonSizer, 0, wxGROW | wxALL, 10 ); - - Button = new wxButton( this, wxID_OK, _( "&OK" ), wxDefaultPosition, - wxDefaultSize, 0 ); - StdDialogButtonSizer->AddButton( Button ); - - Button = new wxButton( this, wxID_CANCEL, _( "&Cancel" ), - wxDefaultPosition, wxDefaultSize, 0 ); - StdDialogButtonSizer->AddButton( Button ); - StdDialogButtonSizer->Realize(); - // Resize the dialog - if( GetSizer() ) - { - GetSizer()->SetSizeHints( this ); - } + GetSizer()->SetSizeHints( this ); + Centre(); } -void SWAP_LAYERS_DIALOG::OnSelectLayer( wxCommandEvent& event ) +void LAYERS_TABLE_DIALOG::OnSelectLayer( wxCommandEvent& event ) { int ii, jj; @@ -365,13 +295,13 @@ void SWAP_LAYERS_DIALOG::OnSelectLayer( wxCommandEvent& event ) } -void SWAP_LAYERS_DIALOG::OnCancelClick( wxCommandEvent& event ) +void LAYERS_TABLE_DIALOG::OnCancelClick( wxCommandEvent& event ) { - EndModal( -1 ); + EndModal( wxID_CANCEL ); } -void SWAP_LAYERS_DIALOG::OnOkClick( wxCommandEvent& event ) +void LAYERS_TABLE_DIALOG::OnOkClick( wxCommandEvent& event ) { int ii; bool AsCmpLayer = false; @@ -395,10 +325,14 @@ void SWAP_LAYERS_DIALOG::OnOkClick( wxCommandEvent& event ) if( AsCmpLayer ) layers_count++; + if( layers_count > NB_COPPER_LAYERS ) // should not occur. layers_count = NB_COPPER_LAYERS; + if( layers_count < 2 ) + layers_count = 2; + m_Parent->GetBoard()->SetCopperLayerCount( layers_count ); - EndModal( 1 ); + EndModal( wxID_OK ); }