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
KIGFX::VIEW * view() const
Definition: pcb_tool.h:123
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:324
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
void Remove(VIEW_ITEM *aItem)
Function Remove() Removes a VIEW_ITEM from the view.
Definition: view.cpp:341
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:328
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:124
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:125
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:320
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
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:1377
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:322
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:560
static TOOL_ACTION microwaveCreateFunctionShape
Definition: pcb_actions.h:326
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
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:1323
void Activate()
Function Activate() Runs the tool.
void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Function Add() Adds a VIEW_ITEM to the view.
Definition: view.cpp:311
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:38
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:126
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39