KiCad PCB EDA Suite
gerbview_inspection_tool.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) 2017 Jon Evans <jon@craftyjon.com>
5  * Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software: you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the
9  * Free Software Foundation, either version 3 of the License, or (at your
10  * option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 
22 #include <eda_item.h>
23 #include <bitmaps.h>
24 #include <class_draw_panel_gal.h>
26 #include <gestfich.h>
27 #include <gerber_file_image.h>
28 #include <gerbview_id.h>
30 #include "gerbview_actions.h"
31 #include <painter.h>
32 #include <pgm_base.h>
35 #include <tool/tool_event.h>
36 #include <tool/tool_manager.h>
37 #include <view/view.h>
38 #include <view/view_controls.h>
39 #include <view/view_group.h>
40 #include <wx/msgdlg.h>
41 #include <wx/textdlg.h>
42 #include <wx/choicdlg.h>
43 
44 
46  TOOL_INTERACTIVE( "gerbview.Inspection" ),
47  m_frame( nullptr )
48 {
49 }
50 
51 
53 {
54 }
55 
56 
58 {
59  return true;
60 }
61 
62 
64 {
65  m_frame = getEditFrame<GERBVIEW_FRAME>();
66 }
67 
68 
70 {
71  int ii, jj;
72  wxString Line;
73  wxArrayString list;
74  int curr_layer = m_frame->GetActiveLayer();
75 
76  double scale = 1.0;
77  wxString units;
78 
79  switch( m_frame->GetUserUnits() )
80  {
82  scale = IU_PER_MM;
83  units = "mm";
84  break;
85 
86  case EDA_UNITS::INCHES:
87  scale = IU_PER_MILS * 1000;
88  units = "in";
89  break;
90 
91  case EDA_UNITS::MILS:
93  units = "mil";
94  break;
95 
96  default:
97  wxASSERT_MSG( false, "Invalid units" );
98  }
99 
100  for( unsigned int layer = 0; layer < m_frame->ImagesMaxCount(); ++layer )
101  {
102  GERBER_FILE_IMAGE* gerber = m_frame->GetGbrImage( layer );
103 
104  if( !gerber )
105  continue;
106 
107  if( gerber->GetDcodesCount() == 0 )
108  continue;
109 
110  if( curr_layer == static_cast<int>( layer ) )
111  Line.Printf( wxT( "*** Active layer (%2.2d) ***" ), layer + 1 );
112  else
113  Line.Printf( wxT( "*** layer %2.2d ***" ), layer + 1 );
114 
115  list.Add( Line );
116 
117  for( ii = 0, jj = 1; ii < TOOLS_MAX_COUNT; ii++ )
118  {
119  D_CODE* pt_D_code = gerber->GetDCODE( ii + FIRST_DCODE );
120 
121  if( pt_D_code == nullptr )
122  continue;
123 
124  if( !pt_D_code->m_InUse && !pt_D_code->m_Defined )
125  continue;
126 
127  Line.Printf( wxT( "tool %2.2d: D%2.2d V %.4f %s H %.4f %s %s attribute '%s'" ),
128  jj,
129  pt_D_code->m_Num_Dcode,
130  pt_D_code->m_Size.y / scale, units,
131  pt_D_code->m_Size.x / scale, units,
132  D_CODE::ShowApertureType( pt_D_code->m_Shape ),
133  pt_D_code->m_AperFunction.IsEmpty()? wxT( "none" ) : pt_D_code->m_AperFunction
134  );
135 
136  if( !pt_D_code->m_Defined )
137  Line += wxT( " (not defined)" );
138 
139  if( pt_D_code->m_InUse )
140  Line += wxT( " (in use)" );
141 
142  list.Add( Line );
143  jj++;
144  }
145  }
146 
147  wxSingleChoiceDialog dlg( m_frame, wxEmptyString, _( "D Codes" ), list, (void**) nullptr,
148  wxCHOICEDLG_STYLE & ~wxCANCEL );
149 
150  dlg.ShowModal();
151 
152  return 0;
153 }
154 
155 
157 {
158  int layer = m_frame->GetActiveLayer();
159  GERBER_FILE_IMAGE* gerber_layer = m_frame->GetGbrImage( layer );
160 
161  if( gerber_layer )
162  {
163  wxString editorname = Pgm().GetTextEditor();
164 
165  if( !editorname.IsEmpty() )
166  {
167  wxFileName fn( gerber_layer->m_FileName );
168 
169  // Call the editor only if the Gerber/drill source file is available.
170  // This is not always the case, because it can be a temporary file
171  // if it comes from a zip archive.
172  if( !fn.FileExists() )
173  {
174  wxString msg;
175  msg.Printf( _( "Source file '%s' not found." ), fn.GetFullPath() );
176  wxMessageBox( msg );
177  }
178  else
179  {
180  ExecuteFile( editorname, QuoteFullPath( fn ) );
181  }
182  }
183  else
184  {
185  wxMessageBox( _( "No text editor selected in KiCad. Please choose one." ) );
186  }
187  }
188  else
189  {
190  wxString msg;
191  msg.Printf( _( "No file loaded on the active layer %d." ), layer + 1 );
192  wxMessageBox( msg );
193  }
194 
195  return 0;
196 }
197 
198 
200 
201 
203 {
204  KIGFX::VIEW_CONTROLS& controls = *getViewControls();
205  bool originSet = false;
207  EDA_UNITS units = m_frame->GetUserUnits();
208  KIGFX::PREVIEW::RULER_ITEM ruler( twoPtMgr, units );
209 
210  std::string tool = aEvent.GetCommandStr().get();
211  m_frame->PushTool( tool );
212 
213  auto setCursor =
214  [&]()
215  {
217  };
218 
219  auto cleanup =
220  [&] ()
221  {
222  getView()->SetVisible( &ruler, false );
223  controls.SetAutoPan( false );
224  controls.CaptureCursor( false );
225  originSet = false;
226  };
227 
228  Activate();
229  // Must be done after Activate() so that it gets set into the correct context
230  controls.ShowCursor( true );
231  // Set initial cursor
232  setCursor();
233 
234  getView()->Add( &ruler );
235  getView()->SetVisible( &ruler, false );
236 
237  while( TOOL_EVENT* evt = Wait() )
238  {
239  setCursor();
240  const VECTOR2I cursorPos = controls.GetCursorPosition();
241 
242  if( evt->IsCancelInteractive() )
243  {
244  if( originSet )
245  {
246  cleanup();
247  }
248  else
249  {
250  m_frame->PopTool( tool );
251  break;
252  }
253  }
254  else if( evt->IsActivate() )
255  {
256  if( originSet )
257  cleanup();
258 
259  if( evt->IsMoveTool() )
260  {
261  // leave ourselves on the stack so we come back after the move
262  break;
263  }
264  else
265  {
266  m_frame->PopTool( tool );
267  break;
268  }
269  }
270  else if( !originSet && ( evt->IsDrag( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) )
271  {
272  // click or drag starts
273  twoPtMgr.SetOrigin( cursorPos );
274  twoPtMgr.SetEnd( cursorPos );
275 
276  controls.CaptureCursor( true );
277  controls.SetAutoPan( true );
278 
279  originSet = true;
280  }
281  else if( originSet && ( evt->IsClick( BUT_LEFT ) || evt->IsMouseUp( BUT_LEFT ) ) )
282  {
283  // second click or mouse up after drag ends
284  originSet = false;
285 
286  controls.SetAutoPan( false );
287  controls.CaptureCursor( false );
288  }
289  else if( originSet && ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) )
290  {
291  // move or drag when origin set updates rules
292  twoPtMgr.SetAngleSnap( evt->Modifier( MD_SHIFT ) );
293  twoPtMgr.SetEnd( cursorPos );
294 
295  getView()->SetVisible( &ruler, true );
296  getView()->Update( &ruler, KIGFX::GEOMETRY );
297  }
298  else if( evt->IsAction( &ACTIONS::updateUnits ) )
299  {
300  if( m_frame->GetUserUnits() != units )
301  {
302  units = m_frame->GetUserUnits();
303  ruler.SwitchUnits( units );
304  getView()->Update( &ruler, KIGFX::GEOMETRY );
305  }
306  evt->SetPassEvent();
307  }
308  else if( evt->IsClick( BUT_RIGHT ) )
309  {
311  }
312  else
313  {
314  evt->SetPassEvent();
315  }
316  }
317 
318  getView()->SetVisible( &ruler, false );
319  getView()->Remove( &ruler );
320 
322  return 0;
323 }
324 
325 
327 {
331 }
virtual void ShowCursor(bool aEnabled)
Enable or disables display of cursor.
TOOL_MENU m_menu
The functions below are not yet implemented - their interface may change.
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Suspend execution of the tool until an event specified in aEventList arrives.
wxSize m_Size
Horizontal and vertical dimensions.
Definition: dcode.h:188
static TOOL_ACTION showSource
static constexpr double IU_PER_MM
Mock up a conversion function.
bool m_InUse
false if the aperture (previously defined) is not used to draw something
Definition: dcode.h:197
APERTURE_T m_Shape
shape ( Line, rectangle, circle , oval .. )
Definition: dcode.h:189
Represent a very simple geometry manager for items that have a start and end point.
virtual EDA_DRAW_PANEL_GAL * GetCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
virtual void PushTool(const std::string &actionName)
NB: the definition of "tool" is different at the user level.
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:353
D_CODE * GetDCODE(int aDCODE) const
Return a pointer to the D_CODE within this GERBER for the given aDCODE.
Hold the image data and parameters for one gerber file and layer parameters.
void SwitchUnits(EDA_UNITS aUnits)
Switch the ruler units.
Definition: ruler_item.h:76
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
static TOOL_ACTION measureTool
Definition: actions.h:154
bool m_Defined
false if the aperture is not defined in the header
Definition: dcode.h:199
unsigned ImagesMaxCount() const
The max number of file images.
int MeasureTool(const TOOL_EVENT &aEvent)
Show a list of the DCodes.
int ExecuteFile(const wxString &ExecFile, const wxString &param, wxProcess *callback)
Call the executable file ExecFile with the command line parameters param.
Definition: gestfich.cpp:115
#define FIRST_DCODE
Definition: dcode.h:70
virtual void PopTool(const std::string &actionName)
virtual void CaptureCursor(bool aEnabled)
Force the cursor to stay within the drawing panel area.
GERBER_FILE_IMAGE * GetGbrImage(int aIdx) const
int m_Num_Dcode
D code value ( >= 10 )
Definition: dcode.h:190
Generic, UI-independent tool event.
Definition: tool_event.h:152
void SetOrigin(const VECTOR2I &aOrigin)
< Set the origin of the ruler (the fixed end)
static const wxChar * ShowApertureType(APERTURE_T aType)
Return a character string telling what type of aperture type aType is.
Definition: dcode.cpp:87
An interface for classes handling user events controlling the view behavior such as zooming,...
#define _(s)
A drawn ruler item for showing the distance between two points.
Definition: ruler_item.h:41
int ShowSource(const TOOL_EVENT &aEvent)
Set up handlers for various events.
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
virtual void SetAutoPan(bool aEnabled)
Turn on/off auto panning (this feature is used when there is a tool active (eg.
bool Init() override
Init() is called once upon a registration of the tool.
wxString m_AperFunction
the aperture attribute (created by a TA.AperFunction command).
Definition: dcode.h:200
EDA_UNITS
Definition: eda_units.h:38
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:460
int GetActiveLayer() const
Return the active layer.
static TOOL_ACTION updateUnits
Definition: actions.h:147
const int scale
see class PGM_BASE
A gerber DCODE (also called Aperture) definition.
Definition: dcode.h:80
int ShowDCodes(const TOOL_EVENT &aEvent)
Show the source for the gerber file.
SELECTION & GetCurrentSelection() override
Get the current selection from the canvas area.
wxString QuoteFullPath(wxFileName &fn, wxPathFormat format)
Quote return value of wxFileName::GetFullPath().
Definition: gestfich.cpp:349
#define TOOLS_MAX_COUNT
Definition: dcode.h:72
#define IU_PER_MILS
Definition: plotter.cpp:136
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:77
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1464
void Activate()
Run the tool.
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:323
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:42
static TOOL_ACTION showDCodes
void ShowContextMenu(SELECTION &aSelection)
Helper function to set and immediately show a CONDITIONAL_MENU in concert with the given SELECTION.
Definition: tool_menu.cpp:59
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1518
void SetEnd(const VECTOR2I &aEnd)
Set the current end of the rectangle (the end that moves with the cursor.
Position or shape has changed.
Definition: view_item.h:54