KiCad PCB EDA Suite
microwave_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 Kicad Developers, see change_log.txt for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include "microwave_tool.h"
25 
27 #include <class_draw_panel_gal.h>
28 #include <view/view_controls.h>
29 #include <view/view.h>
30 #include <tool/tool_manager.h>
31 #include <board_commit.h>
32 #include <confirm.h>
35 
36 // For frame ToolID values
37 #include <pcbnew_id.h>
38 
39 // For action icons
40 #include <bitmaps.h>
41 
42 #include <class_board_item.h>
43 #include <class_module.h>
44 
46 
47 #include "pcb_actions.h"
48 #include "selection_tool.h"
49 #include "tool_event_utils.h"
50 
51 
55 {
56  GAP,
60 };
61 
63  "pcbnew.MicrowaveTool.createGap",
64  AS_GLOBAL, 0,
65  _( "Add Gap" ), _( "Create gap of specified length for microwave applications" ),
66  mw_add_gap_xpm, AF_ACTIVATE, (void*) MWAVE_TOOL_SIMPLE_ID::GAP );
67 
69  "pcbnew.MicrowaveTool.createStub",
70  AS_GLOBAL, 0,
71  _( "Add Stub" ), _( "Create stub of specified length for microwave applications" ),
72  mw_add_stub_xpm, AF_ACTIVATE, (void*) MWAVE_TOOL_SIMPLE_ID::STUB );
73 
75  "pcbnew.MicrowaveTool.createStubArc",
76  AS_GLOBAL, 0,
77  _( "Add Arc Stub" ), _( "Create stub (arc) of specified length for microwave applications" ),
78  mw_add_stub_arc_xpm, AF_ACTIVATE, (void*) MWAVE_TOOL_SIMPLE_ID::STUB_ARC );
79 
81  "pcbnew.MicrowaveTool.createFunctionShape",
82  AS_GLOBAL, 0,
83  _( "Add Polynomial Shape" ), _( "Create polynomial shape for microwave applications" ),
84  mw_add_gap_xpm, AF_ACTIVATE, (void*) MWAVE_TOOL_SIMPLE_ID::FUNCTION_SHAPE );
85 
87  "pcbnew.MicrowaveTool.createLine",
88  AS_GLOBAL, 0,
89  _( "Add Microwave Line" ), _( "Create line of specified length for microwave applications" ),
90  mw_add_line_xpm, AF_ACTIVATE );
91 
92 
94  PCB_TOOL( "pcbnew.MicrowaveTool" )
95 {
96 }
97 
98 
100 {}
101 
102 
104 {
105 }
106 
107 
109 {
110  using MOD_CREATOR = std::function<std::unique_ptr<MODULE>()>;
111 
112  wxString name;
113  int toolId;
115 };
116 
117 
119 {
120  MICROWAVE_TOOL_INFO info;
121 
122  switch( aParam )
123  {
125  info.name = _( "Add Gap" );
127  info.creatorFunc = [&frame] () {
128  return std::unique_ptr<MODULE>( frame.Create_MuWaveComponent( 0 ) );
129  };
130  break;
131 
133  info.name = _( "Add Stub" );
135  info.creatorFunc = [&frame] () {
136  return std::unique_ptr<MODULE>( frame.Create_MuWaveComponent( 1 ) );
137  };
138  break;
139 
141  info.name = _( "Add Stub (Arc)" );
143  info.creatorFunc = [&frame] () {
144  return std::unique_ptr<MODULE>( frame.Create_MuWaveComponent( 2 ) );
145  };
146  break;
147 
149  info.name = _( "Add Polynomial Shape" );
151  info.creatorFunc = [&frame] () {
152  return std::unique_ptr<MODULE>( frame.Create_MuWavePolygonShape() );
153  };
154  break;
155 
156  default:
157  // Avoid uninitilized value:
158  info.toolId = 0;
159  // info.name is already set to empty string
160  break;
161  };
162 
163  return info;
164 }
165 
166 
168 {
169  auto& frame = *getEditFrame<PCB_EDIT_FRAME>();
170 
171  const int param = aEvent.Parameter<intptr_t>();
172 
174 
175  // failed to find suitable item info - shouldn't be possible
176  // if all the id's are handled
177  if( !info.name )
178  {
179  wxASSERT_MSG( 0, "Failed to find suitable microwave tool info" );
180  return 0;
181  }
182 
183  frame.SetToolID( info.toolId, wxCURSOR_PENCIL, info.name );
184 
185  struct MICROWAVE_PLACER : public INTERACTIVE_PLACER_BASE
186  {
187  MICROWAVE_TOOL_INFO& m_info;
188 
189  MICROWAVE_PLACER( MICROWAVE_TOOL_INFO& aInfo ) :
190  m_info( aInfo ) {};
191 
192  std::unique_ptr<BOARD_ITEM> CreateItem() override
193  {
194  auto module = m_info.creatorFunc();
195 
196  // Module has been added in the legacy backend,
197  // so we have to remove it before committing the change
198  // @todo LEGACY
199  if( module )
200  {
201  m_board->Remove( module.get() );
202  }
203 
204  return std::unique_ptr<BOARD_ITEM>( module.release() );
205  }
206  };
207 
208  MICROWAVE_PLACER placer ( info );
209 
210  doInteractiveItemPlacement( &placer, _( "Place microwave feature" ),
212 
214 
215  return 0;
216 }
217 
218 
219 void MICROWAVE_TOOL::createInductorBetween( const VECTOR2I& aStart, const VECTOR2I& aEnd )
220 {
221  auto& frame = *getEditFrame<PCB_EDIT_FRAME>();
222 
223  MWAVE::INDUCTOR_PATTERN pattern;
224 
226 
227  pattern.m_Start = { aStart.x, aStart.y };
228  pattern.m_End = { aEnd.x, aEnd.y };
229 
230  wxString errorMessage;
231 
232  auto inductorModule = std::unique_ptr<MODULE>(
233  CreateMicrowaveInductor( pattern, &frame, errorMessage )
234  );
235 
236  if( inductorModule )
237  {
238  // legacy mode tools add to the board
239  // so remove it and add it back with the commit object
240  // this has to happen, even if we don't end up storing the module
241  // @todo LEGACY
242  board()->Remove( inductorModule.get() );
243  }
244 
245  // on any error, report if we can
246  if ( !inductorModule || !errorMessage.IsEmpty() )
247  {
248  if ( !errorMessage.IsEmpty() )
249  {
250  DisplayError( &frame, errorMessage );
251  }
252  }
253  else
254  {
255  // at this point, we can save the module
256  frame.SetCurItem( inductorModule.get() );
257 
258  BOARD_COMMIT commit( this );
259  commit.Add( inductorModule.release() );
260  commit.Push( _("Add microwave inductor" ) );
261  }
262 }
263 
264 
265 static const COLOR4D inductorAreaFill( 0.3, 0.3, 0.5, 0.3 );
266 static const COLOR4D inductorAreaStroke( 0.4, 1.0, 1.0, 1.0 );
267 static const double inductorAreaStrokeWidth = 1.0;
268 
271 static const double inductorAreaAspect = 0.5;
272 
273 
275 {
276  using namespace KIGFX::PREVIEW;
277 
278  KIGFX::VIEW& view = *getView();
280  auto& frame = *getEditFrame<PCB_EDIT_FRAME>();
281 
282  frame.SetToolID( ID_PCB_MUWAVE_TOOL_SELF_CMD, wxCURSOR_PENCIL, _( "Add Microwave Inductor" ) );
283 
284  Activate();
285 
286  TWO_POINT_GEOMETRY_MANAGER tpGeomMgr;
287 
288  CENTRELINE_RECT_ITEM previewRect( tpGeomMgr, inductorAreaAspect );
289 
290  previewRect.SetFillColor( inductorAreaFill );
291  previewRect.SetStrokeColor( inductorAreaStroke );
292  previewRect.SetLineWidth( inductorAreaStrokeWidth );
293 
294  bool originSet = false;
295 
296  controls.ShowCursor( true );
297  controls.SetSnapping( true );
298  controls.CaptureCursor( false );
299  controls.SetAutoPan( false );
300 
301  view.Add( &previewRect );
302 
303  while( auto evt = Wait() )
304  {
305  VECTOR2I cursorPos = controls.GetCursorPosition();
306 
308  {
309  // overriding action, or we're cancelling without
310  // an in-progress preview area
311  if ( evt->IsActivate() || !originSet )
312  {
313  break;
314  }
315 
316  // had an in-progress area, so start again but don't
317  // cancel the tool
318  originSet = false;
319  controls.CaptureCursor( false );
320  controls.SetAutoPan( false );
321 
322  view.SetVisible( &previewRect, false );
323  view.Update( &previewRect, KIGFX::GEOMETRY );
324  }
325 
326  // A click or drag starts
327  else if( !originSet &&
328  ( evt->IsClick( BUT_LEFT ) || evt->IsDrag( BUT_LEFT ) ) )
329  {
330  tpGeomMgr.SetOrigin( cursorPos );
331  tpGeomMgr.SetEnd( cursorPos );
332 
333  originSet = true;
334  controls.CaptureCursor( true );
335  controls.SetAutoPan( true );
336  }
337 
338  // another click after origin set is the end
339  // left up is also the end, as you'll only get that after a drag
340  else if( originSet &&
341  ( evt->IsClick( BUT_LEFT ) || evt->IsMouseUp( BUT_LEFT ) ) )
342  {
343  // second click, we're done:
344  // delegate to the point-to-point inductor creator function
345  createInductorBetween( tpGeomMgr.GetOrigin(), tpGeomMgr.GetEnd() );
346 
347  // start again if needed
348  originSet = false;
349  controls.CaptureCursor( false );
350  controls.SetAutoPan( false );
351 
352  view.SetVisible( &previewRect, false );
353  view.Update( &previewRect, KIGFX::GEOMETRY );
354  }
355 
356  // any move or drag once the origin was set updates
357  // the end point
358  else if( originSet &&
359  ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) )
360  {
361  tpGeomMgr.SetAngleSnap( evt->Modifier( MD_CTRL ) );
362  tpGeomMgr.SetEnd( cursorPos );
363 
364  view.SetVisible( &previewRect, true );
365  view.Update( &previewRect, KIGFX::GEOMETRY );
366  }
367 
368  else if( evt->IsClick( BUT_RIGHT ) )
369  {
371  }
372  }
373 
374  controls.CaptureCursor( false );
375  controls.SetAutoPan( false );
376  view.Remove( &previewRect );
377 
379 
380  return 0;
381 }
382 
383 
385 {
390 
392 }
virtual void ShowCursor(bool aEnabled)
Function ShowCursor() Enables or disables display of cursor.
static const double inductorAreaStrokeWidth
void SetLineWidth(double aNewWidth)
Set the line width to set before drawing preview
virtual void SetToolID(int aId, int aCursor, const wxString &aToolMsg) override
Set the tool command ID to aId and sets the cursor to aCursor.
std::function< std::unique_ptr< MODULE >()> MOD_CREATOR
void SetStrokeColor(const COLOR4D &aNewColor)
Set the stroke colour to set before drawing preview
TOOL_MENU m_menu
Menu model displayed by the tool.
Definition: pcb_tool.h:148
This file is part of the common library.
static const double inductorAreaAspect
Aspect of the preview rectangle - this is hardcoded in the microwave backend for now ...
static TOOL_ACTION microwaveCreateStubArc
Definition: pcb_actions.h:350
COMMIT & Add(EDA_ITEM *aItem)
Adds a new item to the model
Definition: commit.h:78
VIEW_CONTROLS class definition.
Classes BOARD_ITEM and BOARD_CONNECTED_ITEM.
Class TWO_POINT_GEOMETRY_MANAGER.
Parameters for construction of a microwave inductor.
void Reset(RESET_REASON aReason) override
React to model/view changes
virtual void Remove(VIEW_ITEM *aItem)
Function Remove() Removes a VIEW_ITEM from the view.
Definition: view.cpp:374
void SetCurItem(BOARD_ITEM *aItem, bool aDisplayInfo=true)
Function SetCurItem sets the currently selected item and displays it in the MsgPanel.
OPT_TOOL_EVENT Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
virtual void SetSnapping(bool aEnabled)
Function SetSnapping() Enables/disables snapping cursor to grid.
static TOOL_ACTION microwaveCreateLine
Definition: pcb_actions.h:354
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Function Go()
static const COLOR4D inductorAreaFill(0.3, 0.3, 0.5, 0.3)
KIGFX::VIEW_CONTROLS * controls() const
Definition: pcb_tool.h:138
void createInductorBetween(const VECTOR2I &aStart, const VECTOR2I &aEnd)
Create an inductor between the two points
MICROWAVE_TOOL_INFO getMicrowaveItemCreator(PCB_EDIT_FRAME &frame, int aParam)
MODULE * Create_MuWavePolygonShape()
Definition: microwave.cpp:577
static const COLOR4D inductorAreaStroke(0.4, 1.0, 1.0, 1.0)
MODULE * Create_MuWaveComponent(int shape_type)
Create_MuWaveComponent creates a module "GAP" or "STUB" used in micro wave designs.
Definition: microwave.cpp:228
virtual void CaptureCursor(bool aEnabled)
Function CaptureCursor() Forces the cursor to stay within the drawing panel area. ...
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.
PCB_EDIT_FRAME * frame() const
Definition: pcb_tool.h:139
Class TOOL_EVENT.
Definition: tool_event.h:168
void SetOrigin(const VECTOR2I &aOrigin)
Set the origin of the ruler (the fixed end)
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:539
Class VIEW_CONTROLS is an interface for classes handling user events controlling the view behaviour (...
static TOOL_ACTION microwaveCreateGap
Definition: pcb_actions.h:346
MODULE * module() const
Definition: pcb_tool.h:141
bool IsCancelInteractive(const TOOL_EVENT &aEvt)
Function IsCancelInteractive()
All active tools
Definition: tool_event.h:144
void SetFillColor(const COLOR4D &aNewColor)
Set the fill colour to set before drawing preview
virtual void Update(VIEW_ITEM *aItem, int aUpdateFlags)
For dynamic VIEWs, informs the associated VIEW that the graphical representation of this item has cha...
Definition: view.cpp:1530
void setTransitions() override
Bind handlers to corresponding TOOL_ACTIONs
virtual void SetAutoPan(bool aEnabled)
Function SetAutoPan Turns on/off auto panning (this feature is used when there is a tool active (eg...
KIGFX::VIEW_CONTROLS * getViewControls() const
Function getViewControls()
Definition: tool_base.cpp:41
static TOOL_ACTION microwaveCreateStub
Definition: pcb_actions.h:348
int drawMicrowaveInductor(const TOOL_EVENT &aEvent)
Draw a microwave inductor interactively
KIGFX::VIEW * getView() const
Function getView()
Definition: tool_base.cpp:35
virtual void SetNoToolSelected()
Select the ID_NO_TOOL_SELECTED id tool (Idle tool)
static TOOL_ACTION microwaveCreateFunctionShape
Definition: pcb_actions.h:352
T Parameter() const
Function Parameter() Returns a non-standard parameter assigned to the event.
Definition: tool_event.h:387
MODULE * CreateMicrowaveInductor(INDUCTOR_PATTERN &aPattern, PCB_EDIT_FRAME *aPcbFrame, wxString &aErrorMessage)
Creates an S-shaped coil footprint for microwave applications.
int addMicrowaveFootprint(const TOOL_EVENT &aEvent)
Main interactive tool
KIGFX::PCB_VIEW * view() const
Definition: pcb_tool.h:137
Class TOOL_ACTION.
Definition: tool_action.h:46
Class PCB_EDIT_FRAME is the main frame for Pcbnew.
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true) override
Executes the changes.
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:80
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Sets the item visibility.
Definition: view.cpp:1476
void Activate()
Function Activate() Runs the tool.
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Function Add() Adds a VIEW_ITEM to the view.
Definition: view.cpp:344
Module description (excepted pads)
void doInteractiveItemPlacement(INTERACTIVE_PLACER_BASE *aPlacer, const wxString &aCommitMessage, int aOptions=IPO_ROTATE|IPO_FLIP|IPO_REPEAT)
Helper function for performing a common interactive idiom: wait for a left click, place an item there...
Definition: pcb_tool.cpp:39
Class VIEW.
Definition: view.h:61
int GetCurrentTrackWidth() const
Function GetCurrentTrackWidth.
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:245
MWAVE_TOOL_SIMPLE_ID
Type of items that are "simple" - just get placed on the board directly, without a graphical interact...
void ShowContextMenu(SELECTION &aSelection)
Function ShowContextMenu.
Definition: tool_menu.cpp:62
void Remove(BOARD_ITEM *aBoardItem) override
Removes an item from the container.
void SetEnd(const VECTOR2I &aEnd)
Set the current end of the rectangle (the end that moves with the cursor.
Color has changed.
Definition: view_item.h:57
BOARD * board() const
Definition: pcb_tool.h:140
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39