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-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 
26 
27 #include <fctsys.h>
28 #include <common.h>
29 #include <class_drawpanel.h>
30 #include <macros.h>
31 #include <gbr_layer_box_selector.h>
32 #include <menus_helpers.h>
33 
34 #include <gerbview.h>
35 #include <gerbview_frame.h>
36 #include <gerber_file_image_list.h>
37 #include <layer_widget.h>
38 #include <gerbview_layer_widget.h>
39 
40 #include <view/view.h>
41 #include <gerbview_painter.h>
43 
44 
45 /*
46  * Class GERBER_LAYER_WIDGET
47  * is here to implement the abtract functions of LAYER_WIDGET so they
48  * may be tied into the GERBVIEW_FRAME's data and so we can add a popup
49  * menu which is specific to Pcbnew's needs.
50  */
51 
52 
53 GERBER_LAYER_WIDGET::GERBER_LAYER_WIDGET( GERBVIEW_FRAME* aParent, wxWindow* aFocusOwner ) :
54  LAYER_WIDGET( aParent, aFocusOwner ),
55  myframe( aParent )
56 {
58 
59  ReFillRender();
60 
61  // Update default tabs labels for GerbView
63 
64  //-----<Popup menu>-------------------------------------------------
65  // handle the popup menu over the layer window.
66  m_LayerScrolledWindow->Connect( wxEVT_RIGHT_DOWN,
67  wxMouseEventHandler( GERBER_LAYER_WIDGET::onRightDownLayers ), NULL, this );
68 
69  // since Popupmenu() calls this->ProcessEvent() we must call this->Connect()
70  // and not m_LayerScrolledWindow->Connect()
72  wxEVT_COMMAND_MENU_SELECTED,
73  wxCommandEventHandler( GERBER_LAYER_WIDGET::onPopupSelection ), NULL, this );
74 }
75 
77 {
79 }
80 
81 
83 {
84  return myframe->IsGalCanvasActive();
85 }
86 
87 
89 {
90  m_notebook->SetPageText(0, _("Layers") );
91  m_notebook->SetPageText(1, _("Items") );
92 }
93 
99 {
100  ClearRenderRows();
101 
102  // Fixed "Rendering" tab rows within the LAYER_WIDGET, only the initial color
103  // is changed before appending to the LAYER_WIDGET. This is an automatic variable
104  // not a static variable, change the color & state after copying from code to renderRows
105  // on the stack.
106  LAYER_WIDGET::ROW renderRows[6] = {
107 
108 #define RR LAYER_WIDGET::ROW // Render Row abreviation to reduce source width
109 
110  // text id color tooltip checked
111  RR( _( "DCodes" ), LAYER_DCODES, WHITE, _( "Show DCodes identification" ) ),
112  RR( _( "Negative Objects" ), LAYER_NEGATIVE_OBJECTS, DARKGRAY, _( "Show negative objects in this color" ) ),
113  RR(),
114  RR( _( "Grid" ), LAYER_GERBVIEW_GRID, WHITE, _( "Show the (x,y) grid dots" ) ),
115  RR( _( "Worksheet" ), LAYER_WORKSHEET, DARKRED, _( "Show worksheet") ),
116  RR( _( "Background" ), LAYER_PCB_BACKGROUND, BLACK, _( "PCB Background" ), true, false )
117  };
118 
119  for( unsigned row=0; row<arrayDim(renderRows); ++row )
120  {
121  if( renderRows[row].color != COLOR4D::UNSPECIFIED ) // does this row show a color?
122  renderRows[row].color = myframe->GetVisibleElementColor( renderRows[row].id );
123 
124  if( renderRows[row].id ) // if not the separator
125  renderRows[row].state = myframe->IsElementVisible( renderRows[row].id );
126  }
127 
128  AppendRenderRows( renderRows, arrayDim(renderRows) );
129 }
130 
131 
133 {
134  // Remember: menu text is capitalized (see our rules_for_capitalization_in_Kicad_UI.txt)
135  AddMenuItem( aMenu, ID_SHOW_ALL_LAYERS, _( "Show All Layers" ),
136  KiBitmap( show_all_layers_xpm ) );
137 
139  _( "Hide All Layers But Active" ),
140  KiBitmap( select_w_layer_xpm ) );
141 
143  _( "Always Hide All Layers But Active" ),
144  KiBitmap( select_w_layer_xpm ) );
145 
146  AddMenuItem( aMenu, ID_SHOW_NO_LAYERS, _( "Hide All Layers" ),
147  KiBitmap( show_no_layers_xpm ) );
148 
149  aMenu->AppendSeparator();
150  AddMenuItem( aMenu, ID_SORT_GBR_LAYERS, _( "Sort Layers if X2 Mode" ),
151  KiBitmap( reload_xpm ) );
152 }
153 
154 
155 void GERBER_LAYER_WIDGET::onRightDownLayers( wxMouseEvent& event )
156 {
157  wxMenu menu;
158 
159  AddRightClickMenuItems( &menu );
160  PopupMenu( &menu );
161 
162  passOnFocus();
163 }
164 
165 void GERBER_LAYER_WIDGET::onPopupSelection( wxCommandEvent& event )
166 {
167  int rowCount;
168  int menuId = event.GetId();
169  bool visible = (menuId == ID_SHOW_ALL_LAYERS) ? true : false;
170  LSET visibleLayers;
171  bool force_active_layer_visible;
172 
173  switch( menuId )
174  {
175  case ID_SHOW_ALL_LAYERS:
176  case ID_SHOW_NO_LAYERS:
179  // Set the display layers options. Sorting layers has no effect to these options
181  force_active_layer_visible = ( menuId == ID_SHOW_NO_LAYERS_BUT_ACTIVE ||
183 
184  // Update icons and check boxes
185  rowCount = GetLayerRowCount();
186 
187  for( int row = 0; row < rowCount; ++row )
188  {
189  wxCheckBox* cb = (wxCheckBox*) getLayerComp( row, COLUMN_COLOR_LYR_CB );
190  int layer = getDecodedId( cb->GetId() );
191  bool loc_visible = visible;
192 
193  if( force_active_layer_visible && (layer == myframe->GetActiveLayer() ) )
194  loc_visible = true;
195 
196  cb->SetValue( loc_visible );
197  visibleLayers[ row ] = loc_visible;
198  }
199 
200  myframe->SetVisibleLayers( visibleLayers );
201  myframe->GetCanvas()->Refresh();
202  break;
203 
204  case ID_SORT_GBR_LAYERS:
206  break;
207  }
208 }
209 
211 {
213  return false;
214 
215  // postprocess after active layer selection
216  // ensure active layer visible
217  wxCommandEvent event;
219  onPopupSelection( event );
220  return true;
221 }
222 
223 
225 {
226  Freeze();
227 
228  ClearLayerRows();
229 
230  for( int layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer )
231  {
232  wxString msg = GetImagesList()->GetDisplayName( layer );
233 
234  bool visible = true;
235 
236  if( auto canvas = myframe->GetGalCanvas() )
237  {
238  visible = canvas->GetView()->IsLayerVisible( GERBER_DRAW_LAYER( layer ) );
239  }
240  else
241  {
242  visible = myframe->IsLayerVisible( layer );
243  }
244 
245  AppendLayerRow( LAYER_WIDGET::ROW( msg, layer,
247  wxEmptyString, visible, true ) );
248  }
249 
250  UpdateLayouts();
251  Thaw();
252 }
253 
254 //-----<LAYER_WIDGET callbacks>-------------------------------------------
255 
257 {
258  AddRightClickMenuItems( &aMenu );
259 }
260 
261 
263 {
264  // NOTE: Active layer in GerbView is stored as 0-indexed, but layer color is
265  // stored according to the GERBER_DRAW_LAYER() offset.
266 
267  myframe->SetLayerColor( GERBER_DRAW_LAYER( aLayer ), aColor );
269 
270  if( myframe->IsGalCanvasActive() )
271  {
272  KIGFX::VIEW* view = myframe->GetGalCanvas()->GetView();
274  view->UpdateLayerColor( GERBER_DRAW_LAYER( aLayer ) );
275  }
276 
277  myframe->GetCanvas()->Refresh();
278 }
279 
280 
282 {
283  // the layer change from the GERBER_LAYER_WIDGET can be denied by returning
284  // false from this function.
285  int layer = myframe->GetActiveLayer();
286 
287  myframe->SetActiveLayer( aLayer, false );
289 
290  if( layer != myframe->GetActiveLayer() )
291  {
292  if( ! OnLayerSelected() )
293  myframe->GetCanvas()->Refresh();
294  }
295 
296  return true;
297 }
298 
299 
300 void GERBER_LAYER_WIDGET::OnLayerVisible( int aLayer, bool isVisible, bool isFinal )
301 {
302  LSET visibleLayers = myframe->GetVisibleLayers();
303 
304  visibleLayers[ aLayer ] = isVisible;
305 
306  myframe->SetVisibleLayers( visibleLayers );
307 
308  if( isFinal )
309  myframe->GetCanvas()->Refresh();
310 }
311 
312 
314 {
315  myframe->SetVisibleElementColor( aId, aColor );
316 
317  auto galCanvas = myframe->GetGalCanvas();
318 
319  if( galCanvas && myframe->IsGalCanvasActive() )
320  {
321  auto view = galCanvas->GetView();
323  view->UpdateLayerColor( aId );
324 
325  view->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
326  view->UpdateAllItems( KIGFX::COLOR );
327  }
328 
329  if( galCanvas && myframe->IsGalCanvasActive() )
330  galCanvas->Refresh();
331  else
332  myframe->GetCanvas()->Refresh();
333 }
334 
335 
336 void GERBER_LAYER_WIDGET::OnRenderEnable( int aId, bool isEnabled )
337 {
338  myframe->SetElementVisibility( aId, isEnabled );
339 
340  auto galCanvas = myframe->GetGalCanvas();
341 
342  if( galCanvas )
343  {
344  if( aId == LAYER_GERBVIEW_GRID )
345  {
346  galCanvas->GetGAL()->SetGridVisibility( myframe->IsGridVisible() );
347  galCanvas->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
348  }
349  else
350  galCanvas->GetView()->SetLayerVisible( aId, isEnabled );
351  }
352 
353  if( galCanvas && myframe->IsGalCanvasActive() )
354  galCanvas->Refresh();
355  else
356  myframe->GetCanvas()->Refresh();
357 }
358 
359 //-----</LAYER_WIDGET callbacks>------------------------------------------
360 
361 /*
362  * Virtual Function useAlternateBitmap
363  * return true if bitmaps shown in Render layer list
364  * must be alternate bitmap (when a gerber image is loaded), or false to use "normal" bitmap
365  */
367 {
368  return GetImagesList()->GetGbrImage( aRow ) != NULL;
369 }
wxAuiNotebook * m_notebook
Definition: layer_widget.h:123
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...
const wxString GetDisplayName(int aIdx, bool aNameOnly=false)
void syncLayerBox(bool aRebuildLayerBox=false)
Function syncLayerBox updates the currently "selected" layer within m_SelLayerBox The currently activ...
COLOR4D GetVisibleElementColor(int aLayerID)
Function GetVisibleElementColor returns the color of a gerber visible element.
LSET GetVisibleLayers() const
Function GetVisibleLayers is a proxy function that calls the correspondent function in m_BoardSetting...
wxMenuItem * AddMenuItem(wxMenu *aMenu, int aId, const wxString &aText, const wxBitmap &aImage, wxItemKind aType=wxITEM_NORMAL)
Function AddMenuItem is an inline helper function to create and insert a menu item with an icon into ...
Definition: bitmap.cpp:251
GERBER_LAYER_WIDGET(GERBVIEW_FRAME *aParent, wxWindow *aFocusOwner)
Constructor.
virtual bool IsGridVisible() const
Definition: draw_frame.h:533
void UpdateLayouts()
EDA_DRAW_PANEL_GAL * GetGalCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
Definition: draw_frame.h:931
GERBVIEW_FRAME * myframe
int color
Definition: DXF_plotter.cpp:62
void OnLayerVisible(int aLayer, bool isVisible, bool isFinal) override
Function OnLayerVisible is called to notify client code about a layer visibility change.
void SetActiveLayer(int aLayer, bool doLayerWidgetUpdate=true)
Function SetActiveLayer will change the currently active layer to aLayer and also update the GERBER_L...
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...
Visibility flag has changed.
Definition: view_item.h:56
GERBER_FILE_IMAGE_LIST is a helper class to handle a list of GERBER_FILE_IMAGE files which are loaded...
int GetActiveLayer()
Function SetActiveLayer returns the active layer.
void ClearRenderRows()
Function ClearRenderRows empties out the render rows.
PAINTER * GetPainter() const
Function GetPainter() Returns the painter object used by the view for drawing VIEW_ITEMS.
Definition: view.h:199
Definition: colors.h:54
bool state
initial wxCheckBox state
Definition: layer_widget.h:92
void ClearLayerRows()
Function ClearLayerRows empties out the layer rows.
Auxiliary rendering target (noncached)
Definition: definitions.h:49
This file contains miscellaneous commonly used macros and functions.
bool IsGalCanvasActive() const
Function IsGalCanvasActive is used to check which canvas (GAL-based or standard) is currently in use.
Definition: draw_frame.h:924
void SetLayersManagerTabsText()
Function SetLayersManagerTabsText Update the layer manager tabs labels Useful when changing Language ...
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Construct a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:79
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.
Class LSET is a set of PCB_LAYER_IDs.
#define GERBER_DRAWLAYERS_COUNT
GERBER_FILE_IMAGE * GetGbrImage(int aIdx)
COLORS_DESIGN_SETTINGS * m_colorsSettings
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
Function IsElementVisible tests whether a given element category is visible.
wxScrolledWindow * m_LayerScrolledWindow
Definition: layer_widget.h:125
KIGFX::GAL * GetGAL() const
Function GetGAL() Returns a pointer to the GAL instance used in the panel.
virtual EDA_DRAW_PANEL * GetCanvas() const
Definition: draw_frame.h:399
void onPopupSelection(wxCommandEvent &event)
virtual bool AreArbitraryColorsAllowed() override
Subclasses can override this to provide logic for allowing arbitrary color selection via wxColourPick...
void AppendRenderRows(const ROW *aRowsArray, int aRowCount)
Function AppendRenderRows appends new rows in the render portion of the widget.
Definition: layer_widget.h:333
static LAYER_NUM getDecodedId(int aControlId)
Function getDecodedId decodes aControlId to original un-encoded value.
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Definition: macros.h:107
int GetLayerRowCount() const
Function GetLayerRowCount returns the number of rows in the layer tab.
virtual void ImportLegacyColors(const COLORS_DESIGN_SETTINGS *aSettings)=0
Function ImportLegacyColors Loads a list of color settings for layers.
void passOnFocus()
Function passOnFocus gives away the keyboard focus up to the main parent window.
void UpdateLayerColor(int aLayer)
Function UpdateLayerColor() Applies the new coloring scheme held by RENDER_SETTINGS in case that it h...
Definition: view.cpp:776
virtual bool useAlternateBitmap(int aRow) override
Virtual Function useAlternateBitmap.
virtual RENDER_SETTINGS * GetSettings()=0
Function GetSettings Returns pointer to current settings that are going to be used when drawing items...
Class LAYER_WIDGET is abstract and is used to manage a list of layers, with the notion of a "current"...
Definition: layer_widget.h:79
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
KIGFX::VIEW * GetView() const
Function GetView() Returns a pointer to the VIEW instance used in the panel.
COLOR4D GetLayerColor(int aLayer) const
Function GetLayerColor gets a layer color for any valid layer.
void SetLayerColor(int aLayer, COLOR4D aColor)
Function SetLayerColor changes a layer color for any valid layer.
The common library.
void SetGridVisibility(bool aVisibility)
Sets the visibility setting of the grid.
Definition: colors.h:49
void SetVisibleLayers(LSET aLayerMask)
Function SetVisibleLayers is a proxy function that calls the correspondent function in m_BoardSetting...
#define GERBER_DRAW_LAYER(x)
Definition: colors.h:45
void ReFillRender()
Function ReFillRender Rebuild Render for instance after the config is read.
Class VIEW.
Definition: view.h:61
virtual void Refresh(bool eraseBackground=true, const wxRect *rect=NULL)
bool IsLayerVisible(int aLayer) const
Function IsLayerVisible tests 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)
Function SetElementVisibility changes the visibility of an element category.
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39