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.

429 lines
13 KiB

12 years ago
12 years ago
12 years ago
  1. /**
  2. * @file sel_layer.cpp
  3. * @brief dialogs for one layer selection and a layer pair selection.
  4. */
  5. /*
  6. * This program source code file is part of KiCad, a free EDA CAD application.
  7. *
  8. * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
  9. * Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors.
  10. *
  11. * This program is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU General Public License
  13. * as published by the Free Software Foundation; either version 2
  14. * of the License, or (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, you may find one here:
  23. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  24. * or you may search the http://www.gnu.org website for the version 2 license,
  25. * or you may write to the Free Software Foundation, Inc.,
  26. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  27. */
  28. #include <fctsys.h>
  29. #include <common.h>
  30. #include <class_drawpanel.h>
  31. #include <confirm.h>
  32. #include <wxBasePcbFrame.h>
  33. #include <class_layer_box_selector.h>
  34. #include <class_board.h>
  35. #include <dialogs/dialog_layer_selection_base.h>
  36. /* classes to display a layer list using a wxGrid.
  37. */
  38. class PCB_LAYER_SELECTOR: public LAYER_SELECTOR
  39. {
  40. public:
  41. PCB_LAYER_SELECTOR( BOARD* aBrd ) :
  42. LAYER_SELECTOR()
  43. {
  44. m_brd = aBrd;
  45. }
  46. protected:
  47. BOARD* m_brd;
  48. // Returns true if the layer id is enabled (i.e. is it should be displayed)
  49. bool IsLayerEnabled( LAYER_NUM aLayer ) const
  50. {
  51. return m_brd->IsLayerEnabled( LAYER_ID( aLayer ) );
  52. }
  53. // Returns a color index from the layer id
  54. // Virtual function
  55. EDA_COLOR_T GetLayerColor( LAYER_NUM aLayer ) const
  56. {
  57. return m_brd->GetLayerColor( ToLAYER_ID( aLayer ) );
  58. }
  59. // Returns the name of the layer id
  60. wxString GetLayerName( LAYER_NUM aLayer ) const // overrides LAYER_SELECTOR
  61. {
  62. return m_brd->GetLayerName( ToLAYER_ID( aLayer ) );
  63. }
  64. };
  65. /*
  66. * This class display a pcb layers list in a dialog,
  67. * to select one layer from this list
  68. */
  69. class PCB_ONE_LAYER_SELECTOR : public PCB_LAYER_SELECTOR,
  70. public DIALOG_LAYER_SELECTION_BASE
  71. {
  72. LAYER_ID m_layerSelected;
  73. LSET m_notAllowedLayersMask;
  74. std::vector<LAYER_ID> m_layersIdLeftColumn;
  75. std::vector<LAYER_ID> m_layersIdRightColumn;
  76. public:
  77. PCB_ONE_LAYER_SELECTOR( wxWindow* aParent, BOARD * aBrd,
  78. LAYER_ID aDefaultLayer,
  79. LSET aNotAllowedLayersMask );
  80. LAYER_NUM GetLayerSelection() { return m_layerSelected; }
  81. private:
  82. // Event handlers
  83. void OnLeftGridCellClick( wxGridEvent& event );
  84. void OnRightGridCellClick( wxGridEvent& event );
  85. void buildList();
  86. };
  87. PCB_ONE_LAYER_SELECTOR::PCB_ONE_LAYER_SELECTOR( wxWindow* aParent,
  88. BOARD* aBrd, LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask )
  89. : PCB_LAYER_SELECTOR( aBrd ), DIALOG_LAYER_SELECTION_BASE( aParent )
  90. {
  91. m_layerSelected = aDefaultLayer;
  92. m_notAllowedLayersMask = aNotAllowedLayersMask;
  93. buildList();
  94. Layout();
  95. GetSizer()->SetSizeHints( this );
  96. SetFocus();
  97. }
  98. // Build the layers list
  99. // Column position by function:
  100. #define SELECT_COLNUM 0
  101. #define COLOR_COLNUM 1
  102. #define LAYERNAME_COLNUM 2
  103. void PCB_ONE_LAYER_SELECTOR::buildList()
  104. {
  105. // Hide layerid column which is used only to know the layer id
  106. // not to be shown in dialogs
  107. m_leftGridLayers->SetColSize( COLOR_COLNUM, 20 );
  108. m_rightGridLayers->SetColSize( COLOR_COLNUM, 20 );
  109. int left_row = 0;
  110. int right_row = 0;
  111. wxString layername;
  112. for( LSEQ ui_seq = m_brd->GetEnabledLayers().UIOrder(); ui_seq; ++ui_seq )
  113. {
  114. LAYER_ID layerid = *ui_seq;
  115. if( m_notAllowedLayersMask[layerid] )
  116. continue;
  117. wxColour color = MakeColour( GetLayerColor( layerid ) );
  118. layername = GetLayerName( layerid );
  119. if( IsCopperLayer( layerid ) )
  120. {
  121. if( left_row )
  122. m_leftGridLayers->AppendRows( 1 );
  123. m_leftGridLayers->SetCellBackgroundColour ( left_row, COLOR_COLNUM,
  124. color );
  125. m_leftGridLayers->SetCellValue( left_row, LAYERNAME_COLNUM,
  126. layername );
  127. if( m_layerSelected == layerid )
  128. {
  129. m_leftGridLayers->SetCellValue( left_row, SELECT_COLNUM,
  130. wxT("X") );
  131. m_leftGridLayers->SetCellBackgroundColour ( left_row, SELECT_COLNUM,
  132. color );
  133. m_leftGridLayers->SetGridCursor( left_row, LAYERNAME_COLNUM );
  134. }
  135. m_layersIdLeftColumn.push_back( layerid );
  136. left_row++;
  137. }
  138. else
  139. {
  140. if( right_row )
  141. m_rightGridLayers->AppendRows( 1 );
  142. m_rightGridLayers->SetCellBackgroundColour ( right_row, COLOR_COLNUM,
  143. color );
  144. m_rightGridLayers->SetCellValue( right_row, LAYERNAME_COLNUM,
  145. layername );
  146. if( m_layerSelected == layerid )
  147. {
  148. m_rightGridLayers->SetCellValue( right_row, SELECT_COLNUM,
  149. wxT("X") );
  150. m_rightGridLayers->SetCellBackgroundColour ( right_row, SELECT_COLNUM,
  151. color );
  152. m_rightGridLayers->SetGridCursor( right_row, LAYERNAME_COLNUM );
  153. }
  154. m_layersIdRightColumn.push_back( layerid );
  155. right_row++;
  156. }
  157. }
  158. // Show only populated lists:
  159. if( left_row <= 0 )
  160. m_leftGridLayers->Show( false );
  161. if( right_row <= 0 )
  162. m_rightGridLayers->Show( false );
  163. m_leftGridLayers->AutoSizeColumn(LAYERNAME_COLNUM);
  164. m_rightGridLayers->AutoSizeColumn(LAYERNAME_COLNUM);
  165. m_leftGridLayers->AutoSizeColumn(SELECT_COLNUM);
  166. m_rightGridLayers->AutoSizeColumn(SELECT_COLNUM);
  167. }
  168. void PCB_ONE_LAYER_SELECTOR::OnLeftGridCellClick( wxGridEvent& event )
  169. {
  170. m_layerSelected = m_layersIdLeftColumn[ event.GetRow() ];
  171. m_leftGridLayers->SetGridCursor( event.GetRow(), LAYERNAME_COLNUM );
  172. EndModal( 1 );
  173. }
  174. void PCB_ONE_LAYER_SELECTOR::OnRightGridCellClick( wxGridEvent& event )
  175. {
  176. m_layerSelected = m_layersIdRightColumn[ event.GetRow() ];
  177. m_rightGridLayers->SetGridCursor( event.GetRow(), LAYERNAME_COLNUM );
  178. EndModal( 2 );
  179. }
  180. LAYER_ID PCB_BASE_FRAME::SelectLayer( LAYER_ID aDefaultLayer,
  181. LSET aNotAllowedLayersMask, wxPoint aDlgPosition )
  182. {
  183. PCB_ONE_LAYER_SELECTOR dlg( this, GetBoard(), aDefaultLayer, aNotAllowedLayersMask );
  184. if( aDlgPosition != wxDefaultPosition )
  185. {
  186. wxSize dlgSize = dlg.GetSize();
  187. aDlgPosition.x -= dlgSize.x/2;
  188. aDlgPosition.y -= dlgSize.y/2;
  189. dlg.SetPosition( aDlgPosition );
  190. }
  191. dlg.ShowModal();
  192. LAYER_ID layer = ToLAYER_ID( dlg.GetLayerSelection() );
  193. return layer;
  194. }
  195. /**
  196. * Class SELECT_COPPER_LAYERS_PAIR_DIALOG
  197. * displays a double pcb copper layers list in a dialog,
  198. * to select a layer pair from these lists
  199. */
  200. class SELECT_COPPER_LAYERS_PAIR_DIALOG: public PCB_LAYER_SELECTOR,
  201. public DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE
  202. {
  203. private:
  204. LAYER_ID m_frontLayer;
  205. LAYER_ID m_backLayer;
  206. int m_leftRowSelected;
  207. int m_rightRowSelected;
  208. std::vector<LAYER_ID> m_layersId;
  209. public:
  210. SELECT_COPPER_LAYERS_PAIR_DIALOG( wxWindow* aParent, BOARD* aPcb,
  211. LAYER_ID aFrontLayer, LAYER_ID aBackLayer );
  212. void GetLayerPair( LAYER_ID& aFrontLayer, LAYER_ID& aBackLayer )
  213. {
  214. aFrontLayer = m_frontLayer;
  215. aBackLayer = m_backLayer;
  216. }
  217. private:
  218. void OnLeftGridCellClick( wxGridEvent& event );
  219. void OnRightGridCellClick( wxGridEvent& event );
  220. void OnOkClick( wxCommandEvent& event )
  221. {
  222. EndModal( wxID_OK );
  223. }
  224. void OnCancelClick( wxCommandEvent& event )
  225. {
  226. EndModal( wxID_CANCEL );
  227. }
  228. void buildList();
  229. void SetGridCursor( wxGrid* aGrid, int aRow, bool aEnable );
  230. };
  231. void PCB_BASE_FRAME::SelectCopperLayerPair()
  232. {
  233. PCB_SCREEN* screen = GetScreen();
  234. SELECT_COPPER_LAYERS_PAIR_DIALOG dlg( this, GetBoard(),
  235. screen->m_Route_Layer_TOP,
  236. screen->m_Route_Layer_BOTTOM );
  237. if( dlg.ShowModal() == wxID_OK )
  238. {
  239. dlg.GetLayerPair( screen->m_Route_Layer_TOP, screen->m_Route_Layer_BOTTOM );
  240. // select the same layer for both layers is allowed (normal in some boards)
  241. // but could be a mistake. So display an info message
  242. if( screen->m_Route_Layer_TOP == screen->m_Route_Layer_BOTTOM )
  243. DisplayInfoMessage( this,
  244. _( "Warning: The Top Layer and Bottom Layer are same." ) );
  245. }
  246. m_canvas->MoveCursorToCrossHair();
  247. }
  248. SELECT_COPPER_LAYERS_PAIR_DIALOG::SELECT_COPPER_LAYERS_PAIR_DIALOG(
  249. wxWindow* aParent, BOARD * aPcb, LAYER_ID aFrontLayer, LAYER_ID aBackLayer) :
  250. PCB_LAYER_SELECTOR( aPcb ),
  251. DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE( aParent )
  252. {
  253. m_frontLayer = aFrontLayer;
  254. m_backLayer = aBackLayer;
  255. m_leftRowSelected = 0;
  256. m_rightRowSelected = 0;
  257. buildList();
  258. SetFocus();
  259. GetSizer()->SetSizeHints( this );
  260. Center();
  261. }
  262. void SELECT_COPPER_LAYERS_PAIR_DIALOG::buildList()
  263. {
  264. m_leftGridLayers->SetColSize( COLOR_COLNUM, 20 );
  265. m_rightGridLayers->SetColSize( COLOR_COLNUM, 20 );
  266. // Select a not show cell, to avoid a wrong cell selection for user
  267. int row = 0;
  268. wxString layername;
  269. for( LSEQ ui_seq = m_brd->GetEnabledLayers().UIOrder(); ui_seq; ++ui_seq )
  270. {
  271. LAYER_ID layerid = *ui_seq;
  272. if( !IsCopperLayer( layerid ) )
  273. break;
  274. wxColour color = MakeColour( GetLayerColor( layerid ) );
  275. layername = GetLayerName( layerid );
  276. if( row )
  277. m_leftGridLayers->AppendRows( 1 );
  278. m_leftGridLayers->SetCellBackgroundColour( row, COLOR_COLNUM, color );
  279. m_leftGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername );
  280. m_layersId.push_back( layerid );
  281. if( m_frontLayer == layerid )
  282. {
  283. SetGridCursor( m_leftGridLayers, row, true );
  284. m_leftRowSelected = row;
  285. }
  286. if( row )
  287. m_rightGridLayers->AppendRows( 1 );
  288. m_rightGridLayers->SetCellBackgroundColour ( row, COLOR_COLNUM,
  289. color );
  290. m_rightGridLayers->SetCellValue( row, LAYERNAME_COLNUM,
  291. layername );
  292. if( m_backLayer == layerid )
  293. {
  294. SetGridCursor( m_rightGridLayers, row, true );
  295. m_rightRowSelected = row;
  296. }
  297. row++;
  298. }
  299. m_leftGridLayers->AutoSizeColumn(LAYERNAME_COLNUM);
  300. m_rightGridLayers->AutoSizeColumn(LAYERNAME_COLNUM);
  301. m_leftGridLayers->AutoSizeColumn(SELECT_COLNUM);
  302. m_rightGridLayers->AutoSizeColumn(SELECT_COLNUM);
  303. }
  304. void SELECT_COPPER_LAYERS_PAIR_DIALOG::SetGridCursor( wxGrid* aGrid, int aRow,
  305. bool aEnable )
  306. {
  307. if( aEnable )
  308. {
  309. LAYER_ID layerid = m_layersId[aRow];
  310. wxColour color = MakeColour( GetLayerColor( layerid ) );
  311. aGrid->SetCellValue( aRow, SELECT_COLNUM, wxT("X") );
  312. aGrid->SetCellBackgroundColour( aRow, SELECT_COLNUM, color );
  313. aGrid->SetGridCursor( aRow, LAYERNAME_COLNUM );
  314. }
  315. else
  316. {
  317. aGrid->SetCellValue( aRow, SELECT_COLNUM, wxEmptyString );
  318. aGrid->SetCellBackgroundColour( aRow, SELECT_COLNUM,
  319. aGrid->GetDefaultCellBackgroundColour() );
  320. aGrid->SetGridCursor( aRow, LAYERNAME_COLNUM );
  321. }
  322. }
  323. void SELECT_COPPER_LAYERS_PAIR_DIALOG::OnLeftGridCellClick( wxGridEvent& event )
  324. {
  325. int row = event.GetRow();
  326. LAYER_ID layer = m_layersId[row];
  327. if( m_frontLayer == layer )
  328. return;
  329. SetGridCursor( m_leftGridLayers, m_leftRowSelected, false );
  330. m_frontLayer = layer;
  331. m_leftRowSelected = row;
  332. SetGridCursor( m_leftGridLayers, m_leftRowSelected, true );
  333. }
  334. void SELECT_COPPER_LAYERS_PAIR_DIALOG::OnRightGridCellClick( wxGridEvent& event )
  335. {
  336. int row = event.GetRow();
  337. LAYER_ID layer = m_layersId[row];
  338. if( m_backLayer == layer )
  339. return;
  340. SetGridCursor( m_rightGridLayers, m_rightRowSelected, false );
  341. m_backLayer = layer;
  342. m_rightRowSelected = row;
  343. SetGridCursor( m_rightGridLayers, m_rightRowSelected, true );
  344. }