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 <[email protected]>
6 * Copyright (C) 2018-2022 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 <wx/checkbox.h>
27#include <wx/filedlg.h>
28#include <bitmaps.h>
29#include <menus_helpers.h>
30#include <gerbview.h>
32#include <gerbview_frame.h>
34#include <core/arraydim.h>
35#include <view/view.h>
36#include <gerbview_painter.h>
39#include <tool/tool_manager.h>
41
42#include "layer_widget.h"
45#include "dcode_selection_box.h"
46
47
48GERBER_LAYER_WIDGET::GERBER_LAYER_WIDGET( GERBVIEW_FRAME* aParent, wxWindow* aFocusOwner ) :
49 LAYER_WIDGET( aParent, aFocusOwner ),
50 m_frame( aParent )
51{
53
55
56 // Update default tabs labels for GerbView
58
59 // handle the popup menu over the layer window.
60 m_LayerScrolledWindow->Connect( wxEVT_RIGHT_DOWN,
61 wxMouseEventHandler( GERBER_LAYER_WIDGET::onRightDownLayers ),
62 nullptr, this );
63
64 // since Popupmenu() calls this->ProcessEvent() we must call this->Connect()
65 // and not m_LayerScrolledWindow->Connect()
66 Connect( ID_LAYER_MANAGER_START, ID_LAYER_MANAGER_END, wxEVT_COMMAND_MENU_SELECTED,
67 wxCommandEventHandler( GERBER_LAYER_WIDGET::onPopupSelection ), nullptr, this );
68}
69
70
72{
74}
75
76
78{
79 m_notebook->SetPageText( 0, _( "Layers" ) );
80 m_notebook->SetPageText( 1, _( "Items" ) );
81}
82
83
85{
86 std::vector<int>render_layers{ LAYER_DCODES, LAYER_NEGATIVE_OBJECTS, LAYER_GERBVIEW_GRID,
89
90 for( int layer: render_layers )
91 {
92 int row = findRenderRow( layer );
93
94 if( row < 0 )
95 continue;
96
98
99 if( color != COLOR4D::UNSPECIFIED )
100 aColorSettings->SetColor( layer, color );
101 }
102
103 for( int layer = GERBVIEW_LAYER_ID_START; layer < GERBVIEW_LAYER_ID_START + GERBER_DRAWLAYERS_COUNT; layer++ )
104 {
105 int row = findLayerRow( layer - GERBVIEW_LAYER_ID_START );
106
107 if( row < 0 ) // Not existing in layer list
108 continue;
109
110 COLOR4D color = GetLayerColor( row );
111
112 if( color != COLOR4D::UNSPECIFIED )
113 aColorSettings->SetColor( layer, color );
114 }
115}
116
117
119{
121
122 // Fixed "Rendering" tab rows within the LAYER_WIDGET, only the initial color
123 // is changed before appending to the LAYER_WIDGET. This is an automatic variable
124 // not a static variable, change the color & state after copying from code to renderRows
125 // on the stack.
126 LAYER_WIDGET::ROW renderRows[7] = {
127
128#define RR LAYER_WIDGET::ROW // Render Row abbreviation to reduce source width
129
130 RR( _( "DCodes" ), LAYER_DCODES, WHITE,
131 _( "Show DCodes identification" ) ),
132 RR( _( "Negative Objects" ), LAYER_NEGATIVE_OBJECTS, DARKGRAY,
133 _( "Show negative objects in this color" ) ),
134 RR(),
135 RR( _( "Grid" ), LAYER_GERBVIEW_GRID, WHITE,
136 _( "Show the (x,y) grid dots" ) ),
137 RR( _( "Drawing Sheet" ), LAYER_GERBVIEW_DRAWINGSHEET, DARKRED,
138 _( "Show drawing sheet border and title block") ),
139 RR( _( "Page Limits" ), LAYER_GERBVIEW_PAGE_LIMITS, WHITE,
140 _( "Show drawing sheet page limits" ) ),
141 RR( _( "Background" ), LAYER_GERBVIEW_BACKGROUND, BLACK,
142 _( "PCB Background" ), true, false )
143 };
144
145 for( unsigned row = 0; row < arrayDim( renderRows ); ++row )
146 {
147 if( renderRows[row].color != COLOR4D::UNSPECIFIED ) // does this row show a color?
148 renderRows[row].color = m_frame->GetVisibleElementColor( renderRows[row].id );
149
150 if( renderRows[row].id ) // if not the separator
151 renderRows[row].state = m_frame->IsElementVisible( renderRows[row].id );
152 }
153
154 AppendRenderRows( renderRows, arrayDim(renderRows) );
155}
156
157
159{
160 // Remember: menu text is capitalized (see our rules_for_capitalization_in_Kicad_UI.txt)
161 AddMenuItem( aMenu, ID_SHOW_ALL_LAYERS, _( "Show All Layers" ),
163
165 _( "Hide All Layers But Active" ),
167
169 _( "Always Hide All Layers But Active" ),
171
172 AddMenuItem( aMenu, ID_SHOW_NO_LAYERS, _( "Hide All Layers" ),
174
175 aMenu->AppendSeparator();
176
177 AddMenuItem( aMenu, ID_SORT_GBR_LAYERS_X2, _( "Sort Layers if X2 Mode" ),
179
180 AddMenuItem( aMenu, ID_SORT_GBR_LAYERS_FILE_EXT, _( "Sort Layers by File Extension" ),
182
183 aMenu->AppendSeparator();
184
185 AddMenuItem( aMenu, ID_LAYER_MOVE_UP, _( "Move Current Layer Up" ), KiBitmap( BITMAPS::up ) );
186
187 AddMenuItem( aMenu, ID_LAYER_MOVE_DOWN, _( "Move Current Layer Down" ),
189
190 AddMenuItem( aMenu, ID_LAYER_DELETE, _( "Clear Current Layer..." ),
192}
193
194
195void GERBER_LAYER_WIDGET::onRightDownLayers( wxMouseEvent& event )
196{
197 wxMenu menu;
198
199 AddRightClickMenuItems( &menu );
200 PopupMenu( &menu );
201
202 passOnFocus();
203}
204
205
206void GERBER_LAYER_WIDGET::onPopupSelection( wxCommandEvent& event )
207{
208 int layer;
209 int rowCount;
210 int menuId = event.GetId();
211 bool visible = (menuId == ID_SHOW_ALL_LAYERS) ? true : false;
212 LSET visibleLayers;
213 bool force_active_layer_visible;
214
215 switch( menuId )
216 {
221 // Set the display layers options. Sorting layers has no effect to these options
223 force_active_layer_visible = ( menuId == ID_SHOW_NO_LAYERS_BUT_ACTIVE ||
225
226 // Update icons and check boxes
227 rowCount = GetLayerRowCount();
228
229 for( int row = 0; row < rowCount; ++row )
230 {
231 wxCheckBox* cb = (wxCheckBox*) getLayerComp( row, COLUMN_COLOR_LYR_CB );
232 layer = getDecodedId( cb->GetId() );
233 bool loc_visible = visible;
234
235 if( force_active_layer_visible && (layer == m_frame->GetActiveLayer() ) )
236 loc_visible = true;
237
238 cb->SetValue( loc_visible );
239 visibleLayers[ row ] = loc_visible;
240 }
241
242 m_frame->SetVisibleLayers( visibleLayers );
244 break;
245
248 break;
249
252 break;
253
254 case ID_LAYER_MOVE_UP:
256 break;
257
260 break;
261
262 case ID_LAYER_DELETE:
264
265 break;
266 }
267}
268
270{
272 return false;
273
274 // postprocess after active layer selection ensure active layer visible
275 wxCommandEvent event;
277 onPopupSelection( event );
278 return true;
279}
280
281
283{
285
286 Freeze();
287
288 for( int layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer )
289 {
290 // Don't show inactive layers
291 if ( GetImagesList()->GetGbrImage(layer) == nullptr )
292 continue;
293
294 int aRow = findLayerRow( layer );
295 bool visible = true;
297 wxString msg = GetImagesList()->GetDisplayName( layer,
298 /* include layer number */ false,
299 /* Get the full name */ true );
300
301 if( m_frame->GetCanvas() )
302 visible = m_frame->GetCanvas()->GetView()->IsLayerVisible( GERBER_DRAW_LAYER( layer ) );
303 else
304 visible = m_frame->IsLayerVisible( layer );
305
306 if( aRow >= 0 )
307 {
308 updateLayerRow( findLayerRow( layer ), msg );
309 SetLayerVisible( layer, visible );
310 }
311 else
312 AppendLayerRow( LAYER_WIDGET::ROW( msg, layer, color, wxEmptyString, visible, true ) );
313 }
314
316 Thaw();
317}
318
319
321{
322 AddRightClickMenuItems( &aMenu );
323}
324
325
326void GERBER_LAYER_WIDGET::OnLayerColorChange( int aLayer, const COLOR4D& aColor )
327{
328 // NOTE: Active layer in GerbView is stored as 0-indexed, but layer color is
329 // stored according to the GERBER_DRAW_LAYER() offset.
330 m_frame->SetLayerColor( GERBER_DRAW_LAYER( aLayer ), aColor );
332
333 KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
334 COLOR_SETTINGS* color_settings = m_frame->GetColorSettings();
335 color_settings->SetColor( aLayer, aColor );
336
337 view->GetPainter()->GetSettings()->LoadColors( color_settings );
338 view->UpdateLayerColor( GERBER_DRAW_LAYER( aLayer ) );
339
341}
342
343
345{
346 // the layer change from the GERBER_LAYER_WIDGET can be denied by returning
347 // false from this function.
348 int layer = m_frame->GetActiveLayer();
349
350 m_frame->SetActiveLayer( aLayer, false );
352
353 if( layer != m_frame->GetActiveLayer() )
354 {
355 if( ! OnLayerSelected() )
356 {
357 auto settings = static_cast<KIGFX::GERBVIEW_PAINTER*>
358 ( m_frame->GetCanvas()->GetView()->GetPainter() )->GetSettings();
359 int dcodeSelected = m_frame->m_DCodeSelector->GetSelectedDCodeId();
360 settings->m_dcodeHighlightValue = dcodeSelected;
363 }
364 }
365
366 return true;
367}
368
369
370void GERBER_LAYER_WIDGET::OnLayerVisible( int aLayer, bool isVisible, bool isFinal )
371{
372 LSET visibleLayers = m_frame->GetVisibleLayers();
373
374 visibleLayers[ aLayer ] = isVisible;
375
376 m_frame->SetVisibleLayers( visibleLayers );
377
378 if( isFinal )
380}
381
382
384{
385 m_frame->SetVisibleElementColor( aId, aColor );
386
387 auto view = m_frame->GetCanvas()->GetView();
388
389 COLOR_SETTINGS* color_settings = m_frame->GetColorSettings();
390 color_settings->SetColor( aId, aColor );
391
392 view->GetPainter()->GetSettings()->LoadColors( color_settings );
393 view->UpdateLayerColor( aId );
394 view->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
395 view->UpdateAllItems( KIGFX::COLOR );
397}
398
399
400void GERBER_LAYER_WIDGET::OnRenderEnable( int aId, bool isEnabled )
401{
402 m_frame->SetElementVisibility( aId, isEnabled );
403
404 if( m_frame->GetCanvas() )
405 {
406 if( aId == LAYER_GERBVIEW_GRID )
407 {
410 }
411 else
412 {
413 m_frame->GetCanvas()->GetView()->SetLayerVisible( aId, isEnabled );
414 }
415 }
416
418}
int color
Definition: DXF_plotter.cpp:57
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition: arraydim.h:31
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:106
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:266
@ select_w_layer
@ show_no_layers
@ delete_gerber
@ show_all_layers
Color settings are a bit different than most of the settings objects in that there can be more than o...
void SetColor(int aLayer, const COLOR4D &aColor)
virtual EDA_DRAW_PANEL_GAL * GetCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
bool IsGridVisible() const
virtual KIGFX::VIEW * GetView() const
Return a pointer to the #VIEW instance used in the panel.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
Update the board display after modifying it by a python script (note: it is automatically called by a...
KIGFX::GAL * GetGAL() const
Return a pointer to the GAL 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...
static GERBER_FILE_IMAGE_LIST & GetImagesList()
const wxString GetDisplayName(int aIdx, bool aNameOnly=false, bool aFullName=false)
Get the display name for the layer at aIdx.
GERBER_FILE_IMAGE_LIST * GetImagesList()
void OnRenderEnable(int aId, bool isEnabled) override
Notify client code whenever the user changes an rendering enable in one of the rendering checkboxes.
void onPopupSelection(wxCommandEvent &event)
bool OnLayerSelect(int aLayer) override
Notify client code whenever the user selects a different layer.
void OnLayerRightClick(wxMenu &aMenu) override
Notify client code about a layer being right-clicked.
void onRightDownLayers(wxMouseEvent &event)
Put up a popup menu for the layer panel.
void OnLayerVisible(int aLayer, bool isVisible, bool isFinal) override
Notify client code about a layer visibility change.
void CollectCurrentColorSettings(COLOR_SETTINGS *aColorSettings)
Collect the current color settings and put it in aColorSettings.
void SetLayersManagerTabsText()
Update the layer manager tabs labels.
void AddRightClickMenuItems(wxMenu *aMenu)
Add menu items to a menu that should be shown when right-clicking the Gerber layer widget.
bool OnLayerSelected()
Ensure the active layer is visible, and other layers not visible when m_alwaysShowActiveLayer is true...
GERBER_LAYER_WIDGET(GERBVIEW_FRAME *aParent, wxWindow *aFocusOwner)
void OnLayerColorChange(int aLayer, const COLOR4D &aColor) override
Notify client code about a layer color change.
void OnRenderColorChange(int aId, const COLOR4D &aColor) override
Notify client code whenever the user changes a rendering color.
void ReFillRender()
Rebuild Render for instance after the config is read.
void ReFill()
Rebuild Render for instance after the config is read.
static TOOL_ACTION moveLayerUp
static TOOL_ACTION moveLayerDown
COLOR_SETTINGS * GetColorSettings(bool aForceRefresh=false) const override
Returns a pointer to the active color theme settings.
void SetLayerColor(int aLayer, const COLOR4D &aColor)
COLOR4D GetVisibleElementColor(int aLayerID)
Return the color of a gerber visible element.
bool IsLayerVisible(int aLayer) const
Test whether a given layer is visible.
void SortLayersByX2Attributes()
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
GBR_LAYER_BOX_SELECTOR * m_SelLayerBox
void syncLayerBox(bool aRebuildLayerBox=false)
Update the currently "selected" layer within m_SelLayerBox.
int GetActiveLayer() const
Return the active layer.
bool IsElementVisible(int aLayerID) const
Test whether a given element category is visible.
DCODE_SELECTION_BOX * m_DCodeSelector
void SetActiveLayer(int aLayer, bool doLayerWidgetUpdate=true)
change the currently active layer to aLayer and update the GERBER_LAYER_WIDGET.
void SetVisibleElementColor(int aLayerID, const COLOR4D &aColor)
void SetVisibleLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings.
COLOR4D GetLayerColor(int aLayer) const
void SortLayersByFileExtension()
void Erase_Current_DrawLayer(bool query)
void SetElementVisibility(int aLayerID, bool aNewState)
Change the visibility of an element category.
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:102
void SetGridVisibility(bool aVisibility)
Set the visibility setting of the grid.
Methods for drawing GerbView specific items.
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
virtual void LoadColors(const COLOR_SETTINGS *aSettings)
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:69
void SetLayerVisible(int aLayer, bool aVisible=true)
Control the visibility of a particular layer.
Definition: view.h:393
void UpdateAllItems(int aUpdateFlags)
Update all items in the view according to the given flags.
Definition: view.cpp:1484
void UpdateLayerColor(int aLayer)
Apply the new coloring scheme held by RENDER_SETTINGS in case that it has changed.
Definition: view.cpp:740
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:410
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:213
void MarkTargetDirty(int aTarget)
Set or clear target 'dirty' flag.
Definition: view.h:617
Manage a list of layers with the notion of a "current" layer, and layer specific visibility control.
Definition: layer_widget.h:78
static int getDecodedId(int aControlId)
Decode aControlId to original un-encoded value.
void AppendRenderRows(const ROW *aRowsArray, int aRowCount)
Append new rows in the render portion of the widget.
Definition: layer_widget.h:200
int GetLayerRowCount() const
Return the number of rows in the layer tab.
void UpdateLayouts()
void passOnFocus()
Give away the keyboard focus up to the main parent window.
COLOR4D GetRenderColor(int aRow) const
Return the color of the Render ROW in position aRow.
void updateLayerRow(int aRow, const wxString &aName)
int findLayerRow(int aLayer) const
Return the row index that aLayer resides in, or -1 if not found.
int findRenderRow(int aId) const
void SetLayerVisible(int aLayer, bool isVisible)
Set aLayer visible or not.
void ClearLayerRows()
Empty out the layer rows.
wxWindow * getLayerComp(int aRow, int aColumn) const
Return the component within the m_LayersFlexGridSizer at aRow and aCol or NULL if these parameters ar...
void AppendLayerRow(const ROW &aRow)
Append a new row in the layer portion of the widget.
void ClearRenderRows()
Empty out the render rows.
COLOR4D GetLayerColor(int aLayer) const
Return the color of the layer ROW associated with aLayer id.
wxNotebook * m_notebook
Definition: layer_widget.h:465
wxScrolledWindow * m_LayerScrolledWindow
Definition: layer_widget.h:467
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:532
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:54
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:142
@ WHITE
Definition: color4d.h:46
@ DARKGRAY
Definition: color4d.h:44
@ DARKRED
Definition: color4d.h:51
@ BLACK
Definition: color4d.h:42
#define _(s)
#define RR
@ LAYER_GERBVIEW_DRAWINGSHEET
Definition: layer_ids.h:419
@ GERBVIEW_LAYER_ID_START
Definition: layer_ids.h:409
@ LAYER_GERBVIEW_BACKGROUND
Definition: layer_ids.h:418
@ LAYER_DCODES
Definition: layer_ids.h:414
@ LAYER_NEGATIVE_OBJECTS
Definition: layer_ids.h:415
@ LAYER_GERBVIEW_PAGE_LIMITS
Definition: layer_ids.h:420
@ LAYER_GERBVIEW_GRID
Definition: layer_ids.h:416
#define GERBER_DRAWLAYERS_COUNT
Definition: layer_ids.h:404
#define GERBER_DRAW_LAYER(x)
Definition: layer_ids.h:425
#define COLUMN_COLOR_LYR_CB
Definition: layer_widget.h:53
Macros and inline functions to create menus items in menubars or popup menus.
@ COLOR
Color has changed.
Definition: view_item.h:48
@ TARGET_NONCACHED
Auxiliary rendering target (noncached)
Definition: definitions.h:49
Provide all the data needed to add a row to a LAYER_WIDGET.
Definition: layer_widget.h:85
COLOR4D color
COLOR4D::UNSPECIFIED if none.
Definition: layer_widget.h:88
bool state
initial wxCheckBox state
Definition: layer_widget.h:89