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.

347 lines
12 KiB

8 years ago
  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-2021 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 <bitmaps.h>
  26. #include <menus_helpers.h>
  27. #include <gerbview.h>
  28. #include <gerbview_frame.h>
  29. #include <gerber_file_image_list.h>
  30. #include <core/arraydim.h>
  31. #include <view/view.h>
  32. #include <gerbview_painter.h>
  33. #include <gal/graphics_abstraction_layer.h>
  34. #include <settings/settings_manager.h>
  35. #include "layer_widget.h"
  36. #include "gbr_layer_box_selector.h"
  37. #include "gerbview_layer_widget.h"
  38. #include "dcode_selection_box.h"
  39. /*
  40. * GERBER_LAYER_WIDGET
  41. * is here to implement the abtract functions of LAYER_WIDGET so they
  42. * may be tied into the GERBVIEW_FRAME's data and so we can add a popup
  43. * menu which is specific to Pcbnew's needs.
  44. */
  45. GERBER_LAYER_WIDGET::GERBER_LAYER_WIDGET( GERBVIEW_FRAME* aParent, wxWindow* aFocusOwner ) :
  46. LAYER_WIDGET( aParent, aFocusOwner ),
  47. myframe( aParent )
  48. {
  49. m_alwaysShowActiveLayer = false;
  50. ReFillRender();
  51. // Update default tabs labels for GerbView
  52. SetLayersManagerTabsText( );
  53. //-----<Popup menu>-------------------------------------------------
  54. // handle the popup menu over the layer window.
  55. m_LayerScrolledWindow->Connect( wxEVT_RIGHT_DOWN,
  56. wxMouseEventHandler( GERBER_LAYER_WIDGET::onRightDownLayers ), NULL, this );
  57. // since Popupmenu() calls this->ProcessEvent() we must call this->Connect()
  58. // and not m_LayerScrolledWindow->Connect()
  59. Connect( ID_LAYER_MANAGER_START, ID_LAYER_MANAGER_END,
  60. wxEVT_COMMAND_MENU_SELECTED,
  61. wxCommandEventHandler( GERBER_LAYER_WIDGET::onPopupSelection ), NULL, this );
  62. }
  63. GERBER_FILE_IMAGE_LIST* GERBER_LAYER_WIDGET::GetImagesList()
  64. {
  65. return &GERBER_FILE_IMAGE_LIST::GetImagesList();
  66. }
  67. void GERBER_LAYER_WIDGET::SetLayersManagerTabsText( )
  68. {
  69. m_notebook->SetPageText(0, _("Layers") );
  70. m_notebook->SetPageText(1, _("Items") );
  71. }
  72. /**
  73. * Function ReFillRender
  74. * Rebuild Render for instance after the config is read
  75. */
  76. void GERBER_LAYER_WIDGET::ReFillRender()
  77. {
  78. ClearRenderRows();
  79. // Fixed "Rendering" tab rows within the LAYER_WIDGET, only the initial color
  80. // is changed before appending to the LAYER_WIDGET. This is an automatic variable
  81. // not a static variable, change the color & state after copying from code to renderRows
  82. // on the stack.
  83. LAYER_WIDGET::ROW renderRows[6] = {
  84. #define RR LAYER_WIDGET::ROW // Render Row abreviation to reduce source width
  85. // text id color tooltip checked
  86. RR( _( "DCodes" ), LAYER_DCODES, WHITE, _( "Show DCodes identification" ) ),
  87. RR( _( "Negative Objects" ), LAYER_NEGATIVE_OBJECTS, DARKGRAY, _( "Show negative objects in this color" ) ),
  88. RR(),
  89. RR( _( "Grid" ), LAYER_GERBVIEW_GRID, WHITE, _( "Show the (x,y) grid dots" ) ),
  90. RR( _( "Drawing Sheet" ), LAYER_GERBVIEW_DRAWINGSHEET, DARKRED, _( "Show drawing sheet border and title block") ),
  91. RR( _( "Background" ), LAYER_GERBVIEW_BACKGROUND, BLACK, _( "PCB Background" ), true, false )
  92. };
  93. for( unsigned row=0; row<arrayDim(renderRows); ++row )
  94. {
  95. if( renderRows[row].color != COLOR4D::UNSPECIFIED ) // does this row show a color?
  96. renderRows[row].color = myframe->GetVisibleElementColor( renderRows[row].id );
  97. if( renderRows[row].id ) // if not the separator
  98. renderRows[row].state = myframe->IsElementVisible( renderRows[row].id );
  99. }
  100. AppendRenderRows( renderRows, arrayDim(renderRows) );
  101. }
  102. void GERBER_LAYER_WIDGET::AddRightClickMenuItems( wxMenu* aMenu )
  103. {
  104. // Remember: menu text is capitalized (see our rules_for_capitalization_in_Kicad_UI.txt)
  105. AddMenuItem( aMenu, ID_SHOW_ALL_LAYERS, _( "Show All Layers" ),
  106. KiBitmap( BITMAPS::show_all_layers ) );
  107. AddMenuItem( aMenu, ID_SHOW_NO_LAYERS_BUT_ACTIVE,
  108. _( "Hide All Layers But Active" ),
  109. KiBitmap( BITMAPS::select_w_layer ) );
  110. AddMenuItem( aMenu, ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE,
  111. _( "Always Hide All Layers But Active" ),
  112. KiBitmap( BITMAPS::select_w_layer ) );
  113. AddMenuItem( aMenu, ID_SHOW_NO_LAYERS, _( "Hide All Layers" ),
  114. KiBitmap( BITMAPS::show_no_layers ) );
  115. aMenu->AppendSeparator();
  116. AddMenuItem( aMenu, ID_SORT_GBR_LAYERS, _( "Sort Layers if X2 Mode" ),
  117. KiBitmap( BITMAPS::reload ) );
  118. }
  119. void GERBER_LAYER_WIDGET::onRightDownLayers( wxMouseEvent& event )
  120. {
  121. wxMenu menu;
  122. AddRightClickMenuItems( &menu );
  123. PopupMenu( &menu );
  124. passOnFocus();
  125. }
  126. void GERBER_LAYER_WIDGET::onPopupSelection( wxCommandEvent& event )
  127. {
  128. int rowCount;
  129. int menuId = event.GetId();
  130. bool visible = (menuId == ID_SHOW_ALL_LAYERS) ? true : false;
  131. LSET visibleLayers;
  132. bool force_active_layer_visible;
  133. switch( menuId )
  134. {
  135. case ID_SHOW_ALL_LAYERS:
  136. case ID_SHOW_NO_LAYERS:
  137. case ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE:
  138. case ID_SHOW_NO_LAYERS_BUT_ACTIVE:
  139. // Set the display layers options. Sorting layers has no effect to these options
  140. m_alwaysShowActiveLayer = ( menuId == ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE );
  141. force_active_layer_visible = ( menuId == ID_SHOW_NO_LAYERS_BUT_ACTIVE ||
  142. menuId == ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE );
  143. // Update icons and check boxes
  144. rowCount = GetLayerRowCount();
  145. for( int row = 0; row < rowCount; ++row )
  146. {
  147. wxCheckBox* cb = (wxCheckBox*) getLayerComp( row, COLUMN_COLOR_LYR_CB );
  148. int layer = getDecodedId( cb->GetId() );
  149. bool loc_visible = visible;
  150. if( force_active_layer_visible && (layer == myframe->GetActiveLayer() ) )
  151. loc_visible = true;
  152. cb->SetValue( loc_visible );
  153. visibleLayers[ row ] = loc_visible;
  154. }
  155. myframe->SetVisibleLayers( visibleLayers );
  156. myframe->GetCanvas()->Refresh();
  157. break;
  158. case ID_SORT_GBR_LAYERS:
  159. myframe->SortLayersByX2Attributes();
  160. break;
  161. }
  162. }
  163. bool GERBER_LAYER_WIDGET::OnLayerSelected()
  164. {
  165. if( !m_alwaysShowActiveLayer )
  166. return false;
  167. // postprocess after active layer selection
  168. // ensure active layer visible
  169. wxCommandEvent event;
  170. event.SetId( ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE );
  171. onPopupSelection( event );
  172. return true;
  173. }
  174. void GERBER_LAYER_WIDGET::ReFill()
  175. {
  176. Freeze();
  177. for( int layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer )
  178. {
  179. int aRow = findLayerRow( layer );
  180. bool visible = true;
  181. COLOR4D color = myframe->GetLayerColor( GERBER_DRAW_LAYER( layer ) );
  182. wxString msg = GetImagesList()->GetDisplayName( layer );
  183. if( myframe->GetCanvas() )
  184. visible = myframe->GetCanvas()->GetView()->IsLayerVisible( GERBER_DRAW_LAYER( layer ) );
  185. else
  186. visible = myframe->IsLayerVisible( layer );
  187. if( aRow >= 0 )
  188. updateLayerRow( findLayerRow( layer ), msg );
  189. else
  190. AppendLayerRow( LAYER_WIDGET::ROW( msg, layer, color, wxEmptyString, visible, true ) );
  191. }
  192. UpdateLayouts();
  193. Thaw();
  194. }
  195. //-----<LAYER_WIDGET callbacks>-------------------------------------------
  196. void GERBER_LAYER_WIDGET::OnLayerRightClick( wxMenu& aMenu )
  197. {
  198. AddRightClickMenuItems( &aMenu );
  199. }
  200. void GERBER_LAYER_WIDGET::OnLayerColorChange( int aLayer, COLOR4D aColor )
  201. {
  202. // NOTE: Active layer in GerbView is stored as 0-indexed, but layer color is
  203. // stored according to the GERBER_DRAW_LAYER() offset.
  204. myframe->SetLayerColor( GERBER_DRAW_LAYER( aLayer ), aColor );
  205. myframe->m_SelLayerBox->ResyncBitmapOnly();
  206. KIGFX::VIEW* view = myframe->GetCanvas()->GetView();
  207. auto settings = Pgm().GetSettingsManager().GetColorSettings();
  208. view->GetPainter()->GetSettings()->LoadColors( settings );
  209. view->UpdateLayerColor( GERBER_DRAW_LAYER( aLayer ) );
  210. myframe->GetCanvas()->Refresh();
  211. }
  212. bool GERBER_LAYER_WIDGET::OnLayerSelect( int aLayer )
  213. {
  214. // the layer change from the GERBER_LAYER_WIDGET can be denied by returning
  215. // false from this function.
  216. int layer = myframe->GetActiveLayer();
  217. myframe->SetActiveLayer( aLayer, false );
  218. myframe->syncLayerBox();
  219. if( layer != myframe->GetActiveLayer() )
  220. {
  221. if( ! OnLayerSelected() )
  222. {
  223. auto settings = static_cast<KIGFX::GERBVIEW_PAINTER*>
  224. ( myframe->GetCanvas()->GetView()->GetPainter() )->GetSettings();
  225. int dcodeSelected = myframe->m_DCodeSelector->GetSelectedDCodeId();
  226. settings->m_dcodeHighlightValue = dcodeSelected;
  227. myframe->GetCanvas()->GetView()->UpdateAllItems( KIGFX::COLOR );
  228. myframe->GetCanvas()->Refresh();
  229. }
  230. }
  231. return true;
  232. }
  233. void GERBER_LAYER_WIDGET::OnLayerVisible( int aLayer, bool isVisible, bool isFinal )
  234. {
  235. LSET visibleLayers = myframe->GetVisibleLayers();
  236. visibleLayers[ aLayer ] = isVisible;
  237. myframe->SetVisibleLayers( visibleLayers );
  238. if( isFinal )
  239. myframe->GetCanvas()->Refresh();
  240. }
  241. #include "gerbview_draw_panel_gal.h"
  242. void GERBER_LAYER_WIDGET::OnRenderColorChange( int aId, COLOR4D aColor )
  243. {
  244. myframe->SetVisibleElementColor( aId, aColor );
  245. auto view = myframe->GetCanvas()->GetView();
  246. COLOR_SETTINGS* settings = Pgm().GetSettingsManager().GetColorSettings();
  247. view->GetPainter()->GetSettings()->LoadColors( settings );
  248. view->UpdateLayerColor( aId );
  249. view->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
  250. view->UpdateAllItems( KIGFX::COLOR );
  251. myframe->GetCanvas()->Refresh();
  252. }
  253. void GERBER_LAYER_WIDGET::OnRenderEnable( int aId, bool isEnabled )
  254. {
  255. myframe->SetElementVisibility( aId, isEnabled );
  256. if( myframe->GetCanvas() )
  257. {
  258. if( aId == LAYER_GERBVIEW_GRID )
  259. {
  260. myframe->GetCanvas()->GetGAL()->SetGridVisibility( myframe->IsGridVisible() );
  261. myframe->GetCanvas()->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
  262. }
  263. else
  264. myframe->GetCanvas()->GetView()->SetLayerVisible( aId, isEnabled );
  265. }
  266. myframe->GetCanvas()->Refresh();
  267. }
  268. //-----</LAYER_WIDGET callbacks>------------------------------------------
  269. /*
  270. * Virtual Function useAlternateBitmap
  271. * return true if bitmaps shown in Render layer list
  272. * must be alternate bitmap (when a gerber image is loaded), or false to use "normal" bitmap
  273. */
  274. bool GERBER_LAYER_WIDGET::useAlternateBitmap(int aRow)
  275. {
  276. return GetImagesList()->GetGbrImage( aRow ) != NULL;
  277. }