Browse Source
Add GAL microwave tools
Add GAL microwave tools
This adds the microwave tools to GAL in Pcbnew as a new tool: MICROWAVE_TOOL. Some new preview items are introduced to support this: * TWO_POINT_GEOM_MANAGER for managing construction of two-point geometries, such as that used to construct the inductor. * CENTRELINE_RECT_ITEM a preview item to draw ractangle with a given aspect ratio along a line (specified using a TWO_POINT_GEOM_MANAGER) PCB_TOOL gets a generic event loops which should be useful for more than just microwave tools: * doInteractiveItemPlacement() - handles event loops that wait for a click, create an item on click and then allow moving it around/flipping, etc. Fixes: lp:1531323 * https://bugs.launchpad.net/kicad/+bug/1531323pull/3/merge
committed by
Tomasz Włostowski
13 changed files with 962 additions and 7 deletions
-
1common/CMakeLists.txt
-
100common/preview_items/centreline_rect_item.cpp
-
78include/preview_items/centreline_rect_item.h
-
97include/preview_items/two_point_geom_manager.h
-
2pcbnew/CMakeLists.txt
-
14pcbnew/microwave/microwave_inductor.cpp
-
385pcbnew/tools/microwave_tool.cpp
-
68pcbnew/tools/microwave_tool.h
-
15pcbnew/tools/pcb_actions.cpp
-
11pcbnew/tools/pcb_actions.h
-
169pcbnew/tools/pcb_tool.cpp
-
27pcbnew/tools/pcb_tool.h
-
2pcbnew/tools/tools_common.cpp
@ -0,0 +1,100 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2017 Kicad Developers, see change_log.txt for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 2 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 2 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include <preview_items/centreline_rect_item.h>
|
|||
|
|||
#include <preview_items/two_point_geom_manager.h>
|
|||
|
|||
#include <gal/graphics_abstraction_layer.h>
|
|||
|
|||
|
|||
using namespace KIGFX::PREVIEW; |
|||
|
|||
static SHAPE_POLY_SET getRectangleAlongCentreLine( |
|||
const VECTOR2D& aClStart, const VECTOR2D& aClEnd, double aAspect ) |
|||
{ |
|||
SHAPE_POLY_SET poly; |
|||
poly.NewOutline(); |
|||
|
|||
/*
|
|||
* The point layout of the rectangle goes like this, |
|||
* but start/end don't have to be horz/vert |
|||
* |
|||
* 0 ---------------- 1 ----- |
|||
* | | ^ |
|||
* s--------cl------->e |cl|/aspect |
|||
* | | v |
|||
* 3----------------- 2 ----- |
|||
*/ |
|||
|
|||
// vector down the centre line of the rectangle
|
|||
const VECTOR2D cl = aClEnd - aClStart; |
|||
|
|||
// the "side" of the rectangle is the centre line rotated by 90 deg
|
|||
// and scaled by the aspect ratio
|
|||
const VECTOR2D side = cl.Rotate( M_PI / 2.0 ) * aAspect; |
|||
|
|||
VECTOR2D pt = aClStart + ( side / 2.0 ); |
|||
poly.Append( pt ); |
|||
|
|||
pt += cl; |
|||
poly.Append( pt ); |
|||
|
|||
pt -= side; |
|||
poly.Append( pt ); |
|||
|
|||
pt -= cl; |
|||
poly.Append( pt ); |
|||
|
|||
return poly; |
|||
} |
|||
|
|||
|
|||
CENTRELINE_RECT_ITEM::CENTRELINE_RECT_ITEM( |
|||
const TWO_POINT_GEOMETRY_MANAGER& aGeomMgr, |
|||
double aAspect ): |
|||
m_geomMgr( aGeomMgr ), |
|||
m_aspect( aAspect ) |
|||
{ |
|||
} |
|||
|
|||
|
|||
SHAPE_POLY_SET CENTRELINE_RECT_ITEM::getOutline() const |
|||
{ |
|||
return getRectangleAlongCentreLine( m_geomMgr.GetOrigin(), |
|||
m_geomMgr.GetEnd(), |
|||
m_aspect ); |
|||
} |
|||
|
|||
|
|||
const BOX2I CENTRELINE_RECT_ITEM::ViewBBox() const |
|||
{ |
|||
return getOutline().BBox(); |
|||
} |
|||
|
|||
|
|||
void CENTRELINE_RECT_ITEM::drawPreviewShape( KIGFX::GAL& aGal ) const |
|||
{ |
|||
aGal.DrawLine( m_geomMgr.GetOrigin(), m_geomMgr.GetEnd() ); |
|||
aGal.DrawPolygon( getOutline() ); |
|||
} |
|||
@ -0,0 +1,78 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2017 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 2 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html |
|||
* or you may search the http://www.gnu.org website for the version 2 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#ifndef PREVIEW_ITEMS_CENTERLINE_RECT_ITEM_H |
|||
#define PREVIEW_ITEMS_CENTERLINE_RECT_ITEM_H |
|||
|
|||
#include <preview_items/simple_overlay_item.h> |
|||
|
|||
#include <geometry/shape_poly_set.h> |
|||
|
|||
#include <math/vector2d.h> |
|||
|
|||
namespace KIGFX |
|||
{ |
|||
class GAL; |
|||
|
|||
namespace PREVIEW |
|||
{ |
|||
class TWO_POINT_GEOMETRY_MANAGER; |
|||
|
|||
/** |
|||
* Class CENTRELINE_RECT_ITEM |
|||
* |
|||
* Represents an area drawn by drawing a rectangle of a given aspect |
|||
* along a vector, with the midpoiunt of one side on the start point |
|||
* and the mid point of the opposite side on the end. |
|||
* |
|||
* The centre line does not have to horizontal or vertical, it |
|||
* can be at any angle. |
|||
*/ |
|||
class CENTRELINE_RECT_ITEM : public SIMPLE_OVERLAY_ITEM |
|||
{ |
|||
public: |
|||
|
|||
CENTRELINE_RECT_ITEM( const TWO_POINT_GEOMETRY_MANAGER& aGeomMgr, |
|||
double aAspect ); |
|||
|
|||
///> Gets the bounding box of the rectangle |
|||
virtual const BOX2I ViewBBox() const override; |
|||
|
|||
private: |
|||
|
|||
///> Get the rectangular outline |
|||
SHAPE_POLY_SET getOutline() const; |
|||
|
|||
///> Draw rectangle and centre line onto GAL |
|||
void drawPreviewShape( KIGFX::GAL& aGal ) const override; |
|||
|
|||
const TWO_POINT_GEOMETRY_MANAGER& m_geomMgr; |
|||
|
|||
///> The aspect ratio of the rectangle to draw |
|||
double m_aspect; |
|||
}; |
|||
|
|||
} // PREVIEW |
|||
} // KIGFX |
|||
|
|||
#endif // PREVIEW_ITEMS_CENTERLINE_RECT_ITEM_H |
|||
@ -0,0 +1,97 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2017 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 2 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html |
|||
* or you may search the http://www.gnu.org website for the version 2 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#ifndef PREVIEW_ITEMS_TWO_POINT_GEOMETRY_MANAGER_H |
|||
#define PREVIEW_ITEMS_TWO_POINT_GEOMETRY_MANAGER_H |
|||
|
|||
#include <math/vector2d.h> |
|||
#include <common.h> |
|||
|
|||
namespace KIGFX |
|||
{ |
|||
class GAL; |
|||
|
|||
namespace PREVIEW |
|||
{ |
|||
|
|||
/** |
|||
* Class TWO_POINT_GEOMETRY_MANAGER |
|||
* |
|||
* Represents a very simple geometry manager for items that have |
|||
* a start and end point. |
|||
*/ |
|||
class TWO_POINT_GEOMETRY_MANAGER |
|||
{ |
|||
public: |
|||
|
|||
///> Set the origin of the ruler (the fixed end) |
|||
void SetOrigin( const VECTOR2I& aOrigin ) |
|||
{ |
|||
m_origin = aOrigin; |
|||
} |
|||
|
|||
VECTOR2I GetOrigin() const |
|||
{ |
|||
return m_origin; |
|||
} |
|||
|
|||
/** |
|||
* Set the current end of the rectangle (the end that moves |
|||
* with the cursor. |
|||
*/ |
|||
void SetEnd( const VECTOR2I& aEnd ) |
|||
{ |
|||
if( m_angleSnap ) |
|||
{ |
|||
const auto vec = aEnd - m_origin; |
|||
const auto len = vec.EuclideanNorm(); |
|||
const auto angle = KiROUND( vec.Angle() / M_PI_4 ) * M_PI_4; |
|||
|
|||
m_end = m_origin + VECTOR2I( len, 0 ).Rotate( angle ); |
|||
} |
|||
else |
|||
{ |
|||
m_end = aEnd; |
|||
} |
|||
} |
|||
|
|||
VECTOR2I GetEnd() const |
|||
{ |
|||
return m_end; |
|||
} |
|||
|
|||
void SetAngleSnap( bool aSnap ) |
|||
{ |
|||
m_angleSnap = aSnap; |
|||
} |
|||
|
|||
private: |
|||
|
|||
VECTOR2I m_origin, m_end; |
|||
bool m_angleSnap = false; |
|||
}; |
|||
|
|||
} // PREVIEW |
|||
} // KIGFX |
|||
|
|||
#endif // PREVIEW_ITEMS_TWO_POINT_GEOMETRY_MANAGER_H |
|||
@ -0,0 +1,385 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2017 Kicad Developers, see change_log.txt for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 2 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 2 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include "microwave_tool.h"
|
|||
|
|||
#include <gal/graphics_abstraction_layer.h>
|
|||
#include <class_draw_panel_gal.h>
|
|||
#include <view/view_controls.h>
|
|||
#include <view/view.h>
|
|||
#include <tool/tool_manager.h>
|
|||
#include <board_commit.h>
|
|||
#include <confirm.h>
|
|||
#include <preview_items/two_point_geom_manager.h>
|
|||
#include <preview_items/centreline_rect_item.h>
|
|||
|
|||
// For frame ToolID values
|
|||
#include <pcbnew_id.h>
|
|||
|
|||
// For action icons
|
|||
#include <bitmaps.h>
|
|||
|
|||
#include <class_board_item.h>
|
|||
#include <class_module.h>
|
|||
|
|||
#include <microwave/microwave_inductor.h>
|
|||
|
|||
#include "pcb_actions.h"
|
|||
#include "selection_tool.h"
|
|||
#include "tool_event_utils.h"
|
|||
|
|||
|
|||
///> Type of items that are "simple" - just get placed on
|
|||
///> the board directly, without a graphical interactive setup stage
|
|||
enum MWAVE_TOOL_SIMPLE_ID |
|||
{ |
|||
GAP, |
|||
STUB, |
|||
STUB_ARC, |
|||
FUNCTION_SHAPE, |
|||
}; |
|||
|
|||
TOOL_ACTION PCB_ACTIONS::microwaveCreateGap( |
|||
"pcbnew.MicrowaveTool.createGap", |
|||
AS_GLOBAL, 0, |
|||
_( "Add Gap" ), _( "Create gap of specified length for microwave applications" ), |
|||
mw_add_gap_xpm, AF_ACTIVATE, (void*) MWAVE_TOOL_SIMPLE_ID::GAP ); |
|||
|
|||
TOOL_ACTION PCB_ACTIONS::microwaveCreateStub( |
|||
"pcbnew.MicrowaveTool.createStub", |
|||
AS_GLOBAL, 0, |
|||
_( "Add Stub" ), _( "Create stub of specified length for microwave applications" ), |
|||
mw_add_stub_xpm, AF_ACTIVATE, (void*) MWAVE_TOOL_SIMPLE_ID::STUB ); |
|||
|
|||
TOOL_ACTION PCB_ACTIONS::microwaveCreateStubArc( |
|||
"pcbnew.MicrowaveTool.createStubArc", |
|||
AS_GLOBAL, 0, |
|||
_( "Add Arc Stub" ), _( "Create stub (arc) of specified length for microwave applications" ), |
|||
mw_add_stub_arc_xpm, AF_ACTIVATE, (void*) MWAVE_TOOL_SIMPLE_ID::STUB_ARC ); |
|||
|
|||
TOOL_ACTION PCB_ACTIONS::microwaveCreateFunctionShape( |
|||
"pcbnew.MicrowaveTool.createFunctionShape", |
|||
AS_GLOBAL, 0, |
|||
_( "Add Polynomial Shape" ), _( "Create polynomial shape for microwave applications" ), |
|||
mw_add_gap_xpm, AF_ACTIVATE, (void*) MWAVE_TOOL_SIMPLE_ID::FUNCTION_SHAPE ); |
|||
|
|||
TOOL_ACTION PCB_ACTIONS::microwaveCreateLine( |
|||
"pcbnew.MicrowaveTool.createLine", |
|||
AS_GLOBAL, 0, |
|||
_( "Add Microwave Line" ), _( "Create line of specified length for microwave applications" ), |
|||
mw_add_line_xpm, AF_ACTIVATE ); |
|||
|
|||
|
|||
MICROWAVE_TOOL::MICROWAVE_TOOL() : |
|||
PCB_TOOL( "pcbnew.MicrowaveTool" ), |
|||
m_menu( *this ) |
|||
{ |
|||
} |
|||
|
|||
|
|||
MICROWAVE_TOOL::~MICROWAVE_TOOL() |
|||
{} |
|||
|
|||
|
|||
void MICROWAVE_TOOL::Reset( RESET_REASON aReason ) |
|||
{ |
|||
} |
|||
|
|||
|
|||
bool MICROWAVE_TOOL::Init() |
|||
{ |
|||
auto activeToolFunctor = [ this ] ( const SELECTION& aSel ) { |
|||
return true; |
|||
}; |
|||
|
|||
auto& ctxMenu = m_menu.GetMenu(); |
|||
|
|||
// cancel current goes in main context menu at the top if present
|
|||
ctxMenu.AddItem( ACTIONS::cancelInteractive, activeToolFunctor, 1000 ); |
|||
ctxMenu.AddSeparator( activeToolFunctor, 1000 ); |
|||
|
|||
m_menu.AddStandardSubMenus( *getEditFrame<PCB_BASE_FRAME>() ); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
struct MICROWAVE_TOOL_INFO |
|||
{ |
|||
using MOD_CREATOR = std::function<std::unique_ptr<MODULE>()>; |
|||
|
|||
wxString name; |
|||
int toolId; |
|||
MOD_CREATOR creatorFunc; |
|||
}; |
|||
|
|||
|
|||
MICROWAVE_TOOL_INFO getMicrowaveItemCreator( PCB_EDIT_FRAME& frame, int aParam ) |
|||
{ |
|||
MICROWAVE_TOOL_INFO info; |
|||
|
|||
switch( aParam ) |
|||
{ |
|||
case MWAVE_TOOL_SIMPLE_ID::GAP: |
|||
info.name = _( "Add Gap" ); |
|||
info.toolId = ID_PCB_MUWAVE_TOOL_GAP_CMD; |
|||
info.creatorFunc = [&frame] () { |
|||
return std::unique_ptr<MODULE>( frame.Create_MuWaveComponent( 0 ) ); |
|||
}; |
|||
break; |
|||
|
|||
case MWAVE_TOOL_SIMPLE_ID::STUB: |
|||
info.name = _( "Add Stub" ); |
|||
info.toolId = ID_PCB_MUWAVE_TOOL_STUB_CMD; |
|||
info.creatorFunc = [&frame] () { |
|||
return std::unique_ptr<MODULE>( frame.Create_MuWaveComponent( 1 ) ); |
|||
}; |
|||
break; |
|||
|
|||
case MWAVE_TOOL_SIMPLE_ID::STUB_ARC: |
|||
info.name = _( "Add Stub (Arc)" ); |
|||
info.toolId = ID_PCB_MUWAVE_TOOL_STUB_ARC_CMD; |
|||
info.creatorFunc = [&frame] () { |
|||
return std::unique_ptr<MODULE>( frame.Create_MuWaveComponent( 2 ) ); |
|||
}; |
|||
break; |
|||
|
|||
case MWAVE_TOOL_SIMPLE_ID::FUNCTION_SHAPE: |
|||
info.name = _( "Add Polynomial Shape" ); |
|||
info.toolId = ID_PCB_MUWAVE_TOOL_FUNCTION_SHAPE_CMD; |
|||
info.creatorFunc = [&frame] () { |
|||
return std::unique_ptr<MODULE>( frame.Create_MuWavePolygonShape() ); |
|||
}; |
|||
break; |
|||
}; |
|||
|
|||
return info; |
|||
} |
|||
|
|||
|
|||
int MICROWAVE_TOOL::addMicrowaveFootprint( const TOOL_EVENT& aEvent ) |
|||
{ |
|||
auto& frame = *getEditFrame<PCB_EDIT_FRAME>(); |
|||
|
|||
const int param = aEvent.Parameter<intptr_t>(); |
|||
|
|||
MICROWAVE_TOOL_INFO info = getMicrowaveItemCreator( frame, param ); |
|||
|
|||
// failed to find suitable item info - shouldn't be possible
|
|||
// if all the id's are handled
|
|||
if( !info.name ) |
|||
{ |
|||
wxASSERT_MSG( 0, "Failed to find suitable microwave tool info" ); |
|||
return 0; |
|||
} |
|||
|
|||
frame.SetToolID( info.toolId, wxCURSOR_PENCIL, info.name ); |
|||
|
|||
ITEM_CREATOR moduleCreator = [this, &info] ( const TOOL_EVENT& aAddingEvent ) { |
|||
auto module = info.creatorFunc(); |
|||
|
|||
// Module has been added in the legacy backend,
|
|||
// so we have to remove it before committing the change
|
|||
// @todo LEGACY
|
|||
if( module ) |
|||
{ |
|||
board()->Remove( module.get() ); |
|||
} |
|||
|
|||
return module; |
|||
}; |
|||
|
|||
doInteractiveItemPlacement( moduleCreator, _( "Place microwave feature" ) ); |
|||
|
|||
frame.SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
void MICROWAVE_TOOL::createInductorBetween( const VECTOR2I& aStart, const VECTOR2I& aEnd ) |
|||
{ |
|||
auto& frame = *getEditFrame<PCB_EDIT_FRAME>(); |
|||
|
|||
MWAVE::INDUCTOR_PATTERN pattern; |
|||
|
|||
pattern.m_Width = board()->GetDesignSettings().GetCurrentTrackWidth(); |
|||
|
|||
pattern.m_Start = { aStart.x, aStart.y }; |
|||
pattern.m_End = { aEnd.x, aEnd.y }; |
|||
|
|||
wxString errorMessage; |
|||
|
|||
auto inductorModule = std::unique_ptr<MODULE>( |
|||
CreateMicrowaveInductor( pattern, &frame, errorMessage ) |
|||
); |
|||
|
|||
if( inductorModule ) |
|||
{ |
|||
// legacy mode tools add to the board
|
|||
// so remove it and add it back with the commit object
|
|||
// this has to happen, even if we don't end up storing the module
|
|||
// @todo LEGACY
|
|||
board()->Remove( inductorModule.get() ); |
|||
} |
|||
|
|||
// on any error, report if we can
|
|||
if ( !inductorModule || !errorMessage.IsEmpty() ) |
|||
{ |
|||
if ( !errorMessage.IsEmpty() ) |
|||
{ |
|||
DisplayError( &frame, errorMessage ); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
// at this point, we can save the module
|
|||
frame.SetCurItem( inductorModule.get() ); |
|||
|
|||
BOARD_COMMIT commit( this ); |
|||
commit.Add( inductorModule.release() ); |
|||
commit.Push( _("Add microwave inductor" ) ); |
|||
} |
|||
} |
|||
|
|||
|
|||
static const COLOR4D inductorAreaFill( 0.3, 0.3, 0.5, 0.3 ); |
|||
static const COLOR4D inductorAreaStroke( 0.4, 1.0, 1.0, 1.0 ); |
|||
static const double inductorAreaStrokeWidth = 1.0; |
|||
|
|||
///> Aspect of the preview rectangle - this is hardcoded in the
|
|||
///> microwave backend for now
|
|||
static const double inductorAreaAspect = 0.5; |
|||
|
|||
|
|||
int MICROWAVE_TOOL::drawMicrowaveInductor( const TOOL_EVENT& aEvent ) |
|||
{ |
|||
using namespace KIGFX::PREVIEW; |
|||
|
|||
KIGFX::VIEW& view = *getView(); |
|||
KIGFX::VIEW_CONTROLS& controls = *getViewControls(); |
|||
auto& frame = *getEditFrame<PCB_EDIT_FRAME>(); |
|||
|
|||
frame.SetToolID( ID_PCB_MUWAVE_TOOL_SELF_CMD, wxCURSOR_PENCIL, _( "Add Microwave Inductor" ) ); |
|||
|
|||
Activate(); |
|||
|
|||
TWO_POINT_GEOMETRY_MANAGER tpGeomMgr; |
|||
|
|||
CENTRELINE_RECT_ITEM previewRect( tpGeomMgr, inductorAreaAspect ); |
|||
|
|||
previewRect.SetFillColor( inductorAreaFill ); |
|||
previewRect.SetStrokeColor( inductorAreaStroke ); |
|||
previewRect.SetLineWidth( inductorAreaStrokeWidth ); |
|||
|
|||
bool originSet = false; |
|||
|
|||
controls.ShowCursor( true ); |
|||
controls.SetSnapping( true ); |
|||
|
|||
view.Add( &previewRect ); |
|||
|
|||
while( auto evt = Wait() ) |
|||
{ |
|||
VECTOR2I cursorPos = controls.GetCursorPosition(); |
|||
|
|||
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) ) |
|||
{ |
|||
// overriding action, or we're cancelling without
|
|||
// an in-progress preview area
|
|||
if ( evt->IsActivate() || !originSet ) |
|||
{ |
|||
break; |
|||
} |
|||
|
|||
// had an in-progress area, so start again but don't
|
|||
// cancel the tool
|
|||
originSet = false; |
|||
view.SetVisible( &previewRect, false ); |
|||
view.Update( &previewRect, KIGFX::GEOMETRY ); |
|||
} |
|||
|
|||
// A click or drag starts
|
|||
else if( !originSet && |
|||
( evt->IsClick( BUT_LEFT ) || evt->IsDrag( BUT_LEFT ) ) ) |
|||
{ |
|||
tpGeomMgr.SetOrigin( cursorPos ); |
|||
tpGeomMgr.SetEnd( cursorPos ); |
|||
|
|||
originSet = true; |
|||
|
|||
controls.CaptureCursor( true ); |
|||
controls.SetAutoPan( true ); |
|||
} |
|||
|
|||
// another click after origin set is the end
|
|||
// left up is also the end, as you'll only get that after a drag
|
|||
else if( originSet && |
|||
( evt->IsClick( BUT_LEFT ) || evt->IsMouseUp( BUT_LEFT ) ) ) |
|||
{ |
|||
// second click, we're done:
|
|||
// delegate to the point-to-point inductor creator function
|
|||
createInductorBetween( tpGeomMgr.GetOrigin(), tpGeomMgr.GetEnd() ); |
|||
|
|||
// start again if needed
|
|||
originSet = false; |
|||
|
|||
view.SetVisible( &previewRect, false ); |
|||
view.Update( &previewRect, KIGFX::GEOMETRY ); |
|||
} |
|||
|
|||
// any move or drag once the origin was set updates
|
|||
// the end point
|
|||
else if( originSet && |
|||
( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) ) |
|||
{ |
|||
tpGeomMgr.SetAngleSnap( evt->Modifier( MD_CTRL ) ); |
|||
tpGeomMgr.SetEnd( cursorPos ); |
|||
|
|||
view.SetVisible( &previewRect, true ); |
|||
view.Update( &previewRect, KIGFX::GEOMETRY ); |
|||
} |
|||
|
|||
else if( evt->IsClick( BUT_RIGHT ) ) |
|||
{ |
|||
m_menu.ShowContextMenu(); |
|||
} |
|||
} |
|||
|
|||
view.Remove( &previewRect ); |
|||
|
|||
frame.SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
void MICROWAVE_TOOL::SetTransitions() |
|||
{ |
|||
Go( &MICROWAVE_TOOL::addMicrowaveFootprint, PCB_ACTIONS::microwaveCreateGap.MakeEvent() ); |
|||
Go( &MICROWAVE_TOOL::addMicrowaveFootprint, PCB_ACTIONS::microwaveCreateStub.MakeEvent() ); |
|||
Go( &MICROWAVE_TOOL::addMicrowaveFootprint, PCB_ACTIONS::microwaveCreateStubArc.MakeEvent() ); |
|||
Go( &MICROWAVE_TOOL::addMicrowaveFootprint, PCB_ACTIONS::microwaveCreateFunctionShape.MakeEvent() ); |
|||
|
|||
Go( &MICROWAVE_TOOL::drawMicrowaveInductor, PCB_ACTIONS::microwaveCreateLine.MakeEvent() ); |
|||
} |
|||
@ -0,0 +1,68 @@ |
|||
/* |
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2017 Kicad Developers, see change_log.txt for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 2 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html |
|||
* or you may search the http://www.gnu.org website for the version 2 license, |
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#ifndef TOOLS_MICROWAVE_TOOL_H |
|||
#define TOOLS_MICROWAVE_TOOL_H |
|||
|
|||
#include <tools/pcb_tool.h> |
|||
|
|||
#include <tool/tool_menu.h> |
|||
|
|||
|
|||
/** |
|||
* Class MICROWAVE_TOOL |
|||
* |
|||
* Tool responsible for adding microwave features to PCBs |
|||
*/ |
|||
class MICROWAVE_TOOL : public PCB_TOOL |
|||
{ |
|||
public: |
|||
MICROWAVE_TOOL(); |
|||
~MICROWAVE_TOOL(); |
|||
|
|||
///> React to model/view changes |
|||
void Reset( RESET_REASON aReason ) override; |
|||
|
|||
///> Basic initalization |
|||
bool Init() override; |
|||
|
|||
///> Bind handlers to corresponding TOOL_ACTIONs |
|||
void SetTransitions() override; |
|||
|
|||
private: |
|||
|
|||
///> Main interactive tool |
|||
int addMicrowaveFootprint( const TOOL_EVENT& aEvent ); |
|||
|
|||
///> Create an inductor between the two points |
|||
void createInductorBetween( const VECTOR2I& aStart, const VECTOR2I& aEnd ); |
|||
|
|||
///> Draw a microwave inductor interactively |
|||
int drawMicrowaveInductor( const TOOL_EVENT& aEvent ); |
|||
|
|||
/// Menu model displayed by the tool. |
|||
TOOL_MENU m_menu; |
|||
}; |
|||
|
|||
|
|||
#endif // TOOLS_MICROWAVE_TOOL_H |
|||
@ -0,0 +1,169 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2017 KiCad Developers, see AUTHORS.txt for contributors. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 2 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 2 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
|
|||
#include "pcb_tool.h"
|
|||
|
|||
#include <view/view_controls.h>
|
|||
#include <view/view.h>
|
|||
#include <tool/tool_manager.h>
|
|||
#include <board_commit.h>
|
|||
|
|||
#include <class_module.h>
|
|||
|
|||
#include "selection_tool.h"
|
|||
#include "pcb_actions.h"
|
|||
#include "tool_event_utils.h"
|
|||
|
|||
|
|||
void PCB_TOOL::doInteractiveItemPlacement( ITEM_CREATOR aItemCreator, |
|||
const wxString& aCommitMessage ) |
|||
{ |
|||
using namespace std::placeholders; |
|||
|
|||
KIGFX::VIEW& view = *getView(); |
|||
KIGFX::VIEW_CONTROLS& controls = *getViewControls(); |
|||
auto& frame = *getEditFrame<PCB_EDIT_FRAME>(); |
|||
|
|||
std::unique_ptr<BOARD_ITEM> newItem; |
|||
|
|||
Activate(); |
|||
|
|||
BOARD_COMMIT commit( &frame ); |
|||
|
|||
GetManager()->RunAction( PCB_ACTIONS::selectionClear, true ); |
|||
|
|||
// do not capture or auto-pan until we start placing an item
|
|||
controls.ShowCursor( true ); |
|||
controls.SetSnapping( true ); |
|||
|
|||
// Add a VIEW_GROUP that serves as a preview for the new item
|
|||
SELECTION preview; |
|||
view.Add( &preview ); |
|||
|
|||
// Main loop: keep receiving events
|
|||
while( OPT_TOOL_EVENT evt = Wait() ) |
|||
{ |
|||
VECTOR2I cursorPos = controls.GetCursorPosition(); |
|||
|
|||
if( TOOL_EVT_UTILS::IsCancelInteractive( *evt ) ) |
|||
{ |
|||
if( newItem ) |
|||
{ |
|||
// Delete the old item and have another try
|
|||
newItem = nullptr; |
|||
|
|||
preview.Clear(); |
|||
|
|||
controls.SetAutoPan( false ); |
|||
controls.CaptureCursor( false ); |
|||
controls.ShowCursor( true ); |
|||
} |
|||
else |
|||
{ |
|||
break; |
|||
} |
|||
|
|||
if( evt->IsActivate() ) // now finish unconditionally
|
|||
break; |
|||
} |
|||
|
|||
else if( evt->IsClick( BUT_LEFT ) ) |
|||
{ |
|||
if( !newItem ) |
|||
{ |
|||
// create the item if possible
|
|||
newItem = aItemCreator( *evt ); |
|||
|
|||
// no item created, so wait for another click
|
|||
if( !newItem ) |
|||
continue; |
|||
|
|||
controls.CaptureCursor( true ); |
|||
controls.SetAutoPan( true ); |
|||
|
|||
newItem->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); |
|||
|
|||
preview.Add( newItem.get() ); |
|||
|
|||
if( newItem->Type() == PCB_MODULE_T ) |
|||
{ |
|||
auto module = dyn_cast<MODULE*>( newItem.get() ); |
|||
|
|||
// modules have more drawable parts
|
|||
module->RunOnChildren( std::bind( &KIGFX::VIEW_GROUP::Add, &preview, _1 ) ); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
newItem->ClearFlags(); |
|||
preview.Remove( newItem.get() ); |
|||
|
|||
if( newItem->Type() == PCB_MODULE_T ) |
|||
{ |
|||
auto module = dyn_cast<MODULE*>( newItem.get() ); |
|||
module->RunOnChildren( std::bind( &KIGFX::VIEW_GROUP::Remove, &preview, _1 ) ); |
|||
} |
|||
|
|||
commit.Add( newItem.release() ); |
|||
commit.Push( aCommitMessage ); |
|||
|
|||
controls.CaptureCursor( false ); |
|||
controls.SetAutoPan( false ); |
|||
controls.ShowCursor( true ); |
|||
} |
|||
} |
|||
|
|||
else if( newItem && evt->Category() == TC_COMMAND ) |
|||
{ |
|||
/*
|
|||
* Handle any events that can affect the item as we move |
|||
* it around, eg rotate and flip |
|||
*/ |
|||
|
|||
if( TOOL_EVT_UTILS::IsRotateToolEvt( *evt ) ) |
|||
{ |
|||
const auto rotationAngle = TOOL_EVT_UTILS::GetEventRotationAngle( |
|||
frame, *evt ); |
|||
newItem->Rotate( newItem->GetPosition(), rotationAngle ); |
|||
view.Update( &preview ); |
|||
} |
|||
else if( evt->IsAction( &PCB_ACTIONS::flip ) ) |
|||
{ |
|||
newItem->Flip( newItem->GetPosition() ); |
|||
view.Update( &preview ); |
|||
} |
|||
} |
|||
|
|||
else if( newItem && evt->IsMotion() ) |
|||
{ |
|||
// track the cursor
|
|||
newItem->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); |
|||
|
|||
// Show a preview of the item
|
|||
view.Update( &preview ); |
|||
} |
|||
} |
|||
|
|||
view.Remove( &preview ); |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue