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 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 
32 #include <fctsys.h>
33 #include <common.h>
34 #include <class_drawpanel.h>
35 #include <macros.h>
36 #include <gbr_layer_box_selector.h>
37 #include <menus_helpers.h>
38 
39 #include <gerbview.h>
40 #include <gerbview_frame.h>
41 #include <gerber_file_image_list.h>
42 #include <layer_widget.h>
43 #include <gerbview_layer_widget.h>
44 
45 #include <view/view.h>
46 #include <gerbview_painter.h>
48 
49 
50 /*
51  * Class GERBER_LAYER_WIDGET
52  * is here to implement the abtract functions of LAYER_WIDGET so they
53  * may be tied into the GERBVIEW_FRAME's data and so we can add a popup
54  * menu which is specific to Pcbnew's needs.
55  */
56 
57 
58 GERBER_LAYER_WIDGET::GERBER_LAYER_WIDGET( GERBVIEW_FRAME* aParent, wxWindow* aFocusOwner ) :
59  LAYER_WIDGET( aParent, aFocusOwner ),
60  myframe( aParent )
61 {
63 
64  ReFillRender();
65 
66  // Update default tabs labels for GerbView
68 
69  //-----<Popup menu>-------------------------------------------------
70  // handle the popup menu over the layer window.
71  m_LayerScrolledWindow->Connect( wxEVT_RIGHT_DOWN,
72  wxMouseEventHandler( GERBER_LAYER_WIDGET::onRightDownLayers ), NULL, this );
73 
74  // since Popupmenu() calls this->ProcessEvent() we must call this->Connect()
75  // and not m_LayerScrolledWindow->Connect()
77  wxEVT_COMMAND_MENU_SELECTED,
78  wxCommandEventHandler( GERBER_LAYER_WIDGET::onPopupSelection ), NULL, this );
79 }
80 
82 {
84 }
85 
86 
88 {
89  return myframe->IsGalCanvasActive();
90 }
91 
92 
94 {
95  m_notebook->SetPageText(0, _("Layers") );
96  m_notebook->SetPageText(1, _("Items") );
97 }
98 
104 {
105  ClearRenderRows();
106 
107  // Fixed "Rendering" tab rows within the LAYER_WIDGET, only the initial color
108  // is changed before appending to the LAYER_WIDGET. This is an automatic variable
109  // not a static variable, change the color & state after copying from code to renderRows
110  // on the stack.
111  LAYER_WIDGET::ROW renderRows[6] = {
112 
113 #define RR LAYER_WIDGET::ROW // Render Row abreviation to reduce source width
114 
115  // text id color tooltip checked
116  RR( _( "DCodes" ), LAYER_DCODES, WHITE, _( "Show DCodes identification" ) ),
117  RR( _( "Negative Objects" ), LAYER_NEGATIVE_OBJECTS, DARKGRAY, _( "Show negative objects in this color" ) ),
118  RR(),
119  RR( _( "Grid" ), LAYER_GERBVIEW_GRID, WHITE, _( "Show the (x,y) grid dots" ) ),
120  RR( _( "Worksheet" ), LAYER_WORKSHEET, DARKRED, _( "Show worksheet") ),
121  RR( _( "Background" ), LAYER_PCB_BACKGROUND, BLACK, _( "PCB Background" ), true, false )
122  };
123 
124  for( unsigned row=0; row<DIM(renderRows); ++row )
125  {
126  if( renderRows[row].color != COLOR4D::UNSPECIFIED ) // does this row show a color?
127  renderRows[row].color = myframe->GetVisibleElementColor( renderRows[row].id );
128 
129  if( renderRows[row].id ) // if not the separator
130  renderRows[row].state = myframe->IsElementVisible( renderRows[row].id );
131  }
132 
133  AppendRenderRows( renderRows, DIM(renderRows) );
134 }
135 
136 
138 {
139  // Remember: menu text is capitalized (see our rules_for_capitalization_in_Kicad_UI.txt)
140  AddMenuItem( aMenu, ID_SHOW_ALL_LAYERS, _( "Show All Layers" ),
141  KiBitmap( show_all_layers_xpm ) );
142 
144  _( "Hide All Layers But Active" ),
145  KiBitmap( select_w_layer_xpm ) );
146 
148  _( "Always Hide All Layers But Active" ),
149  KiBitmap( select_w_layer_xpm ) );
150 
151  AddMenuItem( aMenu, ID_SHOW_NO_LAYERS, _( "Hide All Layers" ),
152  KiBitmap( show_no_layers_xpm ) );
153 
154  aMenu->AppendSeparator();
155  AddMenuItem( aMenu, ID_SORT_GBR_LAYERS, _( "Sort Layers if X2 Mode" ),
156  KiBitmap( reload_xpm ) );
157 }
158 
159 
160 void GERBER_LAYER_WIDGET::onRightDownLayers( wxMouseEvent& event )
161 {
162  wxMenu menu;
163 
164  AddRightClickMenuItems( &menu );
165  PopupMenu( &menu );
166 
167  passOnFocus();
168 }
169 
170 void GERBER_LAYER_WIDGET::onPopupSelection( wxCommandEvent& event )
171 {
172  int rowCount;
173  int menuId = event.GetId();
174  bool visible = (menuId == ID_SHOW_ALL_LAYERS) ? true : false;
175  long visibleLayers = 0;
176  bool force_active_layer_visible;
177 
178  switch( menuId )
179  {
180  case ID_SHOW_ALL_LAYERS:
181  case ID_SHOW_NO_LAYERS:
184  // Set the display layers options. Sorting layers has no effect to these options
186  force_active_layer_visible = ( menuId == ID_SHOW_NO_LAYERS_BUT_ACTIVE ||
188  // Update icons and check boxes
189  rowCount = GetLayerRowCount();
190  for( int row=0; row < rowCount; ++row )
191  {
192  wxCheckBox* cb = (wxCheckBox*) getLayerComp( row, COLUMN_COLOR_LYR_CB );
193  int layer = getDecodedId( cb->GetId() );
194  bool loc_visible = visible;
195 
196  if( force_active_layer_visible &&
197  (layer == myframe->GetActiveLayer() ) )
198  {
199  loc_visible = true;
200  }
201 
202  cb->SetValue( loc_visible );
203 
204  if( loc_visible )
205  visibleLayers |= 1 << row;
206  else
207  visibleLayers &= ~( 1 << row );
208  }
209 
210  myframe->SetVisibleLayers( visibleLayers );
211  myframe->GetCanvas()->Refresh();
212  break;
213 
214  case ID_SORT_GBR_LAYERS:
216  break;
217  }
218 }
219 
221 {
223  return false;
224 
225  // postprocess after active layer selection
226  // ensure active layer visible
227  wxCommandEvent event;
229  onPopupSelection( event );
230  return true;
231 }
232 
233 
235 {
236  Freeze();
237 
238  ClearLayerRows();
239 
240  for( int layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer )
241  {
242  wxString msg = GetImagesList()->GetDisplayName( layer );
243 
244  bool visible = true;
245 
246  if( auto canvas = myframe->GetGalCanvas() )
247  {
248  visible = canvas->GetView()->IsLayerVisible( GERBER_DRAW_LAYER( layer ) );
249  }
250  else
251  {
252  visible = myframe->IsLayerVisible( layer );
253  }
254 
255  AppendLayerRow( LAYER_WIDGET::ROW( msg, layer,
257  wxEmptyString, visible, true ) );
258  }
259 
260  UpdateLayouts();
261  Thaw();
262 }
263 
264 //-----<LAYER_WIDGET callbacks>-------------------------------------------
265 
267 {
268  AddRightClickMenuItems( &aMenu );
269 }
270 
271 
273 {
274  // NOTE: Active layer in GerbView is stored as 0-indexed, but layer color is
275  // stored according to the GERBER_DRAW_LAYER() offset.
276 
277  myframe->SetLayerColor( GERBER_DRAW_LAYER( aLayer ), aColor );
279 
280  if( myframe->IsGalCanvasActive() )
281  {
282  KIGFX::VIEW* view = myframe->GetGalCanvas()->GetView();
284  view->UpdateLayerColor( GERBER_DRAW_LAYER( aLayer ) );
285  }
286 
287  myframe->GetCanvas()->Refresh();
288 }
289 
290 
292 {
293  // the layer change from the GERBER_LAYER_WIDGET can be denied by returning
294  // false from this function.
295  int layer = myframe->GetActiveLayer();
296 
297  myframe->SetActiveLayer( aLayer, false );
299 
300  if( layer != myframe->GetActiveLayer() )
301  {
302  if( ! OnLayerSelected() )
303  myframe->GetCanvas()->Refresh();
304  }
305 
306  return true;
307 }
308 
309 
310 void GERBER_LAYER_WIDGET::OnLayerVisible( int aLayer, bool isVisible, bool isFinal )
311 {
312  long visibleLayers = myframe->GetVisibleLayers();
313 
314  if( isVisible )
315  visibleLayers |= 1 << aLayer ;
316  else
317  visibleLayers &= ~( 1 << aLayer );
318 
319  myframe->SetVisibleLayers( visibleLayers );
320 
321  if( isFinal )
322  myframe->GetCanvas()->Refresh();
323 }
324 
325 
327 {
328  myframe->SetVisibleElementColor( aId, aColor );
329 
330  auto galCanvas = myframe->GetGalCanvas();
331 
332  if( galCanvas && myframe->IsGalCanvasActive() )
333  {
334  auto view = galCanvas->GetView();
336  view->UpdateLayerColor( aId );
337 
338  view->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
339  view->UpdateAllItems( KIGFX::COLOR );
340  }
341 
342  if( galCanvas && myframe->IsGalCanvasActive() )
343  galCanvas->Refresh();
344  else
345  myframe->GetCanvas()->Refresh();
346 }
347 
348 
349 void GERBER_LAYER_WIDGET::OnRenderEnable( int aId, bool isEnabled )
350 {
351  myframe->SetElementVisibility( aId, isEnabled );
352 
353  auto galCanvas = myframe->GetGalCanvas();
354 
355  if( galCanvas )
356  {
357  if( aId == LAYER_GERBVIEW_GRID )
358  {
359  galCanvas->GetGAL()->SetGridVisibility( myframe->IsGridVisible() );
360  galCanvas->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
361  }
362  else
363  galCanvas->GetView()->SetLayerVisible( aId, isEnabled );
364  }
365 
366  if( galCanvas && myframe->IsGalCanvasActive() )
367  galCanvas->Refresh();
368  else
369  myframe->GetCanvas()->Refresh();
370 }
371 
372 //-----</LAYER_WIDGET callbacks>------------------------------------------
373 
374 /*
375  * Virtual Function useAlternateBitmap
376  * return true if bitmaps shown in Render layer list
377  * must be alternate bitmap (when a gerber image is loaded), or false to use "normal" bitmap
378  */
380 {
381  return GetImagesList()->GetGbrImage( aRow ) != NULL;
382 }
#define DIM(x)
of elements in an array
Definition: macros.h:98
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.
virtual EDA_DRAW_PANEL * GetCanvas() const
Definition: draw_frame.h:388
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.
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:223
GERBER_LAYER_WIDGET(GERBVIEW_FRAME *aParent, wxWindow *aFocusOwner)
Constructor.
void UpdateLayouts()
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()
KIGFX::VIEW * GetView() const
Function GetView() Returns a pointer to the VIEW instance used in the panel.
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 SetVisibleLayers(long aLayerMask)
Function SetVisibleLayers is a proxy function that calls the correspondent function in m_BoardSetting...
void ClearRenderRows()
Function ClearRenderRows empties out the render rows.
Definition: colors.h:54
bool state
initial wxCheckBox state
Definition: layer_widget.h:92
virtual bool IsGridVisible() const
Definition: draw_frame.h:528
void ClearLayerRows()
Function ClearLayerRows empties out the layer rows.
long GetVisibleLayers() const
Function GetVisibleLayers is a proxy function that calls the correspondent function in m_BoardSetting...
Auxiliary rendering target (noncached)
Definition: definitions.h:42
This file contains miscellaneous commonly used macros and functions.
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
KIGFX::GAL * GetGAL() const
Function GetGAL() Returns a pointer to the GAL instance used in the panel.
bool OnLayerSelect(int aLayer) override
Function OnLayerSelect is called to notify client code whenever the user selects a different layer...
#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.
wxScrolledWindow * m_LayerScrolledWindow
Definition: layer_widget.h:125
wxWindow * getLayerComp(int aRow, int aColumn) const
Function getLayerComp returns the component within the m_LayersFlexGridSizer at aRow and aCol or NULL...
bool IsGalCanvasActive() const
Function IsGalCanvasActive is used to check which canvas (GAL-based or standard) is currently in use...
Definition: draw_frame.h:921
PAINTER * GetPainter() const
Function GetPainter() Returns the painter object used by the view for drawing VIEW_ITEMS.
Definition: view.h:199
int GetLayerRowCount() const
Function GetLayerRowCount returns the number of rows in the layer tab.
bool IsLayerVisible(int aLayer) const
Function IsLayerVisible tests whether a given layer is visible.
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.
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:774
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...
COLOR4D GetLayerColor(int aLayer) const
Function GetLayerColor gets a layer color for any valid layer.
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
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
EDA_DRAW_PANEL_GAL * GetGalCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
Definition: draw_frame.h:928
#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 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
bool IsElementVisible(int aLayerID) const
Function IsElementVisible tests whether a given element category is visible.