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.

316 lines
10 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) 2016 KiCad Developers, see change_log.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. /**
  26. * @file class_gerbview_layer_widget.cpp
  27. * @brief GerbView layers manager.
  28. */
  29. #include <fctsys.h>
  30. #include <common.h>
  31. #include <class_drawpanel.h>
  32. #include <macros.h>
  33. #include <class_gbr_layer_box_selector.h>
  34. #include <gerbview.h>
  35. #include <gerbview_frame.h>
  36. #include <class_gerber_file_image_list.h>
  37. #include <layer_widget.h>
  38. #include <class_gerbview_layer_widget.h>
  39. /*
  40. * Class 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. int aPointSize ) :
  47. LAYER_WIDGET( aParent, aFocusOwner, aPointSize ),
  48. myframe( aParent )
  49. {
  50. m_alwaysShowActiveLayer = false;
  51. ReFillRender();
  52. // Update default tabs labels for GerbView
  53. SetLayersManagerTabsText( );
  54. //-----<Popup menu>-------------------------------------------------
  55. // handle the popup menu over the layer window.
  56. m_LayerScrolledWindow->Connect( wxEVT_RIGHT_DOWN,
  57. wxMouseEventHandler( GERBER_LAYER_WIDGET::onRightDownLayers ), NULL, this );
  58. // since Popupmenu() calls this->ProcessEvent() we must call this->Connect()
  59. // and not m_LayerScrolledWindow->Connect()
  60. Connect( ID_LAYER_MANAGER_START, ID_LAYER_MANAGER_END,
  61. wxEVT_COMMAND_MENU_SELECTED,
  62. wxCommandEventHandler( GERBER_LAYER_WIDGET::onPopupSelection ), NULL, this );
  63. // install the right click handler into each control at end of ReFill()
  64. // using installRightLayerClickHandler
  65. }
  66. GERBER_FILE_IMAGE_LIST* GERBER_LAYER_WIDGET::GetImagesList()
  67. {
  68. return &GERBER_FILE_IMAGE_LIST::GetImagesList();
  69. }
  70. void GERBER_LAYER_WIDGET::SetLayersManagerTabsText( )
  71. {
  72. m_notebook->SetPageText(0, _("Layer") );
  73. m_notebook->SetPageText(1, _("Render") );
  74. }
  75. /**
  76. * Function ReFillRender
  77. * Rebuild Render for instance after the config is read
  78. */
  79. void GERBER_LAYER_WIDGET::ReFillRender()
  80. {
  81. ClearRenderRows();
  82. // Fixed "Rendering" tab rows within the LAYER_WIDGET, only the initial color
  83. // is changed before appending to the LAYER_WIDGET. This is an automatic variable
  84. // not a static variable, change the color & state after copying from code to renderRows
  85. // on the stack.
  86. LAYER_WIDGET::ROW renderRows[3] = {
  87. #define RR LAYER_WIDGET::ROW // Render Row abreviation to reduce source width
  88. // text id color tooltip checked
  89. RR( _( "Grid" ), LAYER_GERBVIEW_GRID, WHITE, _( "Show the (x,y) grid dots" ) ),
  90. RR( _( "DCodes" ), LAYER_DCODES, WHITE, _( "Show DCodes identification" ) ),
  91. RR( _( "Neg. Obj." ), LAYER_NEGATIVE_OBJECTS, DARKGRAY,
  92. _( "Show negative objects in this color" ) ),
  93. };
  94. for( unsigned row=0; row<DIM(renderRows); ++row )
  95. {
  96. if( renderRows[row].color != COLOR4D::UNSPECIFIED ) // does this row show a color?
  97. {
  98. renderRows[row].color = myframe->GetVisibleElementColor(
  99. ( GERBVIEW_LAYER_ID )renderRows[row].id );
  100. }
  101. renderRows[row].state = myframe->IsElementVisible(
  102. ( GERBVIEW_LAYER_ID )renderRows[row].id );
  103. }
  104. AppendRenderRows( renderRows, DIM(renderRows) );
  105. }
  106. void GERBER_LAYER_WIDGET::installRightLayerClickHandler()
  107. {
  108. int rowCount = GetLayerRowCount();
  109. for( int row=0; row<rowCount; ++row )
  110. {
  111. for( int col=0; col<LYR_COLUMN_COUNT; ++col )
  112. {
  113. wxWindow* w = getLayerComp( row, col );
  114. w->Connect( wxEVT_RIGHT_DOWN, wxMouseEventHandler(
  115. GERBER_LAYER_WIDGET::onRightDownLayers ), NULL, this );
  116. }
  117. }
  118. }
  119. void GERBER_LAYER_WIDGET::onRightDownLayers( wxMouseEvent& event )
  120. {
  121. wxMenu menu;
  122. // Remember: menu text is capitalized (see our rules_for_capitalization_in_Kicad_UI.txt)
  123. menu.Append( new wxMenuItem( &menu, ID_SHOW_ALL_LAYERS,
  124. _("Show All Layers") ) );
  125. menu.Append( new wxMenuItem( &menu, ID_SHOW_NO_LAYERS_BUT_ACTIVE,
  126. _( "Hide All Layers But Active" ) ) );
  127. menu.Append( new wxMenuItem( &menu, ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE,
  128. _( "Always Hide All Layers But Active" ) ) );
  129. menu.Append( new wxMenuItem( &menu, ID_SHOW_NO_LAYERS,
  130. _( "Hide All Layers" ) ) );
  131. menu.AppendSeparator();
  132. menu.Append( new wxMenuItem( &menu, ID_SORT_GBR_LAYERS,
  133. _( "Sort Layers if X2 Mode" ) ) );
  134. PopupMenu( &menu );
  135. passOnFocus();
  136. }
  137. void GERBER_LAYER_WIDGET::onPopupSelection( wxCommandEvent& event )
  138. {
  139. int rowCount;
  140. int menuId = event.GetId();
  141. bool visible = (menuId == ID_SHOW_ALL_LAYERS) ? true : false;
  142. long visibleLayers = 0;
  143. bool force_active_layer_visible;
  144. m_alwaysShowActiveLayer = ( menuId == ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE );
  145. force_active_layer_visible = ( menuId == ID_SHOW_NO_LAYERS_BUT_ACTIVE ||
  146. menuId == ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE );
  147. switch( menuId )
  148. {
  149. case ID_SHOW_ALL_LAYERS:
  150. case ID_SHOW_NO_LAYERS:
  151. case ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE:
  152. case ID_SHOW_NO_LAYERS_BUT_ACTIVE:
  153. rowCount = GetLayerRowCount();
  154. for( int row=0; row < rowCount; ++row )
  155. {
  156. wxCheckBox* cb = (wxCheckBox*) getLayerComp( row, COLUMN_COLOR_LYR_CB );
  157. int layer = getDecodedId( cb->GetId() );
  158. bool loc_visible = visible;
  159. if( force_active_layer_visible && (layer == myframe->getActiveLayer() ) )
  160. loc_visible = true;
  161. cb->SetValue( loc_visible );
  162. if( loc_visible )
  163. visibleLayers |= 1 << row;
  164. else
  165. visibleLayers &= ~( 1 << row );
  166. }
  167. myframe->SetVisibleLayers( visibleLayers );
  168. myframe->GetCanvas()->Refresh();
  169. break;
  170. case ID_SORT_GBR_LAYERS:
  171. GetImagesList()->SortImagesByZOrder();
  172. myframe->ReFillLayerWidget();
  173. myframe->syncLayerBox( true );
  174. myframe->GetCanvas()->Refresh();
  175. break;
  176. }
  177. }
  178. bool GERBER_LAYER_WIDGET::OnLayerSelected()
  179. {
  180. if( !m_alwaysShowActiveLayer )
  181. return false;
  182. // postprocess after active layer selection
  183. // ensure active layer visible
  184. wxCommandEvent event;
  185. event.SetId( ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE );
  186. onPopupSelection( event );
  187. return true;
  188. }
  189. void GERBER_LAYER_WIDGET::ReFill()
  190. {
  191. Freeze();
  192. ClearLayerRows();
  193. for( int layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer )
  194. {
  195. wxString msg = GetImagesList()->GetDisplayName( layer );
  196. AppendLayerRow( LAYER_WIDGET::ROW( msg, layer,
  197. myframe->GetLayerColor( layer ), wxEmptyString, true ) );
  198. }
  199. Thaw();
  200. installRightLayerClickHandler();
  201. }
  202. //-----<LAYER_WIDGET callbacks>-------------------------------------------
  203. void GERBER_LAYER_WIDGET::OnLayerColorChange( int aLayer, COLOR4D aColor )
  204. {
  205. myframe->SetLayerColor( aLayer, aColor );
  206. myframe->m_SelLayerBox->ResyncBitmapOnly();
  207. myframe->GetCanvas()->Refresh();
  208. }
  209. bool GERBER_LAYER_WIDGET::OnLayerSelect( int aLayer )
  210. {
  211. // the layer change from the GERBER_LAYER_WIDGET can be denied by returning
  212. // false from this function.
  213. int layer = myframe->getActiveLayer( );
  214. myframe->setActiveLayer( aLayer, false );
  215. myframe->syncLayerBox();
  216. if( layer != myframe->getActiveLayer( ) )
  217. {
  218. if( ! OnLayerSelected() )
  219. myframe->GetCanvas()->Refresh();
  220. }
  221. return true;
  222. }
  223. void GERBER_LAYER_WIDGET::OnLayerVisible( int aLayer, bool isVisible, bool isFinal )
  224. {
  225. long visibleLayers = myframe->GetVisibleLayers();
  226. if( isVisible )
  227. visibleLayers |= 1 << aLayer;
  228. else
  229. visibleLayers &= ~( 1 << aLayer );
  230. myframe->SetVisibleLayers( visibleLayers );
  231. if( isFinal )
  232. myframe->GetCanvas()->Refresh();
  233. }
  234. void GERBER_LAYER_WIDGET::OnRenderColorChange( int aId, COLOR4D aColor )
  235. {
  236. myframe->SetVisibleElementColor( (GERBVIEW_LAYER_ID) aId, aColor );
  237. myframe->GetCanvas()->Refresh();
  238. }
  239. void GERBER_LAYER_WIDGET::OnRenderEnable( int aId, bool isEnabled )
  240. {
  241. myframe->SetElementVisibility( (GERBVIEW_LAYER_ID) aId, isEnabled );
  242. myframe->GetCanvas()->Refresh();
  243. }
  244. //-----</LAYER_WIDGET callbacks>------------------------------------------
  245. /*
  246. * Virtual Function useAlternateBitmap
  247. * return true if bitmaps shown in Render layer list
  248. * must be alternate bitmap (when a gerber image is loaded), or false to use "normal" bitmap
  249. */
  250. bool GERBER_LAYER_WIDGET::useAlternateBitmap(int aRow)
  251. {
  252. return GetImagesList()->GetGbrImage( aRow ) != NULL;
  253. }