From b30b24c50aadaf5fe7894b35aeecd2efaaba7b7e Mon Sep 17 00:00:00 2001 From: g_harland Date: Fri, 2 Nov 2007 05:33:31 +0000 Subject: [PATCH] Update (Pcbnew) "Swap Layers:" and (GerbView) "Layer selection" dialog boxes --- change_log.txt | 24 ++ gerbview/select_layers_to_pcb.cpp | 429 ++++++++++++++++++------------ pcbnew/swap_layers.cpp | 292 +++++++++++++------- 3 files changed, 482 insertions(+), 263 deletions(-) diff --git a/change_log.txt b/change_log.txt index 5279ce4edc..a51bd814a3 100644 --- a/change_log.txt +++ b/change_log.txt @@ -4,6 +4,30 @@ Started 2007-June-11 Please add newer entries at the top, list the date and your name with email address. +2007-Nov-02 UPDATE Geoff Harland +================================================================================ ++ pcbnew + * Sizers have now been provided for the "Swap Layers:" dialog box, and the + previously provided radiobuttons have been replaced with buttons and static + text strings. (In the previous version of this dialog, radiobuttons were being + used in an inappropriate manner. The most "orthodox" way of implementing the + functionality within this dialog would be to provide a combobox for each layer, + but as up to 30 strings would be needed within the dropdown list associated with + each of those controls (one string for each of the layers, and another string to + deselect the layer), such controls would be less than user-friendly. Hence a + button is now provided for each layer instead (and which, like the previously + provided radiobutton, invokes the "Select Layer:" dialog box after being clicked + on). Two static text strings are also provided for each layer, with one of them + being used to identify that layer, and the other being used to identify which + layer that each layer is currently being swapped to.) The previously provided + "Select" and "Deselect" buttons are no longer required, and are thus no longer + provided. ++ gerbview + * The "Layer selection" dialog box (invoked during the "Export to Pcbnew" command) + has similarly been updated. (This dialog did use spacers before, but once again, + the previously provided radiobuttons were being used in an inappropriate manner.) + + 2007-Nov-01 UPDATE Geoff Harland ================================================================================ + pcbnew diff --git a/gerbview/select_layers_to_pcb.cpp b/gerbview/select_layers_to_pcb.cpp index e0bf008eb0..267e6cc6cd 100644 --- a/gerbview/select_layers_to_pcb.cpp +++ b/gerbview/select_layers_to_pcb.cpp @@ -1,8 +1,8 @@ - /*******************************************************/ - /* Dialog frame to choose gerber layers and pcb layers */ - /*******************************************************/ +/*******************************************************/ +/* Dialog frame to choose gerber layers and pcb layers */ +/*******************************************************/ - /* select_layers_to_pcb.cpp*/ +/* select_layers_to_pcb.cpp */ #include "fctsys.h" #include "common.h" @@ -10,15 +10,17 @@ #include "protos.h" +#include "wx/statline.h" /* Variables locales */ -static int RadioButtonTable[32]; // Indexes radiobuttons to Gerber layers +static int ButtonTable[32]; // Indexes buttons to Gerber layers static int LayerLookUpTable[32]; // Indexes Gerber layers to PCB file layers +wxStaticText* layer_list[32]; // Indexes text strings to buttons enum swap_layer_id { - ID_SWAP_LAYER_BUTTON_SELECT = 1800, - ID_SWAP_LAYER_DESELECT, - ID_SWAP_LAYER_SELECT + ID_WINEDA_SWAPLAYERFRAME = 1800, + ID_BUTTON_0, + ID_TEXT_0 = ID_BUTTON_0 + 32 }; @@ -29,14 +31,21 @@ enum swap_layer_id { class WinEDA_SwapLayerFrame: public wxDialog { private: - WinEDA_GerberFrame *m_Parent; - wxRadioBox * m_LayerList; + WinEDA_GerberFrame* m_Parent; + wxBoxSizer* OuterBoxSizer; + wxBoxSizer* MainBoxSizer; + wxFlexGridSizer* FlexColumnBoxSizer; + wxStaticText* label; + wxButton* Button; + wxStaticText* text; + wxStaticLine* Line; + wxStdDialogButtonSizer* StdDialogButtonSizer; public: - // Constructor and destructor - WinEDA_SwapLayerFrame(WinEDA_GerberFrame *parent); - ~WinEDA_SwapLayerFrame() {}; + // Constructor and destructor + WinEDA_SwapLayerFrame(WinEDA_GerberFrame *parent); + ~WinEDA_SwapLayerFrame() {}; private: void Sel_Layer(wxCommandEvent& event); @@ -44,16 +53,15 @@ private: void OnCancelClick(wxCommandEvent& event); DECLARE_EVENT_TABLE() - }; /* Table des evenements pour WinEDA_SwapLayerFrame */ BEGIN_EVENT_TABLE(WinEDA_SwapLayerFrame, wxDialog) - EVT_BUTTON(wxID_OK, WinEDA_SwapLayerFrame::OnOkClick) - EVT_BUTTON(wxID_CANCEL, WinEDA_SwapLayerFrame::OnCancelClick) - EVT_BUTTON(ID_SWAP_LAYER_DESELECT, WinEDA_SwapLayerFrame::Sel_Layer) - EVT_BUTTON(ID_SWAP_LAYER_BUTTON_SELECT, WinEDA_SwapLayerFrame::Sel_Layer) - EVT_RADIOBOX(ID_SWAP_LAYER_SELECT, WinEDA_SwapLayerFrame::Sel_Layer) + EVT_COMMAND_RANGE( ID_BUTTON_0, ID_BUTTON_0 + NB_LAYERS - 1, + wxEVT_COMMAND_BUTTON_CLICKED, + WinEDA_SwapLayerFrame::Sel_Layer ) + EVT_BUTTON( wxID_OK, WinEDA_SwapLayerFrame::OnOkClick ) + EVT_BUTTON( wxID_CANCEL, WinEDA_SwapLayerFrame::OnCancelClick ) END_EVENT_TABLE() @@ -65,129 +73,228 @@ int * InstallDialogLayerPairChoice(WinEDA_GerberFrame * parent) * return the "lookup table" if ok, or NULL */ { - WinEDA_SwapLayerFrame * frame = new WinEDA_SwapLayerFrame(parent); - int ii = frame->ShowModal(); - frame->Destroy(); - if( ii >= 0 ) - return LayerLookUpTable; - else - return NULL; + WinEDA_SwapLayerFrame * frame = new WinEDA_SwapLayerFrame(parent); + int ii = frame->ShowModal(); + frame->Destroy(); + if( ii >= 0 ) + return LayerLookUpTable; + else + return NULL; } /*************************************************************************/ -WinEDA_SwapLayerFrame::WinEDA_SwapLayerFrame(WinEDA_GerberFrame *parent): - wxDialog( parent, -1, _("Layer selection:"), wxPoint(-1, -1), - wxDefaultSize, DIALOG_STYLE ) +WinEDA_SwapLayerFrame::WinEDA_SwapLayerFrame(WinEDA_GerberFrame *parent) : + wxDialog( parent, -1, _("Layer selection:"), wxPoint(-1, -1), + wxDefaultSize, wxDEFAULT_DIALOG_STYLE|MAYBE_RESIZE_BORDER ) /*************************************************************************/ { -wxButton * Button; -int ii, nb_items; -wxString g_Layer_Name_Pair[32]; + OuterBoxSizer = NULL; + MainBoxSizer = NULL; + FlexColumnBoxSizer = NULL; + label = NULL; + Button = NULL; + text = NULL; + Line = NULL; + StdDialogButtonSizer = NULL; - m_Parent = parent; - SetFont(*g_DialogFont); + m_Parent = parent; + SetFont( *g_DialogFont ); - // Compute a reasonable number of copper layers - g_DesignSettings.m_CopperLayerCount = 0; - for( ii = 0; ii < 32; ii++ ) - { - if( g_GERBER_Descr_List[ii] != NULL ) - g_DesignSettings.m_CopperLayerCount++; + int item_ID, ii, nb_items; + wxString msg; + wxSize goodSize; - // Specify the default value for each member of these arrays. - RadioButtonTable[ii] = -1; - LayerLookUpTable[ii] = NB_LAYERS; // Value associated with deselected Gerber layer - } + // Experimentation has shown that buttons in the Windows version can be 20 pixels + // wide and 20 pixels high, but that they need to be 26 pixels wide and 26 pixels + // high in the Linux version. (And although the dimensions of those buttons could + // be set to 26 pixels wide and 26 pixels high in both of those versions, that would + // result in a dialog box which would be excessively high in the Windows version.) +#ifdef __WINDOWS__ + int w = 20; + int h = 20; +#else + int w = 26; + int h = 26; +#endif + // As currently implemented, the dimensions of the buttons in the Mac version are + // also 26 pixels wide and 26 pixels high. If appropriate, the above code should be + // modified as required in the event that those buttons should be some other size + // in that version. - int pcb_layer_number = 0; - for( nb_items = 0, ii = 0; ii < 32; ii++ ) - { - if( g_GERBER_Descr_List[ii] == NULL ) - continue; + // Compute a reasonable number of copper layers + g_DesignSettings.m_CopperLayerCount = 0; + for( ii = 0; ii < 32; ii++ ) + { + if( g_GERBER_Descr_List[ii] != NULL ) + g_DesignSettings.m_CopperLayerCount++; - if( (pcb_layer_number == g_DesignSettings.m_CopperLayerCount - 1) - && (g_DesignSettings.m_CopperLayerCount > 1) ) - pcb_layer_number = CMP_N; + // Specify the default value for each member of these arrays. + ButtonTable[ii] = -1; + LayerLookUpTable[ii] = NB_LAYERS; // Value associated with deselected Gerber layer + } - RadioButtonTable[nb_items] = ii; - LayerLookUpTable[ii] = pcb_layer_number; + int pcb_layer_number = 0; + for( nb_items = 0, ii = 0; ii < 32; ii++ ) + { - // Specify initial (temporary) caption for associated radiobutton, - // which will be appropriately updated after dialog box has been sized. - // (If the radiobuttons' captions are not changed in this way, some of - // each radiobutton's caption could be truncated if the associated - // (Gerber) layer is ever subsequently deselected by the user.) - g_Layer_Name_Pair[nb_items] = _("Gerber layer "); - g_Layer_Name_Pair[nb_items] << ii + 1 << wxT(" -> ") << _("Do not export"); + if( g_GERBER_Descr_List[ii] == NULL ) + continue; - nb_items++; - pcb_layer_number++; - } + if( (pcb_layer_number == g_DesignSettings.m_CopperLayerCount - 1) + && (g_DesignSettings.m_CopperLayerCount > 1) ) + pcb_layer_number = CMP_N; - wxBoxSizer* FrameBoxSizer = new wxBoxSizer(wxVERTICAL); - SetSizer(FrameBoxSizer); + ButtonTable[nb_items] = ii; + LayerLookUpTable[ii] = pcb_layer_number; + nb_items++; + pcb_layer_number++; + } - wxBoxSizer* MainBoxSizer = new wxBoxSizer(wxHORIZONTAL); - FrameBoxSizer->Add(MainBoxSizer, 0, wxGROW|wxALIGN_LEFT|wxALL, 5); + OuterBoxSizer = new wxBoxSizer(wxVERTICAL); + SetSizer(OuterBoxSizer); - m_LayerList = new wxRadioBox(this, ID_SWAP_LAYER_SELECT, _("Layers"), - wxDefaultPosition, wxDefaultSize, - nb_items, g_Layer_Name_Pair, - nb_items < 16 ? nb_items : 16, - wxRA_SPECIFY_ROWS); + MainBoxSizer = new wxBoxSizer(wxHORIZONTAL); + OuterBoxSizer->Add(MainBoxSizer, 1, wxGROW|wxLEFT|wxRIGHT|wxTOP, 5); - // Specify a minimum size for this radiobox (with the objective - // of attempting to prevent any radiobutton's caption from being - // truncated if any of the layers are subsequently deselected) - m_LayerList->SetMinSize( m_LayerList->GetSize() ); + 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); + } - MainBoxSizer->Add(m_LayerList, 0, wxALIGN_TOP|wxALL, 5); + // 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 blue (to indicate that the actual text changes depending upon which + // pcbnew layer has been selected by the child dialog box). + // (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.) - wxBoxSizer* RightBoxSizer = new wxBoxSizer(wxVERTICAL); - MainBoxSizer->Add(RightBoxSizer, 0, wxALIGN_TOP|wxALL, 0); + // 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). - RightBoxSizer->AddSpacer(10); + if( nb_items < 16 ) + FlexColumnBoxSizer = new wxFlexGridSizer(nb_items, 3, 0, 0); + else + FlexColumnBoxSizer = new wxFlexGridSizer(16, 3, 0, 0); - Button = new wxButton(this, ID_SWAP_LAYER_BUTTON_SELECT, _("Select...")); - Button->SetForegroundColour(wxColour(0,100,100)); - RightBoxSizer->Add(Button, 0, wxGROW|wxALL, 5); + // Specify that all of the rows can be expanded. + for( int jj = 0; jj < MIN(nb_items, 16); jj++ ) + { + FlexColumnBoxSizer->AddGrowableRow(jj); + } - Button = new wxButton(this, ID_SWAP_LAYER_DESELECT, _("Deselect")); - Button->SetForegroundColour(wxColour(0,100,0)); - RightBoxSizer->Add(Button, 0, wxGROW|wxALL, 5); + // Specify that (just) the right-hand column can be expanded. + FlexColumnBoxSizer->AddGrowableCol(2); - wxBoxSizer* BottomBoxSizer = new wxBoxSizer(wxHORIZONTAL); - FrameBoxSizer->Add(BottomBoxSizer, 0, wxGROW|wxALIGN_RIGHT|wxALL, 5); + MainBoxSizer->Add(FlexColumnBoxSizer, 1, wxGROW|wxTOP, 5); + } - // The following stretch spacer ensures that the "OK" and "Cancel" buttons - // will be positioned at the lower right corner of the dialog box. - BottomBoxSizer->AddStretchSpacer(); + // Provide a text string to identify the Gerber layer + msg = _("Gerber layer "); + msg << ButtonTable[ii] + 1; - Button = new wxButton(this, wxID_OK, _("OK")); - Button->SetForegroundColour(*wxRED); - BottomBoxSizer->Add(Button, 0, wxGROW|wxALL, 5); - - Button = new wxButton(this, wxID_CANCEL, _("Cancel")); - Button->SetForegroundColour(*wxBLUE); - BottomBoxSizer->Add(Button, 0, wxGROW|wxALL, 5); + label = new wxStaticText( this, wxID_STATIC, msg, wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT ); + FlexColumnBoxSizer->Add(label, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxLEFT|wxBOTTOM, 5); + // Provide a button for this layer (which will invoke a child dialog box) + item_ID = ID_BUTTON_0 + ii; + + Button = new wxButton( this, item_ID, wxT("..."), wxDefaultPosition, wxSize(w, h), 0 ); + FlexColumnBoxSizer->Add(Button, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT|wxBOTTOM, 5); + + // Provide another text string to specify which pcbnew layer that this + // Gerber layer is initially mapped to, and set the initial text to + // specify the appropriate pcbnew layer, and set the foreground color + // of the text to blue (to indicate that the text can be changed). + item_ID = ID_TEXT_0 + ii; + + // When the first of these text strings is being added, determine what size is necessary to + // to be able to display any possible string without it being truncated. Then specify that + // size as the minimum size for all of these text strings. (If this minimum size is not + // determined in this fashion, then it is possible for the display of one or more of these + // strings to be truncated after different pcbnew layers are selected.) + if( ii == 0 ) + { + msg = _( "Do not export" ); + text = new wxStaticText( this, item_ID, msg, wxDefaultPosition, wxDefaultSize, 0 ); + goodSize = text->GetSize(); + for( int jj = 0; jj < NB_LAYERS; jj++ ) + { + text->SetLabel( ReturnPcbLayerName( jj ) ); + if( goodSize.x < text->GetSize().x ) + goodSize.x = text->GetSize().x; + } + msg = ReturnPcbLayerName(LayerLookUpTable[ButtonTable[ii]]); + text->SetLabel( msg ); + } + else + { + msg = ReturnPcbLayerName(LayerLookUpTable[ButtonTable[ii]]); + text = new wxStaticText( this, item_ID, msg, wxDefaultPosition, wxDefaultSize, 0 ); + } + text->SetMinSize( goodSize ); + text->SetForegroundColour( *wxBLUE ); + FlexColumnBoxSizer->Add(text, 1, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxBOTTOM, 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 = 3 * 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, wxALIGN_RIGHT|wxALL, 10); + + Button = new wxButton( this, wxID_OK, _("&OK"), wxDefaultPosition, wxDefaultSize, 0 ); + Button->SetForegroundColour( *wxRED ); + StdDialogButtonSizer->AddButton(Button); + + Button = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); + Button->SetForegroundColour( *wxBLUE ); + StdDialogButtonSizer->AddButton(Button); + + StdDialogButtonSizer->Realize(); + + // Resize the dialog if( GetSizer() ) { GetSizer()->SetSizeHints(this); } - - // Now specify the correct caption for each radiobutton. - // (Regrettably though there are still problems with the Windows - // version; captions for each radiobutton can still be truncated.) :-( - for( ii = 0; ii < nb_items; ii++ ) - { - g_Layer_Name_Pair[ii] = _("Gerber layer "); - g_Layer_Name_Pair[ii] << RadioButtonTable[ii] + 1 << wxT(" -> ") - << ReturnPcbLayerName(LayerLookUpTable[RadioButtonTable[ii]]); - - m_LayerList->SetString( ii, g_Layer_Name_Pair[ii] ); - } } @@ -195,49 +302,31 @@ wxString g_Layer_Name_Pair[32]; void WinEDA_SwapLayerFrame::Sel_Layer(wxCommandEvent& event) /***************************************************************/ { -int ii, jj; -// int gerber_layer_number; -wxString msg; + int ii, jj; - ii = m_LayerList->GetSelection(); - if( ii < 0 ) - return; + ii = event.GetId(); - switch ( event.GetId() ) - { - case ID_SWAP_LAYER_DESELECT: - if( LayerLookUpTable[RadioButtonTable[ii]] != NB_LAYERS ) - { - LayerLookUpTable[RadioButtonTable[ii]] = NB_LAYERS; - msg = _("Gerber layer "); - msg << RadioButtonTable[ii] + 1 - << wxT(" -> ") << _("Do not export"); - m_LayerList->SetString( ii, msg ); - } - break; + if( ii < ID_BUTTON_0 || ii >= ID_BUTTON_0 + 32 ) + return; - case ID_SWAP_LAYER_BUTTON_SELECT: - case ID_SWAP_LAYER_SELECT: - jj = LayerLookUpTable[RadioButtonTable[ii]]; - if( (jj < 0) || (jj > NB_LAYERS) ) - jj = 0; // (Defaults to "Copper" layer.) - jj = m_Parent->SelectLayer(jj, -1, -1, true); - if( (jj < 0) || (jj > NB_LAYERS) ) - return; + ii = event.GetId() - ID_BUTTON_0; - if( jj != LayerLookUpTable[RadioButtonTable[ii]] ) - { - LayerLookUpTable[RadioButtonTable[ii]] = jj; - msg = _("Gerber layer "); - msg << RadioButtonTable[ii] + 1 << wxT(" -> "); - if( jj == NB_LAYERS ) - msg << _("Do not export"); - else - msg << ReturnPcbLayerName(jj); - m_LayerList->SetString( ii, msg ); - } - break; - } + jj = LayerLookUpTable[ButtonTable[ii]]; + if( (jj < 0) || (jj > NB_LAYERS) ) + jj = 0; // (Defaults to "Copper" layer.) + jj = m_Parent->SelectLayer(jj, -1, -1, true); + + if( (jj < 0) || (jj > NB_LAYERS) ) + return; + + if( jj != LayerLookUpTable[ButtonTable[ii]] ) + { + LayerLookUpTable[ButtonTable[ii]] = jj; + if( jj == NB_LAYERS ) + layer_list[ii]->SetLabel( _( "Do not export" ) ); + else + layer_list[ii]->SetLabel( ReturnPcbLayerName( jj ) ); + } } @@ -256,27 +345,27 @@ void WinEDA_SwapLayerFrame::OnOkClick(wxCommandEvent& event) int ii; bool AsCmpLayer = false; - /* Compute the number of copper layers - * this is the max layer number + 1 (if some internal layers exist) - */ - g_DesignSettings.m_CopperLayerCount = 1; - for( ii = 0; ii < 32; ii++ ) - { - if( LayerLookUpTable[ii] == CMP_N ) - AsCmpLayer = true; - else - { - if( LayerLookUpTable[ii] >= LAST_COPPER_LAYER ) - continue; // not a copper layer - if( LayerLookUpTable[ii] >= g_DesignSettings.m_CopperLayerCount ) - g_DesignSettings.m_CopperLayerCount++; - } - } + /* Compute the number of copper layers + * this is the max layer number + 1 (if some internal layers exist) + */ + g_DesignSettings.m_CopperLayerCount = 1; + for( ii = 0; ii < 32; ii++ ) + { + if( LayerLookUpTable[ii] == CMP_N ) + AsCmpLayer = true; + else + { + if( LayerLookUpTable[ii] >= LAST_COPPER_LAYER ) + continue; // not a copper layer + if( LayerLookUpTable[ii] >= g_DesignSettings.m_CopperLayerCount ) + g_DesignSettings.m_CopperLayerCount++; + } + } - if( AsCmpLayer ) - g_DesignSettings.m_CopperLayerCount++; - if( g_DesignSettings.m_CopperLayerCount > NB_COPPER_LAYERS ) // should not occur. - g_DesignSettings.m_CopperLayerCount = NB_COPPER_LAYERS; + if( AsCmpLayer ) + g_DesignSettings.m_CopperLayerCount++; + if( g_DesignSettings.m_CopperLayerCount > NB_COPPER_LAYERS ) // should not occur. + g_DesignSettings.m_CopperLayerCount = NB_COPPER_LAYERS; EndModal( 1 ); } diff --git a/pcbnew/swap_layers.cpp b/pcbnew/swap_layers.cpp index 404e4c8f42..995f8605d6 100644 --- a/pcbnew/swap_layers.cpp +++ b/pcbnew/swap_layers.cpp @@ -10,13 +10,16 @@ #include "protos.h" +#include "wx/statline.h" + /* Variables locales */ static int New_Layer[NB_LAYERS]; +wxStaticText* layer_list[NB_LAYERS]; enum swap_layer_id { - ID_SWAP_LAYER_BUTTON_SELECT = 1800, - ID_SWAP_LAYER_DESELECT, - ID_SWAP_LAYER_SELECT + ID_WINEDA_SWAPLAYERFRAME = 1800, + ID_BUTTON_0, + ID_TEXT_0 = ID_BUTTON_0 + NB_LAYERS }; @@ -27,8 +30,15 @@ enum swap_layer_id { class WinEDA_SwapLayerFrame : public wxDialog { private: - WinEDA_BasePcbFrame* m_Parent; - wxRadioBox* m_LayerList; + WinEDA_BasePcbFrame* m_Parent; + wxBoxSizer* OuterBoxSizer; + wxBoxSizer* MainBoxSizer; + wxFlexGridSizer* FlexColumnBoxSizer; + wxStaticText* label; + wxButton* Button; + wxStaticText* text; + wxStaticLine* Line; + wxStdDialogButtonSizer* StdDialogButtonSizer; public: @@ -46,68 +56,180 @@ private: /* Table des evenements pour WinEDA_SwapLayerFrame */ BEGIN_EVENT_TABLE( WinEDA_SwapLayerFrame, wxDialog ) -EVT_BUTTON( wxID_OK, WinEDA_SwapLayerFrame::OnOkClick ) -EVT_BUTTON( wxID_CANCEL, WinEDA_SwapLayerFrame::OnCancelClick ) -EVT_BUTTON( ID_SWAP_LAYER_DESELECT, WinEDA_SwapLayerFrame::Sel_Layer ) -EVT_BUTTON( ID_SWAP_LAYER_BUTTON_SELECT, WinEDA_SwapLayerFrame::Sel_Layer ) -EVT_RADIOBOX( ID_SWAP_LAYER_SELECT, WinEDA_SwapLayerFrame::Sel_Layer ) + EVT_COMMAND_RANGE( ID_BUTTON_0, ID_BUTTON_0 + NB_LAYERS - 1, + wxEVT_COMMAND_BUTTON_CLICKED, + WinEDA_SwapLayerFrame::Sel_Layer ) + EVT_BUTTON( wxID_OK, WinEDA_SwapLayerFrame::OnOkClick ) + EVT_BUTTON( wxID_CANCEL, WinEDA_SwapLayerFrame::OnCancelClick ) END_EVENT_TABLE() /*************************************************************************/ WinEDA_SwapLayerFrame::WinEDA_SwapLayerFrame( WinEDA_BasePcbFrame* parent ) : wxDialog( parent, -1, _( "Swap Layers:" ), wxPoint( -1, -1 ), - wxSize( 470, 450 ), DIALOG_STYLE ) + wxDefaultSize, wxDEFAULT_DIALOG_STYLE|MAYBE_RESIZE_BORDER ) /*************************************************************************/ { -#define START_Y 15 - wxButton* Button; - int ii; - wxPoint pos; - wxString g_Layer_Name_Pair[NB_LAYERS]; - wxSize winsize; + OuterBoxSizer = NULL; + MainBoxSizer = NULL; + FlexColumnBoxSizer = NULL; + label = NULL; + Button = NULL; + text = NULL; + Line = NULL; + StdDialogButtonSizer = NULL; m_Parent = parent; SetFont( *g_DialogFont ); - for( ii = 0; ii < NB_LAYERS; ii++ ) + int item_ID; + wxSize goodSize; + + // Experimentation has shown that buttons in the Windows version can be 20 pixels + // wide and 20 pixels high, but that they need to be 26 pixels wide and 26 pixels + // high in the Linux version. (And although the dimensions of those buttons could + // be set to 26 pixels wide and 26 pixels high in both of those versions, that would + // result in a dialog box which would be excessively high in the Windows version.) +#ifdef __WINDOWS__ + int w = 20; + int h = 20; +#else + int w = 26; + int h = 26; +#endif + // As currently implemented, the dimensions of the buttons in the Mac version are + // also 26 pixels wide and 26 pixels high. If appropriate, the above code should be + // modified as required in the event that those buttons should be some other size + // in that version. + + OuterBoxSizer = new wxBoxSizer(wxVERTICAL); + SetSizer(OuterBoxSizer); + + MainBoxSizer = new wxBoxSizer(wxHORIZONTAL); + OuterBoxSizer->Add(MainBoxSizer, 1, wxGROW|wxLEFT|wxRIGHT|wxTOP, 5); + + for( int ii = 0; ii < NB_LAYERS; ii++ ) { - g_Layer_Name_Pair[ii] = ReturnPcbLayerName( ii ) + wxT( " -> " ) + _( "No Change" ); + // Provide a vertical line to separate the two FlexGrid sizers + if( ii == 16 ) + { + Line = new wxStaticLine( this, -1, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL ); + MainBoxSizer->Add(Line, 0, wxGROW|wxLEFT|wxRIGHT, 5); + } + + // Provide a separate FlexGrid sizer for every sixteen sets of controls + if( ii % 16 == 0 ) + { + // Each layer has an associated static text string (to identify that layer), + // a button (for invoking a child dialog box to change which layer that the + // layer is mapped to), and a second static text string (to depict which layer + // that the 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 blue + // (to indicate that the actual text changes depending upon which layer has been + // selected by the child dialog box). + // (Experimentation has shown that if a text control is used to depict which + // layer that each 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 sixteen rows and three columns. + FlexColumnBoxSizer = new wxFlexGridSizer(16, 3, 0, 0); + + // Specify that all of the rows can be expanded. + for( int jj = 0; jj < 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); + } + + // Provide a text string to identify this layer (with trailing spaces within that string being purged) + label = new wxStaticText( this, wxID_STATIC, ReturnPcbLayerName( ii ).Trim(), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT ); + FlexColumnBoxSizer->Add(label, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxLEFT|wxBOTTOM, 5); + + // Provide a button for this layer (which will invoke a child dialog box) + item_ID = ID_BUTTON_0 + ii; + + Button = new wxButton( this, item_ID, wxT("..."), wxDefaultPosition, wxSize(w, h), 0 ); + FlexColumnBoxSizer->Add(Button, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT|wxBOTTOM, 5); + + // Provide another text string to specify which layer that this layer is + // mapped to, set the initial text to "No Change" (to indicate that this + // layer is currently unmapped to any other layer), and set the foreground + // color of the text to blue (to indicate that the text can be changed). + item_ID = ID_TEXT_0 + ii; + + // When the first of these text strings is being added, determine what size is necessary to + // to be able to display any possible string without it being truncated. Then specify that + // size as the minimum size for all of these text strings. (If this minimum size is not + // determined in this fashion, then it is possible for the display of one or more of these + // strings to be truncated after different layers are selected.) + if( ii == 0 ) + { + text = new wxStaticText( this, item_ID, ReturnPcbLayerName( 0 ), wxDefaultPosition, wxDefaultSize, 0 ); + goodSize = text->GetSize(); + for( int jj = 1; jj < NB_LAYERS; jj++ ) + { + text->SetLabel( ReturnPcbLayerName( jj ) ); + if( goodSize.x < text->GetSize().x ) + goodSize.x = text->GetSize().x; + } + text->SetLabel( _("No Change") ); + if( goodSize.x < text->GetSize().x ) + goodSize.x = text->GetSize().x; + } + else + text = new wxStaticText( this, item_ID, _("No Change"), wxDefaultPosition, wxDefaultSize, 0 ); + + text->SetMinSize( goodSize ); + text->SetForegroundColour( *wxBLUE ); + FlexColumnBoxSizer->Add(text, 1, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxBOTTOM, 5); + + layer_list[ii] = text; } - pos.x = 5; - pos.y = START_Y; - m_LayerList = new wxRadioBox( this, ID_SWAP_LAYER_SELECT, _( "Layers" ), - pos, wxSize( -1, -1 ), - NB_LAYERS, g_Layer_Name_Pair, 16, wxRA_SPECIFY_ROWS ); + // 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.) + for( int ii = 3 * NB_LAYERS; ii < 96; ii++ ) + { + FlexColumnBoxSizer->Add(5, h, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxBOTTOM, 5); + } - winsize.y = m_LayerList->GetRect().GetBottom(); + // 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); - pos.x = m_LayerList->GetRect().GetRight() + 12; + // 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, wxALIGN_RIGHT|wxALL, 10); - Button = new wxButton(this, ID_SWAP_LAYER_BUTTON_SELECT, _("Select..."), pos ); - Button->SetForegroundColour(wxColour(0,100,100)); + Button = new wxButton( this, wxID_OK, _("&OK"), wxDefaultPosition, wxDefaultSize, 0 ); + Button->SetForegroundColour( *wxRED ); + StdDialogButtonSizer->AddButton(Button); - pos.y += Button->GetSize().y + 10; + Button = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 ); + Button->SetForegroundColour( *wxBLUE ); + StdDialogButtonSizer->AddButton(Button); - Button = new wxButton(this, ID_SWAP_LAYER_DESELECT, _("Deselect"), pos ); - Button->SetForegroundColour(wxColour(0,100,0)); + StdDialogButtonSizer->Realize(); - pos.y = winsize.y - 2 * Button->GetSize().y - 10; - - Button = new wxButton(this, wxID_OK, _("OK"), pos ); - Button->SetForegroundColour(*wxRED); - - pos.y += Button->GetSize().y + 10; - - Button = new wxButton(this, wxID_CANCEL, _("Cancel"), pos ); - Button->SetForegroundColour(*wxBLUE); - - winsize.x = MAX( winsize.x, Button->GetRect().GetRight() ); - winsize.y = MAX( winsize.y, Button->GetRect().GetBottom() ); - winsize.x += 10; - winsize.y += 10; - SetClientSize( winsize ); + // Resize the dialog + if( GetSizer() ) + { + GetSizer()->SetSizeHints(this); + } } @@ -117,56 +239,40 @@ void WinEDA_SwapLayerFrame::Sel_Layer( wxCommandEvent& event ) { int ii, jj; - ii = m_LayerList->GetSelection(); + ii = event.GetId(); - switch( event.GetId() ) + if( ii < ID_BUTTON_0 || ii >= ID_BUTTON_0 + NB_LAYERS ) + return; + + ii = event.GetId() - ID_BUTTON_0; + + jj = New_Layer[ii]; + if( (jj < 0) || (jj > NB_LAYERS) ) + jj = NB_LAYERS; // (Defaults to "No Change".) + jj = m_Parent->SelectLayer( jj, -1, -1, true ); + + if( (jj < 0) || (jj > NB_LAYERS) ) + return; + + // No change if the selected layer matches the layer being edited. + // (Hence the only way to restore a layer to the "No Change" + // state is by specifically deselecting it; any attempt + // to select the same layer (instead) will be ignored.) + if( jj == ii ) { - case ID_SWAP_LAYER_DESELECT: - if( New_Layer[ii] != NB_LAYERS ) - { - New_Layer[ii] = NB_LAYERS; - m_LayerList->SetString( ii, ReturnPcbLayerName( ii ) - + wxT( " -> " ) + _( "No Change" ) ); - } - break; + wxString msg; + msg = _( "Deselect this layer to select the No Change state" ); + DisplayInfo( this, msg ); + return; + } - case ID_SWAP_LAYER_BUTTON_SELECT: - case ID_SWAP_LAYER_SELECT: - jj = New_Layer[ii]; - if( (jj < 0) || (jj > NB_LAYERS) ) - jj = NB_LAYERS; // (Defaults to "No Change".) - jj = m_Parent->SelectLayer( jj, -1, -1, true ); - - if( (jj < 0) || (jj > NB_LAYERS) ) - return; - - // No change if the selected layer matches the layer being edited. - // (Hence the only way to restore a layer to the "No Change" - // state is by specifically deselecting it; any attempt - // to select the same layer (instead) will be ignored.) - if( jj == ii ) - { - wxString msg; - msg = _( "Deselect this layer to restore its No Change state" ); - DisplayInfo( this, msg ); - return; - } - - if( jj != New_Layer[ii] ) - { - New_Layer[ii] = jj; - if( jj == NB_LAYERS ) - m_LayerList->SetString( ii, - ReturnPcbLayerName( ii ) - + wxT( " -> " ) - + _( "No Change" ) ); - else - m_LayerList->SetString( ii, - ReturnPcbLayerName( ii ) - + wxT( " -> " ) - + ReturnPcbLayerName( jj ) ); - } - break; + if( jj != New_Layer[ii] ) + { + New_Layer[ii] = jj; + if( jj == NB_LAYERS ) + layer_list[ii]->SetLabel( _( "No Change" ) ); + else + layer_list[ii]->SetLabel( ReturnPcbLayerName( jj ) ); } }