KiCad PCB EDA Suite
gerbview_layer_widget.cpp
Go to the documentation of this file.
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 
26 #include <wx/checkbox.h>
27 #include <wx/filedlg.h>
28 #include <bitmaps.h>
29 #include <menus_helpers.h>
30 #include <gerbview.h>
32 #include <gerbview_frame.h>
33 #include <gerber_file_image_list.h>
34 #include <core/arraydim.h>
35 #include <view/view.h>
36 #include <gerbview_painter.h>
39 
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 
45 
46 GERBER_LAYER_WIDGET::GERBER_LAYER_WIDGET( GERBVIEW_FRAME* aParent, wxWindow* aFocusOwner ) :
47  LAYER_WIDGET( aParent, aFocusOwner ),
48  m_frame( aParent )
49 {
51 
52  ReFillRender();
53 
54  // Update default tabs labels for GerbView
56 
57  // handle the popup menu over the layer window.
58  m_LayerScrolledWindow->Connect( wxEVT_RIGHT_DOWN,
59  wxMouseEventHandler( GERBER_LAYER_WIDGET::onRightDownLayers ),
60  nullptr, this );
61 
62  // since Popupmenu() calls this->ProcessEvent() we must call this->Connect()
63  // and not m_LayerScrolledWindow->Connect()
64  Connect( ID_LAYER_MANAGER_START, ID_LAYER_MANAGER_END, wxEVT_COMMAND_MENU_SELECTED,
65  wxCommandEventHandler( GERBER_LAYER_WIDGET::onPopupSelection ), nullptr, this );
66 }
67 
68 
70 {
72 }
73 
74 
76 {
77  m_notebook->SetPageText( 0, _( "Layers" ) );
78  m_notebook->SetPageText( 1, _( "Items" ) );
79 }
80 
82 {
84 
85  // Fixed "Rendering" tab rows within the LAYER_WIDGET, only the initial color
86  // is changed before appending to the LAYER_WIDGET. This is an automatic variable
87  // not a static variable, change the color & state after copying from code to renderRows
88  // on the stack.
89  LAYER_WIDGET::ROW renderRows[6] = {
90 
91 #define RR LAYER_WIDGET::ROW // Render Row abbreviation to reduce source width
92 
93  RR( _( "DCodes" ), LAYER_DCODES, WHITE,
94  _( "Show DCodes identification" ) ),
95  RR( _( "Negative Objects" ), LAYER_NEGATIVE_OBJECTS, DARKGRAY,
96  _( "Show negative objects in this color" ) ),
97  RR(),
98  RR( _( "Grid" ), LAYER_GERBVIEW_GRID, WHITE,
99  _( "Show the (x,y) grid dots" ) ),
100  RR( _( "Drawing Sheet" ), LAYER_GERBVIEW_DRAWINGSHEET, DARKRED,
101  _( "Show drawing sheet border and title block") ),
102  RR( _( "Background" ), LAYER_GERBVIEW_BACKGROUND, BLACK,
103  _( "PCB Background" ), true, false )
104  };
105 
106  for( unsigned row = 0; row < arrayDim( renderRows ); ++row )
107  {
108  if( renderRows[row].color != COLOR4D::UNSPECIFIED ) // does this row show a color?
109  renderRows[row].color = m_frame->GetVisibleElementColor( renderRows[row].id );
110 
111  if( renderRows[row].id ) // if not the separator
112  renderRows[row].state = m_frame->IsElementVisible( renderRows[row].id );
113  }
114 
115  AppendRenderRows( renderRows, arrayDim(renderRows) );
116 }
117 
118 
120 {
121  // Remember: menu text is capitalized (see our rules_for_capitalization_in_Kicad_UI.txt)
122  AddMenuItem( aMenu, ID_SHOW_ALL_LAYERS, _( "Show All Layers" ),
124 
126  _( "Hide All Layers But Active" ),
128 
130  _( "Always Hide All Layers But Active" ),
132 
133  AddMenuItem( aMenu, ID_SHOW_NO_LAYERS, _( "Hide All Layers" ),
135 
136  aMenu->AppendSeparator();
137  AddMenuItem( aMenu, ID_SORT_GBR_LAYERS, _( "Sort Layers if X2 Mode" ),
139 }
140 
141 
142 void GERBER_LAYER_WIDGET::onRightDownLayers( wxMouseEvent& event )
143 {
144  wxMenu menu;
145 
146  AddRightClickMenuItems( &menu );
147  PopupMenu( &menu );
148 
149  passOnFocus();
150 }
151 
152 
153 void GERBER_LAYER_WIDGET::onPopupSelection( wxCommandEvent& event )
154 {
155  int rowCount;
156  int menuId = event.GetId();
157  bool visible = (menuId == ID_SHOW_ALL_LAYERS) ? true : false;
158  LSET visibleLayers;
159  bool force_active_layer_visible;
160 
161  switch( menuId )
162  {
163  case ID_SHOW_ALL_LAYERS:
164  case ID_SHOW_NO_LAYERS:
167  // Set the display layers options. Sorting layers has no effect to these options
169  force_active_layer_visible = ( menuId == ID_SHOW_NO_LAYERS_BUT_ACTIVE ||
171 
172  // Update icons and check boxes
173  rowCount = GetLayerRowCount();
174 
175  for( int row = 0; row < rowCount; ++row )
176  {
177  wxCheckBox* cb = (wxCheckBox*) getLayerComp( row, COLUMN_COLOR_LYR_CB );
178  int layer = getDecodedId( cb->GetId() );
179  bool loc_visible = visible;
180 
181  if( force_active_layer_visible && (layer == m_frame->GetActiveLayer() ) )
182  loc_visible = true;
183 
184  cb->SetValue( loc_visible );
185  visibleLayers[ row ] = loc_visible;
186  }
187 
188  m_frame->SetVisibleLayers( visibleLayers );
189  m_frame->GetCanvas()->Refresh();
190  break;
191 
192  case ID_SORT_GBR_LAYERS:
194  break;
195  }
196 }
197 
199 {
201  return false;
202 
203  // postprocess after active layer selection ensure active layer visible
204  wxCommandEvent event;
206  onPopupSelection( event );
207  return true;
208 }
209 
210 
212 {
213  Freeze();
214 
215  for( int layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer )
216  {
217  int aRow = findLayerRow( layer );
218  bool visible = true;
220  wxString msg = GetImagesList()->GetDisplayName( layer,
221  /* include layer number */ false,
222  /* Get the full name */ true );
223 
224  if( m_frame->GetCanvas() )
225  visible = m_frame->GetCanvas()->GetView()->IsLayerVisible( GERBER_DRAW_LAYER( layer ) );
226  else
227  visible = m_frame->IsLayerVisible( layer );
228 
229  if( aRow >= 0 )
230  {
231  updateLayerRow( findLayerRow( layer ), msg );
232  SetLayerVisible( layer, visible );
233  }
234  else
235  AppendLayerRow( LAYER_WIDGET::ROW( msg, layer, color, wxEmptyString, visible, true ) );
236  }
237 
238  UpdateLayouts();
239  Thaw();
240 }
241 
242 
244 {
245  AddRightClickMenuItems( &aMenu );
246 }
247 
248 
249 void GERBER_LAYER_WIDGET::OnLayerColorChange( int aLayer, const COLOR4D& aColor )
250 {
251  // NOTE: Active layer in GerbView is stored as 0-indexed, but layer color is
252  // stored according to the GERBER_DRAW_LAYER() offset.
253  m_frame->SetLayerColor( GERBER_DRAW_LAYER( aLayer ), aColor );
255 
256  KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
257  auto settings = m_frame->GetSettingsManager()->GetColorSettings();
258  view->GetPainter()->GetSettings()->LoadColors( settings );
259  view->UpdateLayerColor( GERBER_DRAW_LAYER( aLayer ) );
260 
261  m_frame->GetCanvas()->Refresh();
262 }
263 
264 
266 {
267  // the layer change from the GERBER_LAYER_WIDGET can be denied by returning
268  // false from this function.
269  int layer = m_frame->GetActiveLayer();
270 
271  m_frame->SetActiveLayer( aLayer, false );
273 
274  if( layer != m_frame->GetActiveLayer() )
275  {
276  if( ! OnLayerSelected() )
277  {
278  auto settings = static_cast<KIGFX::GERBVIEW_PAINTER*>
279  ( m_frame->GetCanvas()->GetView()->GetPainter() )->GetSettings();
280  int dcodeSelected = m_frame->m_DCodeSelector->GetSelectedDCodeId();
281  settings->m_dcodeHighlightValue = dcodeSelected;
283  m_frame->GetCanvas()->Refresh();
284  }
285  }
286 
287  return true;
288 }
289 
290 
291 void GERBER_LAYER_WIDGET::OnLayerVisible( int aLayer, bool isVisible, bool isFinal )
292 {
293  LSET visibleLayers = m_frame->GetVisibleLayers();
294 
295  visibleLayers[ aLayer ] = isVisible;
296 
297  m_frame->SetVisibleLayers( visibleLayers );
298 
299  if( isFinal )
300  m_frame->GetCanvas()->Refresh();
301 }
302 
303 
304 void GERBER_LAYER_WIDGET::OnRenderColorChange( int aId, const COLOR4D& aColor )
305 {
306  m_frame->SetVisibleElementColor( aId, aColor );
307 
308  auto view = m_frame->GetCanvas()->GetView();
310 
311  view->GetPainter()->GetSettings()->LoadColors( settings );
312  view->UpdateLayerColor( aId );
313  view->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
314  view->UpdateAllItems( KIGFX::COLOR );
315  m_frame->GetCanvas()->Refresh();
316 }
317 
318 
319 void GERBER_LAYER_WIDGET::OnRenderEnable( int aId, bool isEnabled )
320 {
321  m_frame->SetElementVisibility( aId, isEnabled );
322 
323  if( m_frame->GetCanvas() )
324  {
325  if( aId == LAYER_GERBVIEW_GRID )
326  {
329  }
330  else
331  {
332  m_frame->GetCanvas()->GetView()->SetLayerVisible( aId, isEnabled );
333  }
334  }
335 
336  m_frame->GetCanvas()->Refresh();
337 }
338 
339 
341 {
342  return GetImagesList()->GetGbrImage( aRow ) != nullptr;
343 }
int findLayerRow(LAYER_NUM aLayer) const
Return the row index that aLayer resides in, or -1 if not found.
wxAuiNotebook * m_notebook
Definition: layer_widget.h:460
void SortLayersByX2Attributes()
void SetLayerColor(int aLayer, const COLOR4D &aColor)
Provide all the data needed to add a row to a LAYER_WIDGET.
Definition: layer_widget.h:84
void onRightDownLayers(wxMouseEvent &event)
Put up a popup menu for the layer panel.
SETTINGS_MANAGER * GetSettingsManager() const
void AddRightClickMenuItems(wxMenu *aMenu)
Add menu items to a menu that should be shown when right-clicking the Gerber layer widget.
void syncLayerBox(bool aRebuildLayerBox=false)
Update the currently "selected" layer within m_SelLayerBox.
COLOR4D GetVisibleElementColor(int aLayerID)
Return the color of a gerber visible element.
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
wxMenuItem * AddMenuItem(wxMenu *aMenu, int aId, const wxString &aText, const wxBitmap &aImage, wxItemKind aType=wxITEM_NORMAL)
Create and insert a menu item with an icon into aMenu.
Definition: bitmap.cpp:254
GERBER_LAYER_WIDGET(GERBVIEW_FRAME *aParent, wxWindow *aFocusOwner)
void UpdateLayouts()
void SetVisibleElementColor(int aLayerID, const COLOR4D &aColor)
int color
Definition: DXF_plotter.cpp:60
virtual EDA_DRAW_PANEL_GAL * GetCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
void OnLayerVisible(int aLayer, bool isVisible, bool isFinal) override
Notify client code about a layer visibility change.
void OnRenderColorChange(int aId, const COLOR4D &aColor) override
Notify client code whenever the user changes a rendering color.
void UpdateAllItems(int aUpdateFlags)
Update all items in the view according to the given flags.
Definition: view.cpp:1415
void SetActiveLayer(int aLayer, bool doLayerWidgetUpdate=true)
change the currently active layer to aLayer and update the GERBER_LAYER_WIDGET.
GBR_LAYER_BOX_SELECTOR * m_SelLayerBox
#define RR
GERBER_FILE_IMAGE_LIST * GetImagesList()
wxWindow * getLayerComp(int aRow, int aColumn) const
Return the component within the m_LayersFlexGridSizer at aRow and aCol or NULL if these parameters ar...
Definition: color4d.h:44
Color has changed.
Definition: view_item.h:53
GERBER_FILE_IMAGE_LIST is a helper class to handle a list of GERBER_FILE_IMAGE files which are loaded...
void updateLayerRow(int aRow, const wxString &aName)
void ClearRenderRows()
Empty out the render rows.
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:207
bool state
initial wxCheckBox state
Definition: layer_widget.h:89
Auxiliary rendering target (noncached)
Definition: definitions.h:49
void SetLayersManagerTabsText()
Update the layer manager tabs labels.
COLOR4D color
COLOR4D::UNSPECIFIED if none.
Definition: layer_widget.h:88
bool OnLayerSelect(int aLayer) override
Notify client code whenever the user selects a different layer.
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:502
GERBER_FILE_IMAGE * GetGbrImage(int aIdx)
void MarkTargetDirty(int aTarget)
Set or clear target 'dirty' flag.
Definition: view.h:572
bool IsGridVisible() const
#define GERBER_DRAWLAYERS_COUNT
Definition: layer_ids.h:376
void AppendLayerRow(const ROW &aRow)
Append a new row in the layer portion of the widget.
static GERBER_FILE_IMAGE_LIST & GetImagesList()
void OnLayerRightClick(wxMenu &aMenu) override
Notify client code about a layer being right-clicked.
bool IsElementVisible(int aLayerID) const
Test whether a given element category is visible.
wxScrolledWindow * m_LayerScrolledWindow
Definition: layer_widget.h:462
KIGFX::GAL * GetGAL() const
Return a pointer to the GAL instance used in the panel.
#define _(s)
virtual KIGFX::VIEW * GetView() const
Return a pointer to the #VIEW instance used in the panel.
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
void SetLayerVisible(int aLayer, bool aVisible=true)
Control the visibility of a particular layer.
Definition: view.h:387
void onPopupSelection(wxCommandEvent &event)
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
void AppendRenderRows(const ROW *aRowsArray, int aRowCount)
Append new rows in the render portion of the widget.
Definition: layer_widget.h:200
static LAYER_NUM getDecodedId(int aControlId)
Decode aControlId to original un-encoded value.
void OnLayerColorChange(int aLayer, const COLOR4D &aColor) override
Notify client code about a layer color change.
#define GERBER_DRAW_LAYER(x)
Definition: layer_ids.h:396
int GetLayerRowCount() const
Return the number of rows in the layer tab.
void passOnFocus()
Give away the keyboard focus up to the main parent window.
Definition: color4d.h:48
DCODE_SELECTION_BOX * m_DCodeSelector
void UpdateLayerColor(int aLayer)
Apply the new coloring scheme held by RENDER_SETTINGS in case that it has changed.
Definition: view.cpp:752
virtual bool useAlternateBitmap(int aRow) override
COLOR_SETTINGS * GetColorSettings(const wxString &aName="user")
Retrieves a color settings object that applications can read colors from.
void ReFill()
Rebuild Render for instance after the config is read.
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
Manage a list of layers with the notion of a "current" layer, and layer specific visibility control.
Definition: layer_widget.h:77
int GetActiveLayer() const
Return the active layer.
void OnRenderEnable(int aId, bool isEnabled) override
Notify client code whenever the user changes an rendering enable in one of the rendering checkboxes.
#define COLUMN_COLOR_LYR_CB
Definition: layer_widget.h:53
COLOR4D GetLayerColor(int aLayer) const
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
void SetGridVisibility(bool aVisibility)
Set the visibility setting of the grid.
Color settings are a bit different than most of the settings objects in that there can be more than o...
void SetVisibleLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings.
void SetLayerVisible(LAYER_NUM aLayer, bool isVisible)
Set aLayer visible or not.
void ReFillRender()
Rebuild Render for instance after the config is read.
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:67
virtual void LoadColors(const COLOR_SETTINGS *aSettings)
bool IsLayerVisible(int aLayer) const
Test whether a given layer is visible.
bool OnLayerSelected()
Ensure the active layer is visible, and other layers not visible when m_alwaysShowActiveLayer is true...
void SetElementVisibility(int aLayerID, bool aNewState)
Change the visibility of an element category.
const wxString GetDisplayName(int aIdx, bool aNameOnly=false, bool aFullName=false)
Get the display name for the layer at aIdx.
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:404
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103