KiCad PCB EDA Suite
class_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) 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 
32 #include <fctsys.h>
33 #include <common.h>
34 #include <class_drawpanel.h>
35 #include <macros.h>
37 
38 #include <gerbview.h>
39 #include <gerbview_frame.h>
41 #include <layer_widget.h>
43 
44 #include <view/view.h>
45 #include <gerbview_painter.h>
47 
48 
49 /*
50  * Class GERBER_LAYER_WIDGET
51  * is here to implement the abtract functions of LAYER_WIDGET so they
52  * may be tied into the GERBVIEW_FRAME's data and so we can add a popup
53  * menu which is specific to Pcbnew's needs.
54  */
55 
56 
58  int aPointSize ) :
59  LAYER_WIDGET( aParent, aFocusOwner, aPointSize ),
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, _("Layer") );
96  m_notebook->SetPageText(1, _("Render") );
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[3] = {
112 
113 #define RR LAYER_WIDGET::ROW // Render Row abreviation to reduce source width
114 
115  // text id color tooltip checked
116  RR( _( "Grid" ), LAYER_GERBVIEW_GRID, WHITE, _( "Show the (x,y) grid dots" ) ),
117  RR( _( "DCodes" ), LAYER_DCODES, WHITE, _( "Show DCodes identification" ) ),
118  RR( _( "Neg. Obj." ), LAYER_NEGATIVE_OBJECTS, DARKGRAY,
119  _( "Show negative objects in this color" ) ),
120  };
121 
122  for( unsigned row=0; row<DIM(renderRows); ++row )
123  {
124  if( renderRows[row].color != COLOR4D::UNSPECIFIED ) // does this row show a color?
125  {
126  renderRows[row].color = myframe->GetVisibleElementColor(
127  ( GERBVIEW_LAYER_ID )renderRows[row].id );
128  }
129  renderRows[row].state = myframe->IsElementVisible(
130  ( GERBVIEW_LAYER_ID )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  menu.Append( new wxMenuItem( &menu, ID_SHOW_ALL_LAYERS,
141  _("Show All Layers") ) );
142 
143  menu.Append( new wxMenuItem( &menu, ID_SHOW_NO_LAYERS_BUT_ACTIVE,
144  _( "Hide All Layers But Active" ) ) );
145 
146  menu.Append( new wxMenuItem( &menu, ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE,
147  _( "Always Hide All Layers But Active" ) ) );
148 
149  menu.Append( new wxMenuItem( &menu, ID_SHOW_NO_LAYERS,
150  _( "Hide All Layers" ) ) );
151 
152  menu.AppendSeparator();
153  menu.Append( new wxMenuItem( &menu, ID_SORT_GBR_LAYERS,
154  _( "Sort Layers if X2 Mode" ) ) );
155 }
156 
157 
158 void GERBER_LAYER_WIDGET::onRightDownLayers( wxMouseEvent& event )
159 {
160  wxMenu menu;
161 
162  AddRightClickMenuItems( menu );
163  PopupMenu( &menu );
164 
165  passOnFocus();
166 }
167 
168 void GERBER_LAYER_WIDGET::onPopupSelection( wxCommandEvent& event )
169 {
170  int rowCount;
171  int menuId = event.GetId();
172  bool visible = (menuId == ID_SHOW_ALL_LAYERS) ? true : false;
173  long visibleLayers = 0;
174  bool force_active_layer_visible;
175 
177  force_active_layer_visible = ( menuId == ID_SHOW_NO_LAYERS_BUT_ACTIVE ||
179 
180  switch( menuId )
181  {
182  case ID_SHOW_ALL_LAYERS:
183  case ID_SHOW_NO_LAYERS:
186  rowCount = GetLayerRowCount();
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 &&
194  (layer == GERBER_DRAW_LAYER( myframe->GetActiveLayer() ) ) )
195  {
196  loc_visible = true;
197  }
198 
199  cb->SetValue( loc_visible );
200 
201  if( loc_visible )
202  visibleLayers |= 1 << row;
203  else
204  visibleLayers &= ~( 1 << row );
205  }
206 
207  myframe->SetVisibleLayers( visibleLayers );
208  myframe->GetCanvas()->Refresh();
209  break;
210 
211  case ID_SORT_GBR_LAYERS:
214  myframe->syncLayerBox( true );
215  myframe->GetCanvas()->Refresh();
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  if( auto canvas = myframe->GetGalCanvas() )
246  {
247  visible = canvas->GetView()->IsLayerVisible( GERBER_DRAW_LAYER( layer ) );
248  }
249  else
250  {
251  visible = myframe->IsLayerVisible( layer );
252  }
253 
256  wxEmptyString, visible, true ) );
257  }
258 
259  Thaw();
260 }
261 
262 //-----<LAYER_WIDGET callbacks>-------------------------------------------
263 
265 {
266  AddRightClickMenuItems( aMenu );
267 }
268 
270 {
271  myframe->SetLayerColor( aLayer, aColor );
273 
274  if( myframe->IsGalCanvasActive() )
275  {
276  KIGFX::VIEW* view = myframe->GetGalCanvas()->GetView();
278  view->UpdateLayerColor( aLayer );
279  }
280 
281  myframe->GetCanvas()->Refresh();
282 }
283 
285 {
286  // the layer change from the GERBER_LAYER_WIDGET can be denied by returning
287  // false from this function.
288  int layer = myframe->GetActiveLayer( );
289  // TODO(JE) ActiveLayer is stored as an index from 0 rather than as a layer
290  // id matching GERBER_DRAW_LAYER( idx ), is this what we want long-term?
291  myframe->SetActiveLayer( GERBER_DRAW_LAYER_INDEX( aLayer ), false );
293 
294  if( layer != myframe->GetActiveLayer( ) )
295  {
296  if( ! OnLayerSelected() )
297  myframe->GetCanvas()->Refresh();
298  }
299 
300  return true;
301 }
302 
303 void GERBER_LAYER_WIDGET::OnLayerVisible( int aLayer, bool isVisible, bool isFinal )
304 {
305  long visibleLayers = myframe->GetVisibleLayers();
306 
307  if( isVisible )
308  visibleLayers |= 1 << ( aLayer - GERBVIEW_LAYER_ID_START );
309  else
310  visibleLayers &= ~( 1 << ( aLayer - GERBVIEW_LAYER_ID_START ) );
311 
312  myframe->SetVisibleLayers( visibleLayers );
313 
314  if( isFinal )
315  myframe->GetCanvas()->Refresh();
316 }
317 
319 {
321 
322  auto galCanvas = myframe->GetGalCanvas();
323 
324  if( galCanvas && myframe->IsGalCanvasActive() )
325  {
326  auto view = galCanvas->GetView();
328  view->UpdateLayerColor( aId );
329  // TODO(JE) Why are the below two lines needed? Not needed in pcbnew
330  view->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
331  view->RecacheAllItems();
332  }
333 
334  if( galCanvas && myframe->IsGalCanvasActive() )
335  galCanvas->Refresh();
336  else
337  myframe->GetCanvas()->Refresh();
338 }
339 
340 void GERBER_LAYER_WIDGET::OnRenderEnable( int aId, bool isEnabled )
341 {
342  myframe->SetElementVisibility( (GERBVIEW_LAYER_ID) aId, isEnabled );
343 
344  auto galCanvas = myframe->GetGalCanvas();
345 
346  if( galCanvas )
347  {
348  if( aId == LAYER_GERBVIEW_GRID )
349  {
350  galCanvas->GetGAL()->SetGridVisibility( myframe->IsGridVisible() );
351  galCanvas->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
352  // TODO(JE) Why is the below line needed? Not needed in pcbnew
353  galCanvas->GetView()->RecacheAllItems();
354  }
355  else
356  galCanvas->GetView()->SetLayerVisible( aId, isEnabled );
357  }
358 
359  if( galCanvas && myframe->IsGalCanvasActive() )
360  galCanvas->Refresh();
361  else
362  myframe->GetCanvas()->Refresh();
363 }
364 
365 //-----</LAYER_WIDGET callbacks>------------------------------------------
366 
367 /*
368  * Virtual Function useAlternateBitmap
369  * return true if bitmaps shown in Render layer list
370  * must be alternate bitmap (when a gerber i¨mage is loaded), or false to use "normal" bitmap
371  */
373 {
374  return GetImagesList()->GetGbrImage( aRow ) != NULL;
375 }
#define DIM(x)
of elements in an array
Definition: macros.h:98
wxAuiNotebook * m_notebook
Definition: layer_widget.h:110
void OnLayerColorChange(int aLayer, COLOR4D aColor) override
Function OnLayerColorChange is called to notify client code about a layer color change.
void AddRightClickMenuItems(wxMenu &menu)
Function addRightClickMenuItems add menu items to a menu that should be shown when right-clicking the...
Struct ROW provides all the data needed to add a row to a LAYER_WIDGET.
Definition: layer_widget.h:85
void onRightDownLayers(wxMouseEvent &event)
Function OnRightDownLayers puts up a popup menu for the layer panel.
virtual void Refresh(bool eraseBackground=true, const wxRect *rect=NULL) override
Update the board display after modifying it bu a python script (note: it is automatically called by a...
Definition: draw_panel.cpp:325
EDA_DRAW_PANEL * GetCanvas()
Definition: draw_frame.h:337
const wxString GetDisplayName(int aIdx, bool aNameOnly=false)
void SetVisibleElementColor(GERBVIEW_LAYER_ID aItemIdVisible, COLOR4D aColor)
void syncLayerBox(bool aRebuildLayerBox=false)
Function syncLayerBox updates the currently "selected" layer within m_SelLayerBox The currently activ...
void SortImagesByZOrder()
Sort loaded images by Z order priority, if they have the X2 FileFormat info (SortImagesByZOrder updat...
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
GERBER_FILE_IMAGE_LIST * GetImagesList()
KIGFX::VIEW * GetView() const
Function GetView() Returns a pointer to the VIEW instance used in the panel.
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.
GERBVIEW_LAYER_ID
GerbView draw layers.
bool state
initial wxCheckBox state
Definition: layer_widget.h:90
GERBER_LAYER_WIDGET(GERBVIEW_FRAME *aParent, wxWindow *aFocusOwner, int aPointSize=10)
Constructor.
virtual bool IsGridVisible() const
Function IsGridVisible() , virtual.
Definition: draw_frame.h:481
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 ...
COLOR4D color
COLOR4D::UNSPECIFIED if none.
Definition: layer_widget.h:89
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...
COLOR4D GetVisibleElementColor(GERBVIEW_LAYER_ID aItemIdVisible)
Function GetVisibleElementColor returns the color of a gerber visible element.
#define GERBER_DRAW_LAYER_INDEX(x)
#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:112
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:862
#define RR
PAINTER * GetPainter() const
Function GetPainter() Returns the painter object used by the view for drawing VIEW_ITEMS.
Definition: view.h:196
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:310
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:657
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:77
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:53
void SetElementVisibility(GERBVIEW_LAYER_ID aItemIdVisible, bool aNewState)
Function SetElementVisibility changes the visibility of an element category.
bool IsElementVisible(GERBVIEW_LAYER_ID aItemIdVisible) const
Function IsElementVisible tests whether a given element category is visible.
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
Function GetGalCanvas returns a pointer to GAL-based canvas of given EDA draw frame.
Definition: draw_frame.h:870
#define GERBER_DRAW_LAYER(x)
void ReFillRender()
Function ReFillRender Rebuild Render for instance after the config is read.
Class VIEW.
Definition: view.h:58
bool OnLayerSelected()
Function OnLayerSelected ensure the active layer is visible, and other layers not visible when m_alwa...
void ReFillLayerWidget()
Function ReFillLayerWidget changes out all the layers in m_Layers and may be called upon loading new ...
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39