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.

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