You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

378 lines
13 KiB

  1. /* Set up the basic primitives for Layer control */
  2. #include "fctsys.h"
  3. #include "gr_basic.h"
  4. #include "common.h"
  5. #include "pcbnew.h"
  6. #include "protos.h"
  7. /* Variables locales */
  8. /* Fonctions locales: */
  9. enum layer_sel_id {
  10. ID_LAYER_SELECT_TOP = 1800,
  11. ID_LAYER_SELECT_BOTTOM,
  12. ID_LAYER_SELECT
  13. };
  14. /***********************************************/
  15. /* classe pour la frame de selection de layers */
  16. /***********************************************/
  17. class WinEDA_SelLayerFrame : public wxDialog
  18. {
  19. private:
  20. WinEDA_BasePcbFrame* m_Parent;
  21. wxRadioBox* m_LayerList;
  22. int m_LayerId[NB_LAYERS + 1]; // One extra element for "(Deselect)" radiobutton
  23. public:
  24. // Constructor and destructor
  25. WinEDA_SelLayerFrame( WinEDA_BasePcbFrame* parent, int default_layer,
  26. int min_layer, int max_layer, bool null_layer );
  27. ~WinEDA_SelLayerFrame() { };
  28. private:
  29. void Sel_Layer( wxCommandEvent& event );
  30. void OnCancelClick( wxCommandEvent& event );
  31. DECLARE_EVENT_TABLE()
  32. };
  33. /* Table des evenements pour WinEDA_SelLayerFrame */
  34. BEGIN_EVENT_TABLE( WinEDA_SelLayerFrame, wxDialog )
  35. EVT_BUTTON( wxID_OK, WinEDA_SelLayerFrame::Sel_Layer )
  36. EVT_BUTTON( wxID_CANCEL, WinEDA_SelLayerFrame::OnCancelClick )
  37. EVT_RADIOBOX( ID_LAYER_SELECT, WinEDA_SelLayerFrame::Sel_Layer )
  38. END_EVENT_TABLE()
  39. /****************************************************************************************/
  40. int WinEDA_BasePcbFrame::SelectLayer( int default_layer, int min_layer, int max_layer,
  41. bool null_layer )
  42. /****************************************************************************************/
  43. /** Install the dialog box for layer selection
  44. * @param default_layer = Preselection (NB_LAYERS for "(Deselect)" layer)
  45. * @param min_layer = min layer value (-1 if no min value)
  46. * @param max_layer = max layer value (-1 if no max value)
  47. * @param null_layer = display a "(Deselect)" radiobutton (when set to true)
  48. * @return new layer value (NB_LAYERS when "(Deselect)" radiobutton selected),
  49. * or -1 if cancelled
  50. *
  51. * Providing the option to also display a "(Deselect)" radiobutton makes the
  52. * "Swap Layers" command (and GerbView's "Export to Pcbnew" command) more "user
  53. * friendly", by permitting any layer to be "deselected" immediately after its
  54. * corresponding radiobutton has been clicked on. (It would otherwise be
  55. * necessary to first cancel the "Select Layer:" dialog box (invoked after a
  56. * different radiobutton is clicked on) prior to then clicking on the "Deselect"
  57. * button provided within the "Swap Layers:" or "Layer selection:" dialog box).
  58. */
  59. {
  60. int layer;
  61. WinEDA_SelLayerFrame* frame =
  62. new WinEDA_SelLayerFrame( this, default_layer, min_layer, max_layer, null_layer );
  63. layer = frame->ShowModal();
  64. frame->Destroy();
  65. return layer;
  66. }
  67. /***********************************************************************/
  68. WinEDA_SelLayerFrame::WinEDA_SelLayerFrame( WinEDA_BasePcbFrame* parent,
  69. int default_layer, int min_layer,
  70. int max_layer, bool null_layer ) :
  71. wxDialog( parent, -1, _("Select Layer:"), wxPoint( -1, -1 ),
  72. wxSize( 470, 250 ),
  73. DIALOG_STYLE )
  74. /***********************************************************************/
  75. /*
  76. * The "OK" and "Cancel" buttons are positioned (in a horizontal line)
  77. * beneath the "Layer" radiobox, unless that contains only one column of
  78. * radiobuttons, in which case they are positioned (in a vertical line)
  79. * to the right of that radiobox.
  80. */
  81. {
  82. BOARD* board = parent->m_Pcb;
  83. wxButton* Button;
  84. int ii;
  85. wxString LayerList[NB_LAYERS + 1]; // One extra element for "(Deselect)" radiobutton
  86. int LayerCount, LayerSelect = -1;
  87. m_Parent = parent;
  88. SetFont( *g_DialogFont );
  89. /* Build the layer list */
  90. LayerCount = 0;
  91. int Masque_Layer = g_TabAllCopperLayerMask[g_DesignSettings.m_CopperLayerCount - 1];
  92. Masque_Layer += ALL_NO_CU_LAYERS;
  93. for( ii = 0; ii < NB_LAYERS; ii++ )
  94. {
  95. m_LayerId[ii] = 0;
  96. if( (g_TabOneLayerMask[ii] & Masque_Layer) )
  97. {
  98. if( min_layer > ii )
  99. continue;
  100. if( (max_layer >= 0) && (max_layer < ii) )
  101. break;
  102. LayerList[LayerCount] = board->GetLayerName( ii );
  103. if( ii == default_layer )
  104. LayerSelect = LayerCount;
  105. m_LayerId[LayerCount] = ii;
  106. LayerCount++;
  107. }
  108. }
  109. // When appropriate, also provide a "(Deselect)" radiobutton
  110. if( null_layer )
  111. {
  112. LayerList[LayerCount] = _( "(Deselect)" );
  113. if( NB_LAYERS == default_layer )
  114. LayerSelect = LayerCount;
  115. m_LayerId[LayerCount] = NB_LAYERS;
  116. LayerCount++;
  117. }
  118. m_LayerList = new wxRadioBox( this, ID_LAYER_SELECT, _("Layer"),
  119. wxPoint( -1, -1 ), wxSize( -1, -1 ), LayerCount, LayerList,
  120. (LayerCount < 8) ? LayerCount : 8, wxRA_SPECIFY_ROWS );
  121. if( LayerSelect >= 0 )
  122. m_LayerList->SetSelection( LayerSelect );
  123. wxBoxSizer* FrameBoxSizer = new wxBoxSizer(wxHORIZONTAL);
  124. SetSizer(FrameBoxSizer);
  125. FrameBoxSizer->Add(m_LayerList, 0, wxALIGN_TOP|wxALL, 5);
  126. wxBoxSizer* ButtonBoxSizer = new wxBoxSizer(wxVERTICAL);
  127. FrameBoxSizer->Add(ButtonBoxSizer, 0, wxALIGN_BOTTOM|wxALL, 0);
  128. Button = new wxButton( this, wxID_OK, _("OK") );
  129. Button->SetForegroundColour( *wxRED );
  130. ButtonBoxSizer->Add(Button, 0, wxGROW|wxALL, 5);
  131. Button = new wxButton( this, wxID_CANCEL, _("Cancel") );
  132. Button->SetForegroundColour( *wxBLUE );
  133. ButtonBoxSizer->Add(Button, 0, wxGROW|wxALL, 5);
  134. if( GetSizer() )
  135. {
  136. GetSizer()->SetSizeHints(this);
  137. }
  138. }
  139. /***************************************************************/
  140. void WinEDA_SelLayerFrame::Sel_Layer( wxCommandEvent& event )
  141. /***************************************************************/
  142. {
  143. int ii = m_LayerId[m_LayerList->GetSelection()];
  144. EndModal( ii );
  145. }
  146. /***************************************************************/
  147. void WinEDA_SelLayerFrame::OnCancelClick( wxCommandEvent& event )
  148. /***************************************************************/
  149. {
  150. EndModal( -1 );
  151. }
  152. /*********************************************************/
  153. /* classe pour la frame de selection de paires de layers */
  154. /*********************************************************/
  155. class WinEDA_SelLayerPairFrame : public wxDialog
  156. {
  157. private:
  158. WinEDA_BasePcbFrame* m_Parent;
  159. wxRadioBox* m_LayerListTOP;
  160. wxRadioBox* m_LayerListBOTTOM;
  161. int m_LayerId[NB_COPPER_LAYERS];
  162. public:
  163. // Constructor and destructor
  164. WinEDA_SelLayerPairFrame( WinEDA_BasePcbFrame* parent );
  165. ~WinEDA_SelLayerPairFrame() { };
  166. private:
  167. void OnOkClick( wxCommandEvent& event );
  168. void OnCancelClick( wxCommandEvent& event );
  169. DECLARE_EVENT_TABLE()
  170. };
  171. /* Table des evenements pour WinEDA_SelLayerPairFrame */
  172. BEGIN_EVENT_TABLE( WinEDA_SelLayerPairFrame, wxDialog )
  173. EVT_BUTTON( wxID_OK, WinEDA_SelLayerPairFrame::OnOkClick )
  174. EVT_BUTTON( wxID_CANCEL, WinEDA_SelLayerPairFrame::OnCancelClick )
  175. END_EVENT_TABLE()
  176. /***********************************************/
  177. void WinEDA_BasePcbFrame::SelectLayerPair()
  178. /***********************************************/
  179. /* Affiche une double liste de layers cuivre pour selection d'une paire de layers
  180. * pour autorutage, vias...
  181. */
  182. {
  183. // Check whether more than one copper layer has been enabled for the
  184. // current PCB file, as Layer Pairs can only meaningfully be defined
  185. // within PCB files which contain at least two copper layers.
  186. if( m_Pcb->m_BoardSettings->m_CopperLayerCount < 2 )
  187. {
  188. wxString InfoMsg;
  189. InfoMsg = _( "Less than two copper layers are being used." );
  190. InfoMsg << wxT( "\n" ) << _( "Hence Layer Pairs cannot be specified." );
  191. DisplayInfo( this, InfoMsg );
  192. return;
  193. }
  194. WinEDA_SelLayerPairFrame* frame =
  195. new WinEDA_SelLayerPairFrame( this );
  196. int result = frame->ShowModal();
  197. frame->Destroy();
  198. DrawPanel->MouseToCursorSchema();
  199. SetToolbars();
  200. // if user changed colors and we are in high contrast mode, then redraw
  201. // because the PAD_SMD pads may change color.
  202. if( result >= 0 && DisplayOpt.ContrastModeDisplay )
  203. {
  204. ReDrawPanel();
  205. }
  206. }
  207. /*******************************************************************************/
  208. WinEDA_SelLayerPairFrame::WinEDA_SelLayerPairFrame( WinEDA_BasePcbFrame* parent ) :
  209. wxDialog( parent, -1, _("Select Layer Pair:"), wxPoint( -1, -1 ),
  210. wxSize( 470, 250 ), DIALOG_STYLE )
  211. /*******************************************************************************/
  212. {
  213. BOARD* board = parent->m_Pcb;
  214. wxButton* Button;
  215. int ii, LayerCount;
  216. wxString LayerList[NB_COPPER_LAYERS];
  217. int LayerTopSelect = 0, LayerBottomSelect = 0;
  218. m_Parent = parent;
  219. SetFont( *g_DialogFont );
  220. PCB_SCREEN* screen = (PCB_SCREEN*) m_Parent->m_CurrentScreen;
  221. /* Construction de la liste des couches autoris�s */
  222. int Masque_Layer = g_TabAllCopperLayerMask[g_DesignSettings.m_CopperLayerCount - 1];
  223. Masque_Layer += ALL_NO_CU_LAYERS;
  224. for( ii = 0, LayerCount = 0; ii < NB_COPPER_LAYERS; ii++ )
  225. {
  226. m_LayerId[ii] = 0;
  227. if( (g_TabOneLayerMask[ii] & Masque_Layer) )
  228. {
  229. LayerList[LayerCount] = board->GetLayerName( ii );
  230. if( ii == screen->m_Route_Layer_TOP )
  231. LayerTopSelect = LayerCount;
  232. if( ii == screen->m_Route_Layer_BOTTOM )
  233. LayerBottomSelect = LayerCount;
  234. m_LayerId[LayerCount] = ii;
  235. LayerCount++;
  236. }
  237. }
  238. m_LayerListTOP = new wxRadioBox( this, ID_LAYER_SELECT_TOP, _("Top Layer"),
  239. wxPoint( -1, -1 ), wxSize( -1, -1 ), LayerCount, LayerList,
  240. (LayerCount < 8) ? LayerCount : 8, wxRA_SPECIFY_ROWS );
  241. m_LayerListTOP->SetSelection( LayerTopSelect );
  242. m_LayerListBOTTOM = new wxRadioBox( this, ID_LAYER_SELECT_BOTTOM, _("Bottom Layer"),
  243. wxPoint( -1, -1 ), wxSize( -1, -1 ), LayerCount, LayerList,
  244. (LayerCount < 8) ? LayerCount : 8, wxRA_SPECIFY_ROWS );
  245. m_LayerListBOTTOM->SetSelection( LayerBottomSelect );
  246. wxBoxSizer* FrameBoxSizer = new wxBoxSizer(wxVERTICAL);
  247. SetSizer(FrameBoxSizer);
  248. wxBoxSizer* RadioBoxSizer = new wxBoxSizer(wxHORIZONTAL);
  249. FrameBoxSizer->Add(RadioBoxSizer, 0, wxALIGN_LEFT|wxALL, 0);
  250. wxBoxSizer* ButtonBoxSizer = new wxBoxSizer(wxHORIZONTAL);
  251. FrameBoxSizer->Add(ButtonBoxSizer, 0, wxALIGN_RIGHT|wxALL, 0);
  252. RadioBoxSizer->Add(m_LayerListTOP, 0, wxALIGN_TOP|wxALL, 5);
  253. RadioBoxSizer->Add(m_LayerListBOTTOM, 0, wxALIGN_TOP|wxALL, 5);
  254. Button = new wxButton( this, wxID_OK, _("OK") );
  255. Button->SetForegroundColour( *wxRED );
  256. ButtonBoxSizer->Add(Button, 0, wxGROW|wxALL, 5);
  257. Button = new wxButton( this, wxID_CANCEL, _("Cancel") );
  258. Button->SetForegroundColour( *wxBLUE );
  259. ButtonBoxSizer->Add(Button, 0, wxGROW|wxALL, 5);
  260. if( GetSizer() )
  261. {
  262. GetSizer()->SetSizeHints(this);
  263. }
  264. }
  265. /***************************************************************/
  266. void WinEDA_SelLayerPairFrame::OnOkClick( wxCommandEvent& event )
  267. /***************************************************************/
  268. {
  269. // Check whether whichever layer has been specified as the "Top"
  270. // layer is really "above" whichever layer has been specified as
  271. // the "Bottom" layer; those values will only be updated (and the
  272. // dialog box subsequently closed) when that condition is met.
  273. // if( m_LayerId[m_LayerListTOP->GetSelection()]
  274. // <= m_LayerId[m_LayerListBOTTOM->GetSelection()] )
  275. // {
  276. // DisplayError( this, _( "The Top Layer must be above the Bottom Layer" ) );
  277. // return;
  278. // }
  279. // Code for previous test commented out because other code now
  280. // transposes the assignment of the Top and Bottom layers if
  281. // the former layer is actually "below" the latter. However,
  282. // it is still desirable to check that those layers differ.
  283. // Check whether whichever layer has been specified as the "Top"
  284. // layer differs from whichever layer has been specified as the
  285. // "Bottom" layer; those values will only be updated (and the
  286. // dialog box subsequently closed) when that condition is met.
  287. if( m_LayerId[m_LayerListTOP->GetSelection()]
  288. == m_LayerId[m_LayerListBOTTOM->GetSelection()] )
  289. {
  290. DisplayError( this, _( "The Top Layer and Bottom Layer must differ" ) );
  291. return;
  292. }
  293. PCB_SCREEN* screen = (PCB_SCREEN*) m_Parent->m_CurrentScreen;
  294. screen->m_Route_Layer_TOP = m_LayerId[m_LayerListTOP->GetSelection()];
  295. screen->m_Route_Layer_BOTTOM = m_LayerId[m_LayerListBOTTOM->GetSelection()];
  296. EndModal( 0 );
  297. }
  298. /***************************************************************/
  299. void WinEDA_SelLayerPairFrame::OnCancelClick( wxCommandEvent& event )
  300. /***************************************************************/
  301. {
  302. EndModal( -1 );
  303. }