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 
216  if( myframe->IsGalCanvasActive() )
217  {
218  for( int layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer )
219  {
221  GetLayerColor( GERBER_DRAW_LAYER( layer ) ) );
222  }
223  }
224 
225  myframe->GetCanvas()->Refresh();
226  break;
227  }
228 }
229 
231 {
233  return false;
234 
235  // postprocess after active layer selection
236  // ensure active layer visible
237  wxCommandEvent event;
239  onPopupSelection( event );
240  return true;
241 }
242 
243 
245 {
246  Freeze();
247 
248  ClearLayerRows();
249 
250  for( int layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer )
251  {
252  wxString msg = GetImagesList()->GetDisplayName( layer );
253 
254  bool visible = true;
255  if( auto canvas = myframe->GetGalCanvas() )
256  {
257  visible = canvas->GetView()->IsLayerVisible( GERBER_DRAW_LAYER( layer ) );
258  }
259  else
260  {
261  visible = myframe->IsLayerVisible( layer );
262  }
263 
266  wxEmptyString, visible, true ) );
267  }
268 
269  Thaw();
270 }
271 
272 //-----<LAYER_WIDGET callbacks>-------------------------------------------
273 
275 {
276  AddRightClickMenuItems( aMenu );
277 }
278 
280 {
281  myframe->SetLayerColor( aLayer, aColor );
283 
284  if( myframe->IsGalCanvasActive() )
285  {
286  KIGFX::VIEW* view = myframe->GetGalCanvas()->GetView();
288  view->UpdateLayerColor( aLayer );
289  }
290 
291  myframe->GetCanvas()->Refresh();
292 }
293 
295 {
296  // the layer change from the GERBER_LAYER_WIDGET can be denied by returning
297  // false from this function.
298  int layer = myframe->GetActiveLayer( );
299  // TODO(JE) ActiveLayer is stored as an index from 0 rather than as a layer
300  // id matching GERBER_DRAW_LAYER( idx ), is this what we want long-term?
301  myframe->SetActiveLayer( GERBER_DRAW_LAYER_INDEX( aLayer ), false );
303 
304  if( layer != myframe->GetActiveLayer( ) )
305  {
306  if( ! OnLayerSelected() )
307  myframe->GetCanvas()->Refresh();
308  }
309 
310  return true;
311 }
312 
313 void GERBER_LAYER_WIDGET::OnLayerVisible( int aLayer, bool isVisible, bool isFinal )
314 {
315  long visibleLayers = myframe->GetVisibleLayers();
316 
317  if( isVisible )
318  visibleLayers |= 1 << ( aLayer - GERBVIEW_LAYER_ID_START );
319  else
320  visibleLayers &= ~( 1 << ( aLayer - GERBVIEW_LAYER_ID_START ) );
321 
322  myframe->SetVisibleLayers( visibleLayers );
323 
324  if( isFinal )
325  myframe->GetCanvas()->Refresh();
326 }
327 
329 {
331 
332  auto galCanvas = myframe->GetGalCanvas();
333 
334  if( galCanvas && myframe->IsGalCanvasActive() )
335  {
336  auto view = galCanvas->GetView();
338  view->UpdateLayerColor( aId );
339  // TODO(JE) Why are the below two lines needed? Not needed in pcbnew
340  view->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
341  view->RecacheAllItems();
342  }
343 
344  if( galCanvas && myframe->IsGalCanvasActive() )
345  galCanvas->Refresh();
346  else
347  myframe->GetCanvas()->Refresh();
348 }
349 
350 void GERBER_LAYER_WIDGET::OnRenderEnable( int aId, bool isEnabled )
351 {
352  myframe->SetElementVisibility( (GERBVIEW_LAYER_ID) aId, isEnabled );
353 
354  auto galCanvas = myframe->GetGalCanvas();
355 
356  if( galCanvas )
357  {
358  if( aId == LAYER_GERBVIEW_GRID )
359  {
360  galCanvas->GetGAL()->SetGridVisibility( myframe->IsGridVisible() );
361  galCanvas->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
362  // TODO(JE) Why is the below line needed? Not needed in pcbnew
363  galCanvas->GetView()->RecacheAllItems();
364  }
365  else
366  galCanvas->GetView()->SetLayerVisible( aId, isEnabled );
367  }
368 
369  if( galCanvas && myframe->IsGalCanvasActive() )
370  galCanvas->Refresh();
371  else
372  myframe->GetCanvas()->Refresh();
373 }
374 
375 //-----</LAYER_WIDGET callbacks>------------------------------------------
376 
377 /*
378  * Virtual Function useAlternateBitmap
379  * return true if bitmaps shown in Render layer list
380  * must be alternate bitmap (when a gerber image is loaded), or false to use "normal" bitmap
381  */
383 {
384  return GetImagesList()->GetGbrImage( aRow ) != NULL;
385 }
#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:331
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
COLOR4D GetLayerColor(LAYER_NUM aLayer) const
Function GetLayerColor returns the color of the layer ROW associated with aLayer id.
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:475
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:856
#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:864
#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