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.

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