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.

432 lines
13 KiB

  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 <pcb_base_frame.h>
  33. #include <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( PCB_BASE_FRAME* aFrame ) :
  42. LAYER_SELECTOR()
  43. {
  44. m_frame = aFrame;
  45. }
  46. protected:
  47. PCB_BASE_FRAME* m_frame;
  48. // Returns true if the layer id is enabled (i.e. is it should be displayed)
  49. bool IsLayerEnabled( LAYER_NUM aLayer ) const override
  50. {
  51. return m_frame->GetBoard()->IsLayerEnabled( PCB_LAYER_ID( aLayer ) );
  52. }
  53. // Returns a color index from the layer id
  54. // Virtual function
  55. COLOR4D GetLayerColor( LAYER_NUM aLayer ) const override
  56. {
  57. return m_frame->Settings().Colors().GetLayerColor( ToLAYER_ID( aLayer ) );
  58. }
  59. // Returns the name of the layer id
  60. wxString GetLayerName( LAYER_NUM aLayer ) const override
  61. {
  62. return m_frame->GetBoard()->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. PCB_LAYER_ID m_layerSelected;
  73. LSET m_notAllowedLayersMask;
  74. BOARD* m_brd;
  75. std::vector<PCB_LAYER_ID> m_layersIdLeftColumn;
  76. std::vector<PCB_LAYER_ID> m_layersIdRightColumn;
  77. public:
  78. PCB_ONE_LAYER_SELECTOR( PCB_BASE_FRAME* aParent, BOARD * aBrd,
  79. PCB_LAYER_ID aDefaultLayer,
  80. LSET aNotAllowedLayersMask );
  81. LAYER_NUM GetLayerSelection() { return m_layerSelected; }
  82. private:
  83. // Event handlers
  84. void OnLeftGridCellClick( wxGridEvent& event ) override;
  85. void OnRightGridCellClick( wxGridEvent& event ) override;
  86. void buildList();
  87. };
  88. PCB_ONE_LAYER_SELECTOR::PCB_ONE_LAYER_SELECTOR( PCB_BASE_FRAME* aParent,
  89. BOARD* aBrd, PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask )
  90. : PCB_LAYER_SELECTOR( aParent ), DIALOG_LAYER_SELECTION_BASE( aParent )
  91. {
  92. m_layerSelected = aDefaultLayer;
  93. m_notAllowedLayersMask = aNotAllowedLayersMask;
  94. m_brd = aBrd;
  95. buildList();
  96. Layout();
  97. GetSizer()->SetSizeHints( this );
  98. SetFocus();
  99. }
  100. // Build the layers list
  101. // Column position by function:
  102. #define SELECT_COLNUM 0
  103. #define COLOR_COLNUM 1
  104. #define LAYERNAME_COLNUM 2
  105. void PCB_ONE_LAYER_SELECTOR::buildList()
  106. {
  107. // Hide layerid column which is used only to know the layer id
  108. // not to be shown in dialogs
  109. m_leftGridLayers->SetColSize( COLOR_COLNUM, 20 );
  110. m_rightGridLayers->SetColSize( COLOR_COLNUM, 20 );
  111. int left_row = 0;
  112. int right_row = 0;
  113. wxString layername;
  114. for( LSEQ ui_seq = m_brd->GetEnabledLayers().UIOrder(); ui_seq; ++ui_seq )
  115. {
  116. PCB_LAYER_ID layerid = *ui_seq;
  117. if( m_notAllowedLayersMask[layerid] )
  118. continue;
  119. COLOR4D color = GetLayerColor( layerid );
  120. layername = GetLayerName( layerid );
  121. if( IsCopperLayer( layerid ) )
  122. {
  123. if( left_row )
  124. m_leftGridLayers->AppendRows( 1 );
  125. m_leftGridLayers->SetCellBackgroundColour ( left_row, COLOR_COLNUM,
  126. color.ToColour() );
  127. m_leftGridLayers->SetCellValue( left_row, LAYERNAME_COLNUM,
  128. layername );
  129. if( m_layerSelected == layerid )
  130. {
  131. m_leftGridLayers->SetCellValue( left_row, SELECT_COLNUM,
  132. wxT("X") );
  133. m_leftGridLayers->SetCellBackgroundColour ( left_row, SELECT_COLNUM,
  134. color.ToColour() );
  135. m_leftGridLayers->SetGridCursor( left_row, LAYERNAME_COLNUM );
  136. }
  137. m_layersIdLeftColumn.push_back( layerid );
  138. left_row++;
  139. }
  140. else
  141. {
  142. if( right_row )
  143. m_rightGridLayers->AppendRows( 1 );
  144. m_rightGridLayers->SetCellBackgroundColour ( right_row, COLOR_COLNUM,
  145. color.ToColour() );
  146. m_rightGridLayers->SetCellValue( right_row, LAYERNAME_COLNUM,
  147. layername );
  148. if( m_layerSelected == layerid )
  149. {
  150. m_rightGridLayers->SetCellValue( right_row, SELECT_COLNUM,
  151. wxT("X") );
  152. m_rightGridLayers->SetCellBackgroundColour ( right_row, SELECT_COLNUM,
  153. color.ToColour() );
  154. m_rightGridLayers->SetGridCursor( right_row, LAYERNAME_COLNUM );
  155. }
  156. m_layersIdRightColumn.push_back( layerid );
  157. right_row++;
  158. }
  159. }
  160. // Show only populated lists:
  161. if( left_row <= 0 )
  162. m_leftGridLayers->Show( false );
  163. if( right_row <= 0 )
  164. m_rightGridLayers->Show( false );
  165. m_leftGridLayers->AutoSizeColumn(LAYERNAME_COLNUM);
  166. m_rightGridLayers->AutoSizeColumn(LAYERNAME_COLNUM);
  167. m_leftGridLayers->AutoSizeColumn(SELECT_COLNUM);
  168. m_rightGridLayers->AutoSizeColumn(SELECT_COLNUM);
  169. }
  170. void PCB_ONE_LAYER_SELECTOR::OnLeftGridCellClick( wxGridEvent& event )
  171. {
  172. m_layerSelected = m_layersIdLeftColumn[ event.GetRow() ];
  173. m_leftGridLayers->SetGridCursor( event.GetRow(), LAYERNAME_COLNUM );
  174. EndModal( 1 );
  175. }
  176. void PCB_ONE_LAYER_SELECTOR::OnRightGridCellClick( wxGridEvent& event )
  177. {
  178. m_layerSelected = m_layersIdRightColumn[ event.GetRow() ];
  179. m_rightGridLayers->SetGridCursor( event.GetRow(), LAYERNAME_COLNUM );
  180. EndModal( 2 );
  181. }
  182. PCB_LAYER_ID PCB_BASE_FRAME::SelectLayer( PCB_LAYER_ID aDefaultLayer,
  183. LSET aNotAllowedLayersMask, wxPoint aDlgPosition )
  184. {
  185. PCB_ONE_LAYER_SELECTOR dlg( this, GetBoard(), aDefaultLayer, aNotAllowedLayersMask );
  186. if( aDlgPosition != wxDefaultPosition )
  187. {
  188. wxSize dlgSize = dlg.GetSize();
  189. aDlgPosition.x -= dlgSize.x/2;
  190. aDlgPosition.y -= dlgSize.y/2;
  191. dlg.SetPosition( aDlgPosition );
  192. }
  193. dlg.ShowModal();
  194. PCB_LAYER_ID layer = ToLAYER_ID( dlg.GetLayerSelection() );
  195. return layer;
  196. }
  197. /**
  198. * Class SELECT_COPPER_LAYERS_PAIR_DIALOG
  199. * displays a double pcb copper layers list in a dialog,
  200. * to select a layer pair from these lists
  201. */
  202. class SELECT_COPPER_LAYERS_PAIR_DIALOG: public PCB_LAYER_SELECTOR,
  203. public DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE
  204. {
  205. private:
  206. BOARD* m_brd;
  207. PCB_LAYER_ID m_frontLayer;
  208. PCB_LAYER_ID m_backLayer;
  209. int m_leftRowSelected;
  210. int m_rightRowSelected;
  211. std::vector<PCB_LAYER_ID> m_layersId;
  212. public:
  213. SELECT_COPPER_LAYERS_PAIR_DIALOG( PCB_BASE_FRAME* aParent, BOARD* aPcb,
  214. PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer );
  215. void GetLayerPair( PCB_LAYER_ID& aFrontLayer, PCB_LAYER_ID& aBackLayer )
  216. {
  217. aFrontLayer = m_frontLayer;
  218. aBackLayer = m_backLayer;
  219. }
  220. private:
  221. void OnLeftGridCellClick( wxGridEvent& event ) override;
  222. void OnRightGridCellClick( wxGridEvent& event ) override;
  223. void OnOkClick( wxCommandEvent& event )
  224. {
  225. EndModal( wxID_OK );
  226. }
  227. void OnCancelClick( wxCommandEvent& event ) override
  228. {
  229. EndModal( wxID_CANCEL );
  230. }
  231. void buildList();
  232. void SetGridCursor( wxGrid* aGrid, int aRow, bool aEnable );
  233. };
  234. void PCB_BASE_FRAME::SelectCopperLayerPair()
  235. {
  236. PCB_SCREEN* screen = GetScreen();
  237. SELECT_COPPER_LAYERS_PAIR_DIALOG dlg( this, GetBoard(),
  238. screen->m_Route_Layer_TOP,
  239. screen->m_Route_Layer_BOTTOM );
  240. if( dlg.ShowModal() == wxID_OK )
  241. {
  242. dlg.GetLayerPair( screen->m_Route_Layer_TOP, screen->m_Route_Layer_BOTTOM );
  243. // select the same layer for both layers is allowed (normal in some boards)
  244. // but could be a mistake. So display an info message
  245. if( screen->m_Route_Layer_TOP == screen->m_Route_Layer_BOTTOM )
  246. DisplayInfoMessage( this,
  247. _( "Warning: The Top Layer and Bottom Layer are same." ) );
  248. }
  249. m_canvas->MoveCursorToCrossHair();
  250. }
  251. SELECT_COPPER_LAYERS_PAIR_DIALOG::SELECT_COPPER_LAYERS_PAIR_DIALOG(
  252. PCB_BASE_FRAME* aParent, BOARD * aPcb, PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer) :
  253. PCB_LAYER_SELECTOR( aParent ),
  254. DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE( aParent )
  255. {
  256. m_frontLayer = aFrontLayer;
  257. m_backLayer = aBackLayer;
  258. m_leftRowSelected = 0;
  259. m_rightRowSelected = 0;
  260. m_brd = aPcb;
  261. buildList();
  262. SetFocus();
  263. GetSizer()->SetSizeHints( this );
  264. Center();
  265. }
  266. void SELECT_COPPER_LAYERS_PAIR_DIALOG::buildList()
  267. {
  268. m_leftGridLayers->SetColSize( COLOR_COLNUM, 20 );
  269. m_rightGridLayers->SetColSize( COLOR_COLNUM, 20 );
  270. // Select a not show cell, to avoid a wrong cell selection for user
  271. int row = 0;
  272. wxString layername;
  273. for( LSEQ ui_seq = m_brd->GetEnabledLayers().UIOrder(); ui_seq; ++ui_seq )
  274. {
  275. PCB_LAYER_ID layerid = *ui_seq;
  276. if( !IsCopperLayer( layerid ) )
  277. break;
  278. COLOR4D color = GetLayerColor( layerid );
  279. layername = GetLayerName( layerid );
  280. if( row )
  281. m_leftGridLayers->AppendRows( 1 );
  282. m_leftGridLayers->SetCellBackgroundColour( row, COLOR_COLNUM, color.ToColour() );
  283. m_leftGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername );
  284. m_layersId.push_back( layerid );
  285. if( m_frontLayer == layerid )
  286. {
  287. SetGridCursor( m_leftGridLayers, row, true );
  288. m_leftRowSelected = row;
  289. }
  290. if( row )
  291. m_rightGridLayers->AppendRows( 1 );
  292. m_rightGridLayers->SetCellBackgroundColour ( row, COLOR_COLNUM,
  293. color.ToColour() );
  294. m_rightGridLayers->SetCellValue( row, LAYERNAME_COLNUM,
  295. layername );
  296. if( m_backLayer == layerid )
  297. {
  298. SetGridCursor( m_rightGridLayers, row, true );
  299. m_rightRowSelected = row;
  300. }
  301. row++;
  302. }
  303. m_leftGridLayers->AutoSizeColumn(LAYERNAME_COLNUM);
  304. m_rightGridLayers->AutoSizeColumn(LAYERNAME_COLNUM);
  305. m_leftGridLayers->AutoSizeColumn(SELECT_COLNUM);
  306. m_rightGridLayers->AutoSizeColumn(SELECT_COLNUM);
  307. }
  308. void SELECT_COPPER_LAYERS_PAIR_DIALOG::SetGridCursor( wxGrid* aGrid, int aRow,
  309. bool aEnable )
  310. {
  311. if( aEnable )
  312. {
  313. PCB_LAYER_ID layerid = m_layersId[aRow];
  314. COLOR4D color = GetLayerColor( layerid );
  315. aGrid->SetCellValue( aRow, SELECT_COLNUM, wxT("X") );
  316. aGrid->SetCellBackgroundColour( aRow, SELECT_COLNUM, color.ToColour() );
  317. aGrid->SetGridCursor( aRow, LAYERNAME_COLNUM );
  318. }
  319. else
  320. {
  321. aGrid->SetCellValue( aRow, SELECT_COLNUM, wxEmptyString );
  322. aGrid->SetCellBackgroundColour( aRow, SELECT_COLNUM,
  323. aGrid->GetDefaultCellBackgroundColour() );
  324. aGrid->SetGridCursor( aRow, LAYERNAME_COLNUM );
  325. }
  326. }
  327. void SELECT_COPPER_LAYERS_PAIR_DIALOG::OnLeftGridCellClick( wxGridEvent& event )
  328. {
  329. int row = event.GetRow();
  330. PCB_LAYER_ID layer = m_layersId[row];
  331. if( m_frontLayer == layer )
  332. return;
  333. SetGridCursor( m_leftGridLayers, m_leftRowSelected, false );
  334. m_frontLayer = layer;
  335. m_leftRowSelected = row;
  336. SetGridCursor( m_leftGridLayers, m_leftRowSelected, true );
  337. }
  338. void SELECT_COPPER_LAYERS_PAIR_DIALOG::OnRightGridCellClick( wxGridEvent& event )
  339. {
  340. int row = event.GetRow();
  341. PCB_LAYER_ID layer = m_layersId[row];
  342. if( m_backLayer == layer )
  343. return;
  344. SetGridCursor( m_rightGridLayers, m_rightRowSelected, false );
  345. m_backLayer = layer;
  346. m_rightRowSelected = row;
  347. SetGridCursor( m_rightGridLayers, m_rightRowSelected, true );
  348. }