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.

430 lines
14 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2004-2010 Jean-Pierre Charras, jp.charras at wanadoo.fr
  5. * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
  6. * Copyright (C) 2018-2023 KiCad Developers, see AUTHORS.txt for contributors.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, you may find one here:
  20. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  21. * or you may search the http://www.gnu.org website for the version 2 license,
  22. * or you may write to the Free Software Foundation, Inc.,
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  24. */
  25. #include <wx/checkbox.h>
  26. #include <wx/filedlg.h>
  27. #include <bitmaps.h>
  28. #include <menus_helpers.h>
  29. #include <gerbview.h>
  30. #include "gerbview_draw_panel_gal.h"
  31. #include <gerbview_frame.h>
  32. #include <gerber_file_image_list.h>
  33. #include <core/arraydim.h>
  34. #include <view/view.h>
  35. #include <gerbview_painter.h>
  36. #include <gal/graphics_abstraction_layer.h>
  37. #include <settings/settings_manager.h>
  38. #include <tool/tool_manager.h>
  39. #include <tools/gerbview_actions.h>
  40. #include "layer_widget.h"
  41. #include "gbr_layer_box_selector.h"
  42. #include "gerbview_layer_widget.h"
  43. #include "dcode_selection_box.h"
  44. GERBER_LAYER_WIDGET::GERBER_LAYER_WIDGET( GERBVIEW_FRAME* aParent, wxWindow* aFocusOwner ) :
  45. LAYER_WIDGET( aParent, aFocusOwner ),
  46. m_frame( aParent )
  47. {
  48. m_alwaysShowActiveLayer = false;
  49. ReFillRender();
  50. // Update default tabs labels for GerbView
  51. SetLayersManagerTabsText( );
  52. // handle the popup menu over the layer window.
  53. m_LayerScrolledWindow->Connect( wxEVT_RIGHT_DOWN,
  54. wxMouseEventHandler( GERBER_LAYER_WIDGET::onRightDownLayers ),
  55. nullptr, this );
  56. // since Popupmenu() calls this->ProcessEvent() we must call this->Connect()
  57. // and not m_LayerScrolledWindow->Connect()
  58. Connect( ID_LAYER_MANAGER_START, ID_LAYER_MANAGER_END, wxEVT_COMMAND_MENU_SELECTED,
  59. wxCommandEventHandler( GERBER_LAYER_WIDGET::onPopupSelection ), nullptr, this );
  60. }
  61. GERBER_FILE_IMAGE_LIST* GERBER_LAYER_WIDGET::GetImagesList()
  62. {
  63. return &GERBER_FILE_IMAGE_LIST::GetImagesList();
  64. }
  65. void GERBER_LAYER_WIDGET::SetLayersManagerTabsText()
  66. {
  67. m_notebook->SetPageText( 0, _( "Layers" ) );
  68. m_notebook->SetPageText( 1, _( "Items" ) );
  69. }
  70. void GERBER_LAYER_WIDGET::CollectCurrentColorSettings( COLOR_SETTINGS* aColorSettings )
  71. {
  72. std::vector<int>render_layers{ LAYER_DCODES, LAYER_NEGATIVE_OBJECTS, LAYER_GERBVIEW_GRID,
  73. LAYER_GERBVIEW_DRAWINGSHEET, LAYER_GERBVIEW_PAGE_LIMITS,
  74. LAYER_GERBVIEW_BACKGROUND };
  75. for( int layer: render_layers )
  76. {
  77. int row = findRenderRow( layer );
  78. if( row < 0 )
  79. continue;
  80. COLOR4D color = GetRenderColor( row );
  81. if( color != COLOR4D::UNSPECIFIED )
  82. aColorSettings->SetColor( layer, color );
  83. }
  84. for( int layer = GERBVIEW_LAYER_ID_START; layer < GERBVIEW_LAYER_ID_START + GERBER_DRAWLAYERS_COUNT; layer++ )
  85. {
  86. int row = findLayerRow( layer - GERBVIEW_LAYER_ID_START );
  87. if( row < 0 ) // Not existing in layer list
  88. continue;
  89. COLOR4D color = GetLayerColor( row );
  90. if( color != COLOR4D::UNSPECIFIED )
  91. aColorSettings->SetColor( layer, color );
  92. }
  93. }
  94. void GERBER_LAYER_WIDGET::ReFillRender()
  95. {
  96. ClearRenderRows();
  97. // Fixed "Rendering" tab rows within the LAYER_WIDGET, only the initial color
  98. // is changed before appending to the LAYER_WIDGET. This is an automatic variable
  99. // not a static variable, change the color & state after copying from code to renderRows
  100. // on the stack.
  101. LAYER_WIDGET::ROW renderRows[7] = {
  102. #define RR LAYER_WIDGET::ROW // Render Row abbreviation to reduce source width
  103. RR( _( "DCodes" ), LAYER_DCODES, WHITE,
  104. _( "Show DCodes identification" ) ),
  105. RR( _( "Negative Objects" ), LAYER_NEGATIVE_OBJECTS, DARKGRAY,
  106. _( "Show negative objects in this color" ) ),
  107. RR(),
  108. RR( _( "Grid" ), LAYER_GERBVIEW_GRID, WHITE,
  109. _( "Show the (x,y) grid dots" ) ),
  110. RR( _( "Drawing Sheet" ), LAYER_GERBVIEW_DRAWINGSHEET, DARKRED,
  111. _( "Show drawing sheet border and title block") ),
  112. RR( _( "Page Limits" ), LAYER_GERBVIEW_PAGE_LIMITS, WHITE,
  113. _( "Show drawing sheet page limits" ) ),
  114. RR( _( "Background" ), LAYER_GERBVIEW_BACKGROUND, BLACK,
  115. _( "PCB Background" ), true, false )
  116. };
  117. for( unsigned row = 0; row < arrayDim( renderRows ); ++row )
  118. {
  119. if( renderRows[row].color != COLOR4D::UNSPECIFIED ) // does this row show a color?
  120. renderRows[row].color = m_frame->GetVisibleElementColor( renderRows[row].id );
  121. if( renderRows[row].id ) // if not the separator
  122. renderRows[row].state = m_frame->IsElementVisible( renderRows[row].id );
  123. }
  124. AppendRenderRows( renderRows, arrayDim(renderRows) );
  125. }
  126. void GERBER_LAYER_WIDGET::AddRightClickMenuItems( wxMenu* aMenu )
  127. {
  128. // Remember: menu text is capitalized (see our rules_for_capitalization_in_Kicad_UI.txt)
  129. KIUI::AddMenuItem( aMenu, ID_SHOW_ALL_LAYERS, _( "Show All Layers" ),
  130. KiBitmap( BITMAPS::show_all_layers ) );
  131. KIUI::AddMenuItem( aMenu, ID_SHOW_NO_LAYERS_BUT_ACTIVE, _( "Hide All Layers But Active" ),
  132. KiBitmap( BITMAPS::select_w_layer ) );
  133. KIUI::AddMenuItem( aMenu, ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE,
  134. _( "Always Hide All Layers But Active" ),
  135. KiBitmap( BITMAPS::select_w_layer ) );
  136. KIUI::AddMenuItem( aMenu, ID_SHOW_NO_LAYERS, _( "Hide All Layers" ),
  137. KiBitmap( BITMAPS::show_no_layers ) );
  138. aMenu->AppendSeparator();
  139. KIUI::AddMenuItem( aMenu, ID_SORT_GBR_LAYERS_X2, _( "Sort Layers if X2 Mode" ),
  140. KiBitmap( BITMAPS::reload ) );
  141. KIUI::AddMenuItem( aMenu, ID_SORT_GBR_LAYERS_FILE_EXT, _( "Sort Layers by File Extension" ),
  142. KiBitmap( BITMAPS::reload ) );
  143. aMenu->AppendSeparator();
  144. KIUI::AddMenuItem( aMenu, ID_SET_GBR_LAYERS_DRAW_PRMS,
  145. _( "Layers Display Parameters: Offset and Rotation" ),
  146. KiBitmap( BITMAPS::tools ) );
  147. aMenu->AppendSeparator();
  148. KIUI::AddMenuItem( aMenu, ID_LAYER_MOVE_UP, _( "Move Current Layer Up" ),
  149. KiBitmap( BITMAPS::up ) );
  150. KIUI::AddMenuItem( aMenu, ID_LAYER_MOVE_DOWN, _( "Move Current Layer Down" ),
  151. KiBitmap( BITMAPS::down ) );
  152. KIUI::AddMenuItem( aMenu, ID_LAYER_DELETE, _( "Clear Current Layer..." ),
  153. KiBitmap( BITMAPS::delete_gerber ) );
  154. }
  155. void GERBER_LAYER_WIDGET::onRightDownLayers( wxMouseEvent& event )
  156. {
  157. wxMenu menu;
  158. AddRightClickMenuItems( &menu );
  159. PopupMenu( &menu );
  160. passOnFocus();
  161. }
  162. void GERBER_LAYER_WIDGET::onPopupSelection( wxCommandEvent& event )
  163. {
  164. int layer;
  165. int rowCount;
  166. int menuId = event.GetId();
  167. bool visible = (menuId == ID_SHOW_ALL_LAYERS) ? true : false;
  168. LSET visibleLayers;
  169. bool force_active_layer_visible;
  170. switch( menuId )
  171. {
  172. case ID_SHOW_ALL_LAYERS:
  173. case ID_SHOW_NO_LAYERS:
  174. case ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE:
  175. case ID_SHOW_NO_LAYERS_BUT_ACTIVE:
  176. // Set the display layers options. Sorting layers has no effect to these options
  177. m_alwaysShowActiveLayer = ( menuId == ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE );
  178. force_active_layer_visible = ( menuId == ID_SHOW_NO_LAYERS_BUT_ACTIVE ||
  179. menuId == ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE );
  180. // Update icons and check boxes
  181. rowCount = GetLayerRowCount();
  182. for( int row = 0; row < rowCount; ++row )
  183. {
  184. wxCheckBox* cb = (wxCheckBox*) getLayerComp( row, COLUMN_COLOR_LYR_CB );
  185. layer = getDecodedId( cb->GetId() );
  186. bool loc_visible = visible;
  187. if( force_active_layer_visible && (layer == m_frame->GetActiveLayer() ) )
  188. loc_visible = true;
  189. cb->SetValue( loc_visible );
  190. visibleLayers[ row ] = loc_visible;
  191. }
  192. m_frame->SetVisibleLayers( visibleLayers );
  193. m_frame->GetCanvas()->Refresh();
  194. break;
  195. case ID_SORT_GBR_LAYERS_X2:
  196. m_frame->SortLayersByX2Attributes();
  197. break;
  198. case ID_SORT_GBR_LAYERS_FILE_EXT:
  199. m_frame->SortLayersByFileExtension();
  200. break;
  201. case ID_SET_GBR_LAYERS_DRAW_PRMS:
  202. m_frame->SetLayerDrawPrms();
  203. break;
  204. case ID_LAYER_MOVE_UP:
  205. m_frame->GetToolManager()->RunAction( GERBVIEW_ACTIONS::moveLayerUp );
  206. break;
  207. case ID_LAYER_MOVE_DOWN:
  208. m_frame->GetToolManager()->RunAction( GERBVIEW_ACTIONS::moveLayerDown );
  209. break;
  210. case ID_LAYER_DELETE:
  211. m_frame->Erase_Current_DrawLayer( false );
  212. break;
  213. }
  214. }
  215. bool GERBER_LAYER_WIDGET::OnLayerSelected()
  216. {
  217. if( !m_alwaysShowActiveLayer )
  218. return false;
  219. // postprocess after active layer selection ensure active layer visible
  220. wxCommandEvent event;
  221. event.SetId( ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE );
  222. onPopupSelection( event );
  223. return true;
  224. }
  225. void GERBER_LAYER_WIDGET::ReFill()
  226. {
  227. ClearLayerRows();
  228. Freeze();
  229. for( int layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer )
  230. {
  231. // Don't show inactive layers
  232. if ( GetImagesList()->GetGbrImage(layer) == nullptr )
  233. continue;
  234. int aRow = findLayerRow( layer );
  235. bool visible = true;
  236. COLOR4D color = m_frame->GetLayerColor( GERBER_DRAW_LAYER( layer ) );
  237. wxString msg = GetImagesList()->GetDisplayName( layer,
  238. /* include layer number */ false,
  239. /* Get the full name */ true );
  240. if( m_frame->GetCanvas() )
  241. visible = m_frame->GetCanvas()->GetView()->IsLayerVisible( GERBER_DRAW_LAYER( layer ) );
  242. else
  243. visible = m_frame->IsLayerVisible( layer );
  244. if( aRow >= 0 )
  245. {
  246. updateLayerRow( findLayerRow( layer ), msg );
  247. SetLayerVisible( layer, visible );
  248. }
  249. else
  250. {
  251. AppendLayerRow( LAYER_WIDGET::ROW( msg, layer, color, wxEmptyString, visible, true ) );
  252. }
  253. }
  254. UpdateLayouts();
  255. Thaw();
  256. }
  257. void GERBER_LAYER_WIDGET::OnLayerRightClick( wxMenu& aMenu )
  258. {
  259. AddRightClickMenuItems( &aMenu );
  260. }
  261. void GERBER_LAYER_WIDGET::OnLayerColorChange( int aLayer, const COLOR4D& aColor )
  262. {
  263. // NOTE: Active layer in GerbView is stored as 0-indexed, but layer color is
  264. // stored according to the GERBER_DRAW_LAYER() offset.
  265. m_frame->SetLayerColor( GERBER_DRAW_LAYER( aLayer ), aColor );
  266. m_frame->m_SelLayerBox->ResyncBitmapOnly();
  267. KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
  268. COLOR_SETTINGS* color_settings = m_frame->GetColorSettings();
  269. color_settings->SetColor( aLayer, aColor );
  270. view->GetPainter()->GetSettings()->LoadColors( color_settings );
  271. view->UpdateLayerColor( GERBER_DRAW_LAYER( aLayer ) );
  272. m_frame->GetCanvas()->Refresh();
  273. }
  274. bool GERBER_LAYER_WIDGET::OnLayerSelect( int aLayer )
  275. {
  276. // the layer change from the GERBER_LAYER_WIDGET can be denied by returning
  277. // false from this function.
  278. int layer = m_frame->GetActiveLayer();
  279. m_frame->SetActiveLayer( aLayer, false );
  280. m_frame->syncLayerBox();
  281. if( layer != m_frame->GetActiveLayer() )
  282. {
  283. if( ! OnLayerSelected() )
  284. {
  285. auto settings = static_cast<KIGFX::GERBVIEW_PAINTER*>
  286. ( m_frame->GetCanvas()->GetView()->GetPainter() )->GetSettings();
  287. int dcodeSelected = m_frame->m_DCodeSelector->GetSelectedDCodeId();
  288. settings->m_dcodeHighlightValue = dcodeSelected;
  289. m_frame->GetCanvas()->GetView()->UpdateAllItems( KIGFX::COLOR );
  290. m_frame->GetCanvas()->Refresh();
  291. }
  292. }
  293. return true;
  294. }
  295. void GERBER_LAYER_WIDGET::OnLayerVisible( int aLayer, bool isVisible, bool isFinal )
  296. {
  297. LSET visibleLayers = m_frame->GetVisibleLayers();
  298. visibleLayers[ aLayer ] = isVisible;
  299. m_frame->SetVisibleLayers( visibleLayers );
  300. if( isFinal )
  301. m_frame->GetCanvas()->Refresh();
  302. }
  303. void GERBER_LAYER_WIDGET::OnRenderColorChange( int aId, const COLOR4D& aColor )
  304. {
  305. m_frame->SetVisibleElementColor( aId, aColor );
  306. auto view = m_frame->GetCanvas()->GetView();
  307. COLOR_SETTINGS* color_settings = m_frame->GetColorSettings();
  308. color_settings->SetColor( aId, aColor );
  309. view->GetPainter()->GetSettings()->LoadColors( color_settings );
  310. view->UpdateLayerColor( aId );
  311. view->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
  312. view->UpdateAllItems( KIGFX::COLOR );
  313. m_frame->GetCanvas()->Refresh();
  314. }
  315. void GERBER_LAYER_WIDGET::OnRenderEnable( int aId, bool isEnabled )
  316. {
  317. m_frame->SetElementVisibility( aId, isEnabled );
  318. if( m_frame->GetCanvas() )
  319. {
  320. if( aId == LAYER_GERBVIEW_GRID )
  321. {
  322. m_frame->GetCanvas()->GetGAL()->SetGridVisibility( m_frame->IsGridVisible() );
  323. m_frame->GetCanvas()->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
  324. }
  325. else
  326. {
  327. m_frame->GetCanvas()->GetView()->SetLayerVisible( aId, isEnabled );
  328. }
  329. }
  330. m_frame->GetCanvas()->Refresh();
  331. }