Add zone cutout tool to GAL

When activated, the zone interactive editor is launched with a flag. The
drawn zone is then used to modify the existing zone at the end of the
action.
This commit is contained in:
John Beard 2017-02-06 13:59:55 +08:00 committed by Maciej Suminski
parent d37586aeaf
commit abe83b54ae
5 changed files with 185 additions and 9 deletions

View File

@ -189,6 +189,11 @@ TOOL_ACTION COMMON_ACTIONS::drawKeepout( "pcbnew.InteractiveDrawing.keepout",
AS_GLOBAL, 0,
_( "Add Keepout Area" ), _( "Add a keepout area" ), NULL, AF_ACTIVATE );
TOOL_ACTION COMMON_ACTIONS::drawZoneCutout( "pcbnew.InteractiveDrawing.zoneCutout",
AS_GLOBAL, 0,
_( "Add a Zone Cutout" ), _( "Add a cutout area of an existing zone" ),
add_zone_cutout_xpm, AF_ACTIVATE );
TOOL_ACTION COMMON_ACTIONS::placeDXF( "pcbnew.InteractiveDrawing.placeDXF",
AS_GLOBAL, 0,
"Place DXF", "", NULL, AF_ACTIVATE );

View File

@ -126,6 +126,9 @@ public:
/// Activation of the drawing tool (drawing a keepout area)
static TOOL_ACTION drawKeepout;
/// Activation of the drawing tool (drawing a ZONE cutout)
static TOOL_ACTION drawZoneCutout;
/// Activation of the drawing tool (placing a TARGET)
static TOOL_ACTION placeTarget;

View File

@ -545,7 +545,7 @@ int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent )
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ZONE );
m_frame->SetToolID( ID_PCB_ZONES_BUTT, wxCURSOR_PENCIL, _( "Add zones" ) );
return drawZone( false );
return drawZone( false, ZONE_MODE::ADD );
}
@ -554,7 +554,16 @@ int DRAWING_TOOL::DrawKeepout( const TOOL_EVENT& aEvent )
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::KEEPOUT );
m_frame->SetToolID( ID_PCB_KEEPOUT_AREA_BUTT, wxCURSOR_PENCIL, _( "Add keepout" ) );
return drawZone( true );
return drawZone( true, ZONE_MODE::ADD );
}
int DRAWING_TOOL::DrawZoneCutout( const TOOL_EVENT& aEvent )
{
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ZONE );
m_frame->SetToolID( ID_PCB_KEEPOUT_AREA_BUTT, wxCURSOR_PENCIL, _( "Add zone cutout" ) );
return drawZone( false, ZONE_MODE::CUTOUT );
}
@ -1186,12 +1195,89 @@ std::unique_ptr<ZONE_CONTAINER> DRAWING_TOOL::createNewZone(
}
int DRAWING_TOOL::drawZone( bool aKeepout )
std::unique_ptr<ZONE_CONTAINER> DRAWING_TOOL::createZoneFromExisting(
const ZONE_CONTAINER& aSrcZone )
{
auto newZone = std::make_unique<ZONE_CONTAINER>( m_board );
ZONE_SETTINGS zoneSettings;
zoneSettings << aSrcZone;
zoneSettings.ExportSetting( *newZone );
return newZone;
}
bool DRAWING_TOOL::getSourceZoneForAction( ZONE_MODE aMode,
ZONE_CONTAINER*& aZone )
{
aZone = nullptr;
// not an action that needs a source zone
if( aMode == ZONE_MODE::ADD )
return true;
SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
const SELECTION& selection = selTool->GetSelection();
if( selection.Empty() )
m_toolMgr->RunAction( COMMON_ACTIONS::selectionCursor, true );
// we want a single zone
if( selection.Size() != 1 )
return false;
aZone = dyn_cast<ZONE_CONTAINER*>( selection[0] );
// expected a zone, but didn't get one
if( !aZone )
return false;
return true;
}
void DRAWING_TOOL::performZoneCutout( ZONE_CONTAINER& aExistingZone,
ZONE_CONTAINER& cutout )
{
// Copy cutout corners into existing zone
for( int ii = 0; ii < cutout.GetNumCorners(); ii++ )
{
aExistingZone.AppendCorner( cutout.GetCornerPosition( ii ) );
}
// Close the current corner list
aExistingZone.Outline()->CloseLastContour();
m_board->OnAreaPolygonModified( nullptr, &aExistingZone );
// Re-fill if needed
if( aExistingZone.IsFilled() )
{
SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
auto& selection = selTool->GetSelection();
selection.Clear();
selection.Add( &aExistingZone );
m_toolMgr->RunAction( COMMON_ACTIONS::zoneFill, true );
}
}
int DRAWING_TOOL::drawZone( bool aKeepout, ZONE_MODE aMode )
{
std::unique_ptr<ZONE_CONTAINER> zone;
DRAWSEGMENT line45;
DRAWSEGMENT* helperLine = NULL; // we will need more than one helper line
BOARD_COMMIT commit( m_frame );
ZONE_CONTAINER* sourceZone = nullptr;
// get a source zone, if we need one
if( !getSourceZoneForAction( aMode, sourceZone ) )
return 0;
// Add a VIEW_GROUP that serves as a preview for the new item
SELECTION preview;
@ -1279,8 +1365,21 @@ int DRAWING_TOOL::drawZone( bool aKeepout )
if( !aKeepout )
static_cast<PCB_EDIT_FRAME*>( m_frame )->Fill_Zone( zone.get() );
commit.Add( zone.release() );
commit.Push( _( "Draw a zone" ) );
if ( aMode == ZONE_MODE::CUTOUT )
{
// For cutouts, subtract from the source
commit.Modify( sourceZone );
performZoneCutout( *sourceZone, *zone );
commit.Push( _( "Add a zone cutout" ) );
}
else
{
// Add the zone as a new board item
commit.Add( zone.release() );
commit.Push( _( "Draw a zone" ) );
}
}
// if kept, this was released. if still not null,
@ -1304,7 +1403,14 @@ int DRAWING_TOOL::drawZone( bool aKeepout )
{
if( numPoints == 0 ) // it's the first click
{
zone = createNewZone( aKeepout );
if( sourceZone )
{
zone = createZoneFromExisting( *sourceZone );
}
else
{
zone = createNewZone( aKeepout );
}
if( !zone )
{
@ -1397,6 +1503,7 @@ void DRAWING_TOOL::SetTransitions()
Go( &DRAWING_TOOL::DrawDimension, COMMON_ACTIONS::drawDimension.MakeEvent() );
Go( &DRAWING_TOOL::DrawZone, COMMON_ACTIONS::drawZone.MakeEvent() );
Go( &DRAWING_TOOL::DrawKeepout, COMMON_ACTIONS::drawKeepout.MakeEvent() );
Go( &DRAWING_TOOL::DrawZoneCutout, COMMON_ACTIONS::drawZoneCutout.MakeEvent() );
Go( &DRAWING_TOOL::PlaceText, COMMON_ACTIONS::placeText.MakeEvent() );
Go( &DRAWING_TOOL::PlaceDXF, COMMON_ACTIONS::placeDXF.MakeEvent() );
Go( &DRAWING_TOOL::SetAnchor, COMMON_ACTIONS::setAnchor.MakeEvent() );

View File

@ -143,6 +143,15 @@ public:
*/
int DrawKeepout( const TOOL_EVENT& aEvent );
/**
* Function DrawZoneCutout()
* Starts interactively drawing a zone cutout area of an existing zone.
* The normal zone interactive tool is used, but the zone settings
* dialog is not shown (since the cutout affects only shape of an
* existing zone).
*/
int DrawZoneCutout( const TOOL_EVENT& aEvent );
/**
* Function PlaceDXF()
* Places a drawing imported from a DXF file in module editor.
@ -159,6 +168,13 @@ public:
void SetTransitions() override;
private:
enum class ZONE_MODE
{
ADD, ///< Add a new zone/keepout with fresh settings
CUTOUT, ///< Make a cutout to an existing zone
};
///> Shows the context menu for the drawing tool
///> This menu consists of normal UI functions (zoom, grid, etc)
///> And any suitable global functions for the active drawing type.
@ -180,9 +196,14 @@ private:
///> the same point.
bool drawArc( DRAWSEGMENT*& aGraphic );
///> Draws a polygon, that is added as a zone or a keepout area.
///> @param aKeepout decides if the drawn polygon is a zone or a keepout area.
int drawZone( bool aKeepout );
/**
* Draws a polygon, that is added as a zone or a keepout area.
*
* @param aKeepout dictates if the drawn polygon is a zone or a
* keepout area.
* @param aMode dictates the mode of the zone tool
*/
int drawZone( bool aKeepout, ZONE_MODE aMode );
/**
* Function createNewZone()
@ -195,6 +216,44 @@ private:
*/
std::unique_ptr<ZONE_CONTAINER> createNewZone( bool aKeepout );
/**
* Function createZoneFromExisting
*
* Create a new zone with the settings from an existing zone
*
* @param aSrcZone the zone to copy settings from
* @return the new zone
*/
std::unique_ptr<ZONE_CONTAINER> createZoneFromExisting(
const ZONE_CONTAINER& aSrcZone );
/**
* Function getSourceZoneForAction()
*
* Gets a source zone item for an action that takes an existing zone
* into account (for example a cutout of an existing zone). The source
* zone is taken from the current selection
*
* @param aMode mode of the zone tool
* @param aZone updated pointer to a suitable source zone,
* or nullptr if none found, or the action doesn't need a source
* @return true if a suitable zone was found, or the action doesn't
* need a zone. False if the action needs a zone but none was found.
*/
bool getSourceZoneForAction( ZONE_MODE aMode, ZONE_CONTAINER*& aZone );
/**
* Function performZoneCutout()
*
* Cut one zone out of another one (i.e. subtraction) and
* update the zone.
*
* @param aExistingZone the zone to removed area from
* @param aCutout the area to remove
*/
void performZoneCutout( ZONE_CONTAINER& aExistingZone,
ZONE_CONTAINER& cutout );
/**
* Function make45DegLine()
* Forces a DRAWSEGMENT to be drawn at multiple of 45 degrees. The origin stays the same,

View File

@ -74,6 +74,7 @@ public:
Add( COMMON_ACTIONS::zoneMerge );
Add( COMMON_ACTIONS::zoneDuplicate );
Add( COMMON_ACTIONS::drawZoneCutout );
}
protected:
@ -93,6 +94,7 @@ private:
)( selTool->GetSelection() );
Enable( getMenuId( COMMON_ACTIONS::zoneDuplicate), singleZoneActionsEnabled );
Enable( getMenuId( COMMON_ACTIONS::drawZoneCutout), singleZoneActionsEnabled );
// enable zone actions that ably to a specific set of zones (as opposed to all of them)
bool nonGlobalActionsEnabled = ( SELECTION_CONDITIONS::MoreThan( 0 ) )( selTool->GetSelection() );