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.

384 lines
12 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 <widgets/layer_box_selector.h>
  34. #include <class_board.h>
  35. #include <dialogs/dialog_layer_selection_base.h>
  36. // Column position by function:
  37. #define SELECT_COLNUM 0
  38. #define COLOR_COLNUM 1
  39. #define LAYERNAME_COLNUM 2
  40. /* classes to display a layer list using a wxGrid.
  41. */
  42. class PCB_LAYER_SELECTOR: public LAYER_SELECTOR
  43. {
  44. public:
  45. PCB_LAYER_SELECTOR( PCB_BASE_FRAME* aFrame ) :
  46. LAYER_SELECTOR()
  47. {
  48. m_frame = aFrame;
  49. }
  50. protected:
  51. PCB_BASE_FRAME* m_frame;
  52. // Returns true if the layer id is enabled (i.e. is it should be displayed)
  53. bool IsLayerEnabled( LAYER_NUM aLayer ) const override
  54. {
  55. return m_frame->GetBoard()->IsLayerEnabled( PCB_LAYER_ID( aLayer ) );
  56. }
  57. // Returns a color index from the layer id
  58. // Virtual function
  59. COLOR4D GetLayerColor( LAYER_NUM aLayer ) const override
  60. {
  61. return m_frame->Settings().Colors().GetLayerColor( aLayer );
  62. }
  63. // Returns the name of the layer id
  64. wxString GetLayerName( LAYER_NUM aLayer ) const override
  65. {
  66. return m_frame->GetBoard()->GetLayerName( ToLAYER_ID( aLayer ) );
  67. }
  68. };
  69. /*
  70. * This class display a pcb layers list in a dialog,
  71. * to select one layer from this list
  72. */
  73. class PCB_ONE_LAYER_SELECTOR : public PCB_LAYER_SELECTOR,
  74. public DIALOG_LAYER_SELECTION_BASE
  75. {
  76. PCB_LAYER_ID m_layerSelected;
  77. LSET m_notAllowedLayersMask;
  78. BOARD* m_brd;
  79. std::vector<PCB_LAYER_ID> m_layersIdLeftColumn;
  80. std::vector<PCB_LAYER_ID> m_layersIdRightColumn;
  81. public:
  82. PCB_ONE_LAYER_SELECTOR( PCB_BASE_FRAME* aParent, BOARD * aBrd, PCB_LAYER_ID aDefaultLayer,
  83. LSET aNotAllowedLayersMask );
  84. LAYER_NUM GetLayerSelection() { return m_layerSelected; }
  85. private:
  86. // Event handlers
  87. void OnLeftGridCellClick( wxGridEvent& event ) override;
  88. void OnRightGridCellClick( wxGridEvent& event ) override;
  89. void buildList();
  90. };
  91. PCB_ONE_LAYER_SELECTOR::PCB_ONE_LAYER_SELECTOR( PCB_BASE_FRAME* aParent, BOARD* aBrd,
  92. PCB_LAYER_ID aDefaultLayer,
  93. LSET aNotAllowedLayersMask ) :
  94. PCB_LAYER_SELECTOR( aParent ),
  95. DIALOG_LAYER_SELECTION_BASE( aParent )
  96. {
  97. m_layerSelected = aDefaultLayer;
  98. m_notAllowedLayersMask = aNotAllowedLayersMask;
  99. m_brd = aBrd;
  100. m_leftGridLayers->SetCellHighlightPenWidth( 0 );
  101. m_rightGridLayers->SetCellHighlightPenWidth( 0 );
  102. m_leftGridLayers->SetColFormatBool( SELECT_COLNUM );
  103. m_rightGridLayers->SetColFormatBool( SELECT_COLNUM );
  104. buildList();
  105. Layout();
  106. GetSizer()->SetSizeHints( this );
  107. SetFocus();
  108. }
  109. void PCB_ONE_LAYER_SELECTOR::buildList()
  110. {
  111. wxColour bg = GetLayerColor( LAYER_PCB_BACKGROUND ).ToColour();
  112. int left_row = 0;
  113. int right_row = 0;
  114. wxString layername;
  115. for( LSEQ ui_seq = m_brd->GetEnabledLayers().UIOrder(); ui_seq; ++ui_seq )
  116. {
  117. PCB_LAYER_ID layerid = *ui_seq;
  118. if( m_notAllowedLayersMask[layerid] )
  119. continue;
  120. wxColour fg = GetLayerColor( layerid ).ToColour();
  121. wxColour color( wxColour::AlphaBlend( fg.Red(), bg.Red(), fg.Alpha() / 255.0 ),
  122. wxColour::AlphaBlend( fg.Green(), bg.Green(), fg.Alpha() / 255.0 ),
  123. wxColour::AlphaBlend( fg.Blue(), bg.Blue(), fg.Alpha() / 255.0 ) );
  124. layername = wxT( " " ) + GetLayerName( layerid );
  125. if( IsCopperLayer( layerid ) )
  126. {
  127. if( left_row )
  128. m_leftGridLayers->AppendRows( 1 );
  129. m_leftGridLayers->SetCellBackgroundColour ( left_row, COLOR_COLNUM, color );
  130. m_leftGridLayers->SetCellValue( left_row, LAYERNAME_COLNUM, layername );
  131. if( m_layerSelected == layerid )
  132. m_leftGridLayers->SetCellValue( left_row, SELECT_COLNUM, "1" );
  133. m_layersIdLeftColumn.push_back( layerid );
  134. left_row++;
  135. }
  136. else
  137. {
  138. if( right_row )
  139. m_rightGridLayers->AppendRows( 1 );
  140. m_rightGridLayers->SetCellBackgroundColour( right_row, COLOR_COLNUM, color );
  141. m_rightGridLayers->SetCellValue( right_row, LAYERNAME_COLNUM, layername );
  142. if( m_layerSelected == layerid )
  143. m_rightGridLayers->SetCellValue( right_row, SELECT_COLNUM, "1" );
  144. m_layersIdRightColumn.push_back( layerid );
  145. right_row++;
  146. }
  147. }
  148. // Show only populated lists:
  149. if( left_row <= 0 )
  150. m_leftGridLayers->Show( false );
  151. if( right_row <= 0 )
  152. m_rightGridLayers->Show( false );
  153. }
  154. void PCB_ONE_LAYER_SELECTOR::OnLeftGridCellClick( wxGridEvent& event )
  155. {
  156. m_layerSelected = m_layersIdLeftColumn[ event.GetRow() ];
  157. EndModal( 1 );
  158. }
  159. void PCB_ONE_LAYER_SELECTOR::OnRightGridCellClick( wxGridEvent& event )
  160. {
  161. m_layerSelected = m_layersIdRightColumn[ event.GetRow() ];
  162. EndModal( 2 );
  163. }
  164. PCB_LAYER_ID PCB_BASE_FRAME::SelectLayer( PCB_LAYER_ID aDefaultLayer, LSET aNotAllowedLayersMask,
  165. wxPoint aDlgPosition )
  166. {
  167. PCB_ONE_LAYER_SELECTOR dlg( this, GetBoard(), aDefaultLayer, aNotAllowedLayersMask );
  168. if( aDlgPosition != wxDefaultPosition )
  169. {
  170. wxSize dlgSize = dlg.GetSize();
  171. aDlgPosition.x -= dlgSize.x/2;
  172. aDlgPosition.y -= dlgSize.y/2;
  173. dlg.SetPosition( aDlgPosition );
  174. }
  175. dlg.ShowModal();
  176. PCB_LAYER_ID layer = ToLAYER_ID( dlg.GetLayerSelection() );
  177. return layer;
  178. }
  179. /**
  180. * Class SELECT_COPPER_LAYERS_PAIR_DIALOG
  181. * displays a double pcb copper layers list in a dialog,
  182. * to select a layer pair from these lists
  183. */
  184. class SELECT_COPPER_LAYERS_PAIR_DIALOG: public PCB_LAYER_SELECTOR,
  185. public DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE
  186. {
  187. private:
  188. BOARD* m_brd;
  189. PCB_LAYER_ID m_frontLayer;
  190. PCB_LAYER_ID m_backLayer;
  191. int m_leftRowSelected;
  192. int m_rightRowSelected;
  193. std::vector<PCB_LAYER_ID> m_layersId;
  194. public:
  195. SELECT_COPPER_LAYERS_PAIR_DIALOG( PCB_BASE_FRAME* aParent, BOARD* aPcb,
  196. PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer );
  197. void GetLayerPair( PCB_LAYER_ID& aFrontLayer, PCB_LAYER_ID& aBackLayer )
  198. {
  199. aFrontLayer = m_frontLayer;
  200. aBackLayer = m_backLayer;
  201. }
  202. private:
  203. void OnLeftGridCellClick( wxGridEvent& event ) override;
  204. void OnRightGridCellClick( wxGridEvent& event ) override;
  205. void buildList();
  206. };
  207. void PCB_BASE_FRAME::SelectCopperLayerPair()
  208. {
  209. PCB_SCREEN* screen = GetScreen();
  210. SELECT_COPPER_LAYERS_PAIR_DIALOG dlg( this, GetBoard(),
  211. screen->m_Route_Layer_TOP,
  212. screen->m_Route_Layer_BOTTOM );
  213. if( dlg.ShowModal() == wxID_OK )
  214. {
  215. dlg.GetLayerPair( screen->m_Route_Layer_TOP, screen->m_Route_Layer_BOTTOM );
  216. // select the same layer for both layers is allowed (normal in some boards)
  217. // but could be a mistake. So display an info message
  218. if( screen->m_Route_Layer_TOP == screen->m_Route_Layer_BOTTOM )
  219. DisplayInfoMessage( this, _( "Warning: top and bottom layers are same." ) );
  220. }
  221. m_canvas->MoveCursorToCrossHair();
  222. }
  223. SELECT_COPPER_LAYERS_PAIR_DIALOG::SELECT_COPPER_LAYERS_PAIR_DIALOG(
  224. PCB_BASE_FRAME* aParent, BOARD * aPcb, PCB_LAYER_ID aFrontLayer, PCB_LAYER_ID aBackLayer) :
  225. PCB_LAYER_SELECTOR( aParent ),
  226. DIALOG_COPPER_LAYER_PAIR_SELECTION_BASE( aParent )
  227. {
  228. m_frontLayer = aFrontLayer;
  229. m_backLayer = aBackLayer;
  230. m_leftRowSelected = 0;
  231. m_rightRowSelected = 0;
  232. m_brd = aPcb;
  233. m_leftGridLayers->SetCellHighlightPenWidth( 0 );
  234. m_rightGridLayers->SetCellHighlightPenWidth( 0 );
  235. m_leftGridLayers->SetColFormatBool( SELECT_COLNUM );
  236. m_rightGridLayers->SetColFormatBool( SELECT_COLNUM );
  237. buildList();
  238. SetFocus();
  239. GetSizer()->SetSizeHints( this );
  240. Center();
  241. }
  242. void SELECT_COPPER_LAYERS_PAIR_DIALOG::buildList()
  243. {
  244. wxColour bg = GetLayerColor( LAYER_PCB_BACKGROUND ).ToColour();
  245. int row = 0;
  246. wxString layername;
  247. for( LSEQ ui_seq = m_brd->GetEnabledLayers().UIOrder(); ui_seq; ++ui_seq )
  248. {
  249. PCB_LAYER_ID layerid = *ui_seq;
  250. if( !IsCopperLayer( layerid ) )
  251. continue;
  252. wxColour fg = GetLayerColor( layerid ).ToColour();
  253. wxColour color( wxColour::AlphaBlend( fg.Red(), bg.Red(), fg.Alpha() / 255.0 ),
  254. wxColour::AlphaBlend( fg.Green(), bg.Green(), fg.Alpha() / 255.0 ),
  255. wxColour::AlphaBlend( fg.Blue(), bg.Blue(), fg.Alpha() / 255.0 ) );
  256. layername = wxT( " " ) + GetLayerName( layerid );
  257. if( row )
  258. m_leftGridLayers->AppendRows( 1 );
  259. m_leftGridLayers->SetCellBackgroundColour( row, COLOR_COLNUM, color );
  260. m_leftGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername );
  261. m_layersId.push_back( layerid );
  262. if( m_frontLayer == layerid )
  263. {
  264. m_leftGridLayers->SetCellValue( row, SELECT_COLNUM, "1" );
  265. m_leftGridLayers->SetGridCursor( row, COLOR_COLNUM );
  266. m_leftRowSelected = row;
  267. }
  268. if( row )
  269. m_rightGridLayers->AppendRows( 1 );
  270. m_rightGridLayers->SetCellBackgroundColour( row, COLOR_COLNUM, color );
  271. m_rightGridLayers->SetCellValue( row, LAYERNAME_COLNUM, layername );
  272. if( m_backLayer == layerid )
  273. {
  274. m_rightGridLayers->SetCellValue( row, SELECT_COLNUM, "1" );
  275. m_rightRowSelected = row;
  276. }
  277. row++;
  278. }
  279. }
  280. void SELECT_COPPER_LAYERS_PAIR_DIALOG::OnLeftGridCellClick( wxGridEvent& event )
  281. {
  282. int row = event.GetRow();
  283. PCB_LAYER_ID layer = m_layersId[row];
  284. if( m_frontLayer == layer )
  285. return;
  286. m_leftGridLayers->SetCellValue( m_leftRowSelected, SELECT_COLNUM, wxEmptyString );
  287. m_frontLayer = layer;
  288. m_leftRowSelected = row;
  289. m_leftGridLayers->SetCellValue( m_leftRowSelected, SELECT_COLNUM, "1" );
  290. }
  291. void SELECT_COPPER_LAYERS_PAIR_DIALOG::OnRightGridCellClick( wxGridEvent& event )
  292. {
  293. int row = event.GetRow();
  294. PCB_LAYER_ID layer = m_layersId[row];
  295. if( m_backLayer == layer )
  296. return;
  297. m_rightGridLayers->SetCellValue( m_rightRowSelected, SELECT_COLNUM, wxEmptyString );
  298. m_backLayer = layer;
  299. m_rightRowSelected = row;
  300. m_rightGridLayers->SetCellValue( m_rightRowSelected, SELECT_COLNUM, "1" );
  301. }