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  m_menu( *this )
96 {
97 }
98 
99 
101 {}
102 
103 
105 {
106 }
107 
108 
110 {
111  auto activeToolFunctor = [ this ] ( const SELECTION& aSel ) {
112  return true;
113  };
114 
115  auto& ctxMenu = m_menu.GetMenu();
116 
117  // cancel current goes in main context menu at the top if present
118  ctxMenu.AddItem( ACTIONS::cancelInteractive, activeToolFunctor, 1000 );
119  ctxMenu.AddSeparator( activeToolFunctor, 1000 );
120 
121  m_menu.AddStandardSubMenus( *getEditFrame<PCB_BASE_FRAME>() );
122 
123  return true;
124 }
125 
126 
128 {
129  using MOD_CREATOR = std::function<std::unique_ptr<MODULE>()>;
130 
131  wxString name;
132  int toolId;
134 };
135 
136 
138 {
139  MICROWAVE_TOOL_INFO info;
140 
141  switch( aParam )
142  {
144  info.name = _( "Add Gap" );
146  info.creatorFunc = [&frame] () {
147  return std::unique_ptr<MODULE>( frame.Create_MuWaveComponent( 0 ) );
148  };
149  break;
150 
152  info.name = _( "Add Stub" );
154  info.creatorFunc = [&frame] () {
155  return std::unique_ptr<MODULE>( frame.Create_MuWaveComponent( 1 ) );
156  };
157  break;
158 
160  info.name = _( "Add Stub (Arc)" );
162  info.creatorFunc = [&frame] () {
163  return std::unique_ptr<MODULE>( frame.Create_MuWaveComponent( 2 ) );
164  };
165  break;
166 
168  info.name = _( "Add Polynomial Shape" );
170  info.creatorFunc = [&frame] () {
171  return std::unique_ptr<MODULE>( frame.Create_MuWavePolygonShape() );
172  };
173  break;
174 
175  default:
176  // Avoid uninitilized value:
177  info.toolId = 0;
178  // info.name is already set to empty string
179  break;
180  };
181 
182  return info;
183 }
184 
185 
187 {
188  auto& frame = *getEditFrame<PCB_EDIT_FRAME>();
189 
190  const int param = aEvent.Parameter<intptr_t>();
191 
193 
194  // failed to find suitable item info - shouldn't be possible
195  // if all the id's are handled
196  if( !info.name )
197  {
198  wxASSERT_MSG( 0, "Failed to find suitable microwave tool info" );
199  return 0;
200  }
201 
202  frame.SetToolID( info.toolId, wxCURSOR_PENCIL, info.name );
203 
204  struct MICROWAVE_PLACER : public INTERACTIVE_PLACER_BASE
205  {
206  MICROWAVE_TOOL_INFO& m_info;
207 
208  MICROWAVE_PLACER( MICROWAVE_TOOL_INFO& aInfo ) :
209  m_info( aInfo ) {};
210 
211  std::unique_ptr<BOARD_ITEM> CreateItem() override
212  {
213  auto module = m_info.creatorFunc();
214 
215  // Module has been added in the legacy backend,
216  // so we have to remove it before committing the change
217  // @todo LEGACY
218  if( module )
219  {
220  m_board->Remove( module.get() );
221  }
222 
223  return std::unique_ptr<BOARD_ITEM>( module.release() );
224  }
225  };
226 
227  MICROWAVE_PLACER placer ( info );
228 
229  doInteractiveItemPlacement( &placer, _( "Place microwave feature" ) );
230 
232 
233  return 0;
234 }
235 
236 
237 void MICROWAVE_TOOL::createInductorBetween( const VECTOR2I& aStart, const VECTOR2I& aEnd )
238 {
239  auto& frame = *getEditFrame<PCB_EDIT_FRAME>();
240 
241  MWAVE::INDUCTOR_PATTERN pattern;
242 
244 
245  pattern.m_Start = { aStart.x, aStart.y };
246  pattern.m_End = { aEnd.x, aEnd.y };
247 
248  wxString errorMessage;
249 
250  auto inductorModule = std::unique_ptr<MODULE>(
251  CreateMicrowaveInductor( pattern, &frame, errorMessage )
252  );
253 
254  if( inductorModule )
255  {
256  // legacy mode tools add to the board
257  // so remove it and add it back with the commit object
258  // this has to happen, even if we don't end up storing the module
259  // @todo LEGACY
260  board()->Remove( inductorModule.get() );
261  }
262 
263  // on any error, report if we can
264  if ( !inductorModule || !errorMessage.IsEmpty() )
265  {
266  if ( !errorMessage.IsEmpty() )
267  {
268  DisplayError( &frame, errorMessage );
269  }
270  }
271  else
272  {
273  // at this point, we can save the module
274  frame.SetCurItem( inductorModule.get() );
275 
276  BOARD_COMMIT commit( this );
277  commit.Add( inductorModule.release() );
278  commit.Push( _("Add microwave inductor" ) );
279  }
280 }
281 
282 
283 static const COLOR4D inductorAreaFill( 0.3, 0.3, 0.5, 0.3 );
284 static const COLOR4D inductorAreaStroke( 0.4, 1.0, 1.0, 1.0 );
285 static const double inductorAreaStrokeWidth = 1.0;
286 
289 static const double inductorAreaAspect = 0.5;
290 
291 
293 {
294  using namespace KIGFX::PREVIEW;
295 
296  KIGFX::VIEW& view = *getView();
298  auto& frame = *getEditFrame<PCB_EDIT_FRAME>();
299 
300  frame.SetToolID( ID_PCB_MUWAVE_TOOL_SELF_CMD, wxCURSOR_PENCIL, _( "Add Microwave Inductor" ) );
301 
302  Activate();
303 
304  TWO_POINT_GEOMETRY_MANAGER tpGeomMgr;
305 
306  CENTRELINE_RECT_ITEM previewRect( tpGeomMgr, inductorAreaAspect );
307 
308  previewRect.SetFillColor( inductorAreaFill );
309  previewRect.SetStrokeColor( inductorAreaStroke );
310  previewRect.SetLineWidth( inductorAreaStrokeWidth );
311 
312  bool originSet = false;
313 
314  controls.ShowCursor( true );
315  controls.SetSnapping( true );
316 
317  view.Add( &previewRect );
318 
319  while( auto evt = Wait() )
320  {
321  VECTOR2I cursorPos = controls.GetCursorPosition();
322 
324  {
325  // overriding action, or we're cancelling without
326  // an in-progress preview area
327  if ( evt->IsActivate() || !originSet )
328  {
329  break;
330  }
331 
332  // had an in-progress area, so start again but don't
333  // cancel the tool
334  originSet = false;
335  view.SetVisible( &previewRect, false );
336  view.Update( &previewRect, KIGFX::GEOMETRY );
337  }
338 
339  // A click or drag starts
340  else if( !originSet &&
341  ( evt->IsClick( BUT_LEFT ) || evt->IsDrag( BUT_LEFT ) ) )
342  {
343  tpGeomMgr.SetOrigin( cursorPos );
344  tpGeomMgr.SetEnd( cursorPos );
345 
346  originSet = true;
347 
348  controls.CaptureCursor( true );
349  controls.SetAutoPan( true );
350  }
351 
352  // another click after origin set is the end
353  // left up is also the end, as you'll only get that after a drag
354  else if( originSet &&
355  ( evt->IsClick( BUT_LEFT ) || evt->IsMouseUp( BUT_LEFT ) ) )
356  {
357  // second click, we're done:
358  // delegate to the point-to-point inductor creator function
359  createInductorBetween( tpGeomMgr.GetOrigin(), tpGeomMgr.GetEnd() );
360 
361  // start again if needed
362  originSet = false;
363 
364  view.SetVisible( &previewRect, false );
365  view.Update( &previewRect, KIGFX::GEOMETRY );
366  }
367 
368  // any move or drag once the origin was set updates
369  // the end point
370  else if( originSet &&
371  ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) )
372  {
373  tpGeomMgr.SetAngleSnap( evt->Modifier( MD_CTRL ) );
374  tpGeomMgr.SetEnd( cursorPos );
375 
376  view.SetVisible( &previewRect, true );
377  view.Update( &previewRect, KIGFX::GEOMETRY );
378  }
379 
380  else if( evt->IsClick( BUT_RIGHT ) )
381  {
383  }
384  }
385 
386  view.Remove( &previewRect );
387 
389 
390  return 0;
391 }
392 
393 
395 {
400 
402 }
virtual void ShowCursor(bool aEnabled)
Function ShowCursor() Enables or disables display of cursor.
static const double inductorAreaStrokeWidth
bool Init() override
Basic initalization
void SetLineWidth(double aNewWidth)
Set the line width to set before drawing preview
virtual void SetToolID(int aId, int aCursor, const wxString &aToolMsg) override
Function SetToolID sets 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
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:333
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.
CONDITIONAL_MENU & GetMenu()
Function GetMenu.
Definition: tool_menu.cpp:49
Parameters for construction of a microwave inductor.
void Reset(RESET_REASON aReason) override
React to model/view changes
static TOOL_ACTION cancelInteractive
Definition: actions.h:45
virtual void Remove(VIEW_ITEM *aItem)
Function Remove() Removes a VIEW_ITEM from the view.
Definition: view.cpp:342
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:337
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)
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true) override
Executes the changes.
TOOL_MENU m_menu
Menu model displayed by the tool.
KIGFX::VIEW_CONTROLS * controls() const
Definition: pcb_tool.h:132
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)
void AddStandardSubMenus(EDA_DRAW_FRAME &aFrame)
Function CreateBasicMenu.
Definition: tool_menu.cpp:95
MODULE * Create_MuWavePolygonShape()
Definition: microwave.cpp:574
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:226
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:133
Class TOOL_EVENT.
Definition: tool_event.h:162
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:532
Class VIEW_CONTROLS is an interface for classes handling user events controlling the view behaviour (...
static TOOL_ACTION microwaveCreateGap
Definition: pcb_actions.h:329
MODULE * module() const
Definition: pcb_tool.h:135
bool IsCancelInteractive(const TOOL_EVENT &aEvt)
Function IsCancelInteractive()
All active tools
Definition: tool_event.h:138
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:1385
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:331
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)
Definition: draw_frame.cpp:571
static TOOL_ACTION microwaveCreateFunctionShape
Definition: pcb_actions.h:335
T Parameter() const
Function Parameter() Returns a non-standard parameter assigned to the event.
Definition: tool_event.h:373
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:131
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition=SELECTION_CONDITIONS::ShowAlways, int aOrder=ANY_ORDER)
Function AddItem()
Class TOOL_ACTION.
Definition: tool_action.h:46
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:1331
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:312
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:58
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:71
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:134
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39