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 <bitmaps.h>
27 #include <menus_helpers.h>
28 #include <gerbview.h>
29 #include <gerbview_frame.h>
30 #include <gerber_file_image_list.h>
31 #include <core/arraydim.h>
32 #include <view/view.h>
33 #include <gerbview_painter.h>
36 
37 #include "layer_widget.h"
38 #include "gbr_layer_box_selector.h"
39 #include "gerbview_layer_widget.h"
40 #include "dcode_selection_box.h"
41 
42 /*
43  * GERBER_LAYER_WIDGET
44  * is here to implement the abtract functions of LAYER_WIDGET so they
45  * may be tied into the GERBVIEW_FRAME's data and so we can add a popup
46  * menu which is specific to Pcbnew's needs.
47  */
48 
49 
50 GERBER_LAYER_WIDGET::GERBER_LAYER_WIDGET( GERBVIEW_FRAME* aParent, wxWindow* aFocusOwner ) :
51  LAYER_WIDGET( aParent, aFocusOwner ),
52  myframe( aParent )
53 {
55 
56  ReFillRender();
57 
58  // Update default tabs labels for GerbView
60 
61  //-----<Popup menu>-------------------------------------------------
62  // handle the popup menu over the layer window.
63  m_LayerScrolledWindow->Connect( wxEVT_RIGHT_DOWN,
64  wxMouseEventHandler( GERBER_LAYER_WIDGET::onRightDownLayers ), NULL, this );
65 
66  // since Popupmenu() calls this->ProcessEvent() we must call this->Connect()
67  // and not m_LayerScrolledWindow->Connect()
69  wxEVT_COMMAND_MENU_SELECTED,
70  wxCommandEventHandler( GERBER_LAYER_WIDGET::onPopupSelection ), NULL, this );
71 }
72 
74 {
76 }
77 
78 
80 {
81  m_notebook->SetPageText(0, _("Layers") );
82  m_notebook->SetPageText(1, _("Items") );
83 }
84 
90 {
92 
93  // Fixed "Rendering" tab rows within the LAYER_WIDGET, only the initial color
94  // is changed before appending to the LAYER_WIDGET. This is an automatic variable
95  // not a static variable, change the color & state after copying from code to renderRows
96  // on the stack.
97  LAYER_WIDGET::ROW renderRows[6] = {
98 
99 #define RR LAYER_WIDGET::ROW // Render Row abreviation to reduce source width
100 
101  // text id color tooltip checked
102  RR( _( "DCodes" ), LAYER_DCODES, WHITE, _( "Show DCodes identification" ) ),
103  RR( _( "Negative Objects" ), LAYER_NEGATIVE_OBJECTS, DARKGRAY, _( "Show negative objects in this color" ) ),
104  RR(),
105  RR( _( "Grid" ), LAYER_GERBVIEW_GRID, WHITE, _( "Show the (x,y) grid dots" ) ),
106  RR( _( "Drawing Sheet" ), LAYER_GERBVIEW_DRAWINGSHEET, DARKRED, _( "Show drawing sheet border and title block") ),
107  RR( _( "Background" ), LAYER_GERBVIEW_BACKGROUND, BLACK, _( "PCB Background" ), true, false )
108  };
109 
110  for( unsigned row=0; row<arrayDim(renderRows); ++row )
111  {
112  if( renderRows[row].color != COLOR4D::UNSPECIFIED ) // does this row show a color?
113  renderRows[row].color = myframe->GetVisibleElementColor( renderRows[row].id );
114 
115  if( renderRows[row].id ) // if not the separator
116  renderRows[row].state = myframe->IsElementVisible( renderRows[row].id );
117  }
118 
119  AppendRenderRows( renderRows, arrayDim(renderRows) );
120 }
121 
122 
124 {
125  // Remember: menu text is capitalized (see our rules_for_capitalization_in_Kicad_UI.txt)
126  AddMenuItem( aMenu, ID_SHOW_ALL_LAYERS, _( "Show All Layers" ),
128 
130  _( "Hide All Layers But Active" ),
132 
134  _( "Always Hide All Layers But Active" ),
136 
137  AddMenuItem( aMenu, ID_SHOW_NO_LAYERS, _( "Hide All Layers" ),
139 
140  aMenu->AppendSeparator();
141  AddMenuItem( aMenu, ID_SORT_GBR_LAYERS, _( "Sort Layers if X2 Mode" ),
143 }
144 
145 
146 void GERBER_LAYER_WIDGET::onRightDownLayers( wxMouseEvent& event )
147 {
148  wxMenu menu;
149 
150  AddRightClickMenuItems( &menu );
151  PopupMenu( &menu );
152 
153  passOnFocus();
154 }
155 
156 void GERBER_LAYER_WIDGET::onPopupSelection( wxCommandEvent& event )
157 {
158  int rowCount;
159  int menuId = event.GetId();
160  bool visible = (menuId == ID_SHOW_ALL_LAYERS) ? true : false;
161  LSET visibleLayers;
162  bool force_active_layer_visible;
163 
164  switch( menuId )
165  {
166  case ID_SHOW_ALL_LAYERS:
167  case ID_SHOW_NO_LAYERS:
170  // Set the display layers options. Sorting layers has no effect to these options
172  force_active_layer_visible = ( menuId == ID_SHOW_NO_LAYERS_BUT_ACTIVE ||
174 
175  // Update icons and check boxes
176  rowCount = GetLayerRowCount();
177 
178  for( int row = 0; row < rowCount; ++row )
179  {
180  wxCheckBox* cb = (wxCheckBox*) getLayerComp( row, COLUMN_COLOR_LYR_CB );
181  int layer = getDecodedId( cb->GetId() );
182  bool loc_visible = visible;
183 
184  if( force_active_layer_visible && (layer == myframe->GetActiveLayer() ) )
185  loc_visible = true;
186 
187  cb->SetValue( loc_visible );
188  visibleLayers[ row ] = loc_visible;
189  }
190 
191  myframe->SetVisibleLayers( visibleLayers );
192  myframe->GetCanvas()->Refresh();
193  break;
194 
195  case ID_SORT_GBR_LAYERS:
197  break;
198  }
199 }
200 
202 {
204  return false;
205 
206  // postprocess after active layer selection
207  // ensure active layer visible
208  wxCommandEvent event;
210  onPopupSelection( event );
211  return true;
212 }
213 
214 
216 {
217  Freeze();
218 
219  for( int layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer )
220  {
221  int aRow = findLayerRow( layer );
222  bool visible = true;
224  wxString msg = GetImagesList()->GetDisplayName( layer, /* include layer number */ false,
225  /* Get the full name */ true );
226 
227  if( myframe->GetCanvas() )
228  visible = myframe->GetCanvas()->GetView()->IsLayerVisible( GERBER_DRAW_LAYER( layer ) );
229  else
230  visible = myframe->IsLayerVisible( layer );
231 
232  if( aRow >= 0 )
233  updateLayerRow( findLayerRow( layer ), msg );
234  else
235  AppendLayerRow( LAYER_WIDGET::ROW( msg, layer, color, wxEmptyString, visible, true ) );
236  }
237 
238  UpdateLayouts();
239  Thaw();
240 }
241 
242 //-----<LAYER_WIDGET callbacks>-------------------------------------------
243 
245 {
246  AddRightClickMenuItems( &aMenu );
247 }
248 
249 
251 {
252  // NOTE: Active layer in GerbView is stored as 0-indexed, but layer color is
253  // stored according to the GERBER_DRAW_LAYER() offset.
254  myframe->SetLayerColor( GERBER_DRAW_LAYER( aLayer ), aColor );
256 
257  KIGFX::VIEW* view = myframe->GetCanvas()->GetView();
258  auto settings = Pgm().GetSettingsManager().GetColorSettings();
259  view->GetPainter()->GetSettings()->LoadColors( settings );
260  view->UpdateLayerColor( GERBER_DRAW_LAYER( aLayer ) );
261 
262  myframe->GetCanvas()->Refresh();
263 }
264 
265 
267 {
268  // the layer change from the GERBER_LAYER_WIDGET can be denied by returning
269  // false from this function.
270  int layer = myframe->GetActiveLayer();
271 
272  myframe->SetActiveLayer( aLayer, false );
274 
275  if( layer != myframe->GetActiveLayer() )
276  {
277  if( ! OnLayerSelected() )
278  {
279  auto settings = static_cast<KIGFX::GERBVIEW_PAINTER*>
280  ( myframe->GetCanvas()->GetView()->GetPainter() )->GetSettings();
281  int dcodeSelected = myframe->m_DCodeSelector->GetSelectedDCodeId();
282  settings->m_dcodeHighlightValue = dcodeSelected;
284  myframe->GetCanvas()->Refresh();
285  }
286  }
287 
288  return true;
289 }
290 
291 
292 void GERBER_LAYER_WIDGET::OnLayerVisible( int aLayer, bool isVisible, bool isFinal )
293 {
294  LSET visibleLayers = myframe->GetVisibleLayers();
295 
296  visibleLayers[ aLayer ] = isVisible;
297 
298  myframe->SetVisibleLayers( visibleLayers );
299 
300  if( isFinal )
301  myframe->GetCanvas()->Refresh();
302 }
303 
304 #include "gerbview_draw_panel_gal.h"
306 {
307  myframe->SetVisibleElementColor( aId, aColor );
308 
309  auto view = myframe->GetCanvas()->GetView();
310  COLOR_SETTINGS* settings = Pgm().GetSettingsManager().GetColorSettings();
311 
312  view->GetPainter()->GetSettings()->LoadColors( settings );
313  view->UpdateLayerColor( aId );
314  view->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
315  view->UpdateAllItems( KIGFX::COLOR );
316  myframe->GetCanvas()->Refresh();
317 }
318 
319 
320 void GERBER_LAYER_WIDGET::OnRenderEnable( int aId, bool isEnabled )
321 {
322  myframe->SetElementVisibility( aId, isEnabled );
323 
324  if( myframe->GetCanvas() )
325  {
326  if( aId == LAYER_GERBVIEW_GRID )
327  {
330  }
331  else
332  myframe->GetCanvas()->GetView()->SetLayerVisible( aId, isEnabled );
333  }
334 
335  myframe->GetCanvas()->Refresh();
336 }
337 
338 //-----</LAYER_WIDGET callbacks>------------------------------------------
339 
340 /*
341  * Virtual Function useAlternateBitmap
342  * return true if bitmaps shown in Render layer list
343  * must be alternate bitmap (when a gerber image is loaded), or false to use "normal" bitmap
344  */
346 {
347  return GetImagesList()->GetGbrImage( aRow ) != NULL;
348 }
int findLayerRow(LAYER_NUM aLayer) const
Function findLayerRow returns the row index that aLayer resides in, or -1 if not found.
wxAuiNotebook * m_notebook
Definition: layer_widget.h:127
void SetVisibleElementColor(int aLayerID, COLOR4D aColor)
void SortLayersByX2Attributes()
void OnLayerColorChange(int aLayer, COLOR4D aColor) override
Function OnLayerColorChange is called to notify client code about a layer color change.
Struct ROW provides all the data needed to add a row to a LAYER_WIDGET.
Definition: layer_widget.h:87
void onRightDownLayers(wxMouseEvent &event)
Function OnRightDownLayers puts up a popup menu for the layer panel.
void AddRightClickMenuItems(wxMenu *aMenu)
Function addRightClickMenuItems add menu items to a menu that should be shown when right-clicking the...
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:245
GERBER_LAYER_WIDGET(GERBVIEW_FRAME *aParent, wxWindow *aFocusOwner)
Constructor.
void UpdateLayouts()
GERBVIEW_FRAME * myframe
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
Function OnLayerVisible is called to notify client code about a layer visibility change.
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
Function getLayerComp returns the component within the m_LayersFlexGridSizer at aRow and aCol or NULL...
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)
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
void ClearRenderRows()
Function ClearRenderRows empties 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:92
Auxiliary rendering target (noncached)
Definition: definitions.h:49
void SetLayersManagerTabsText()
Function SetLayersManagerTabsText Update the layer manager tabs labels Useful when changing Language ...
COLOR4D color
COLOR4D::UNSPECIFIED if none.
Definition: layer_widget.h:91
bool OnLayerSelect(int aLayer) override
Function OnLayerSelect is called to notify client code whenever the user selects a different layer.
LSET is a set of PCB_LAYER_IDs.
#define NULL
#define GERBER_DRAWLAYERS_COUNT
GERBER_FILE_IMAGE * GetGbrImage(int aIdx)
void MarkTargetDirty(int aTarget)
Set or clear target 'dirty' flag.
Definition: view.h:574
bool IsGridVisible() const
int GetSelectedDCodeId()
Function GetSelectedDCodeId.
void AppendLayerRow(const ROW &aRow)
Function AppendLayerRow appends a new row in the layer portion of the widget.
static GERBER_FILE_IMAGE_LIST & GetImagesList()
void OnRenderColorChange(int aId, COLOR4D aColor) override
Function OnRenderColorChange is called to notify client code whenever the user changes a rendering co...
void OnLayerRightClick(wxMenu &aMenu) override
Function OnLayerRightClick is called to 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:129
KIGFX::GAL * GetGAL() const
Return a pointer to the GAL instance used in the panel.
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)
void AppendRenderRows(const ROW *aRowsArray, int aRowCount)
Function AppendRenderRows appends new rows in the render portion of the widget.
Definition: layer_widget.h:342
static LAYER_NUM getDecodedId(int aControlId)
Function getDecodedId decodes aControlId to original un-encoded value.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
int GetLayerRowCount() const
Function GetLayerRowCount returns the number of rows in the layer tab.
void passOnFocus()
Function passOnFocus gives 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
Virtual Function useAlternateBitmap.
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
LAYER_WIDGET is abstract and is used to manage a list of layers, with the notion of a "current" layer...
Definition: layer_widget.h:79
int GetActiveLayer() const
Return the active layer.
void OnRenderEnable(int aId, bool isEnabled) override
Function OnRenderEnable is called to notify client code whenever the user changes an rendering enable...
#define COLUMN_COLOR_LYR_CB
Definition: layer_widget.h:54
#define _(s)
Definition: 3d_actions.cpp:33
COLOR4D GetLayerColor(int aLayer) const
void SetLayerColor(int aLayer, COLOR4D aColor)
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.
#define GERBER_DRAW_LAYER(x)
void ReFillRender()
Function 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()
Function OnLayerSelected ensure the active layer is visible, and other layers not visible when m_alwa...
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:98
wxBitmap KiBitmap(BITMAPS aBitmap)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:104