/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2007 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com * Copyright (C) 2011 Wayne Stambaugh * Copyright (C) 1992-2011 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 */ /** * @file zones_by_polygon.cpp */ #include "fctsys.h" #include "appl_wxstruct.h" #include "class_drawpanel.h" #include "confirm.h" #include "wxPcbStruct.h" #include "class_board.h" #include "class_zone.h" #include "pcbnew.h" #include "zones.h" #include "pcbnew_id.h" #include "protos.h" #include "zones_functions_for_undo_redo.h" #include "drc_stuff.h" bool s_Verbose = false; // false if zone outline diags must not be shown // Outline creation: static void Abort_Zone_Create_Outline( EDA_DRAW_PANEL* Panel, wxDC* DC ); static void Show_New_Edge_While_Move_Mouse( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase ); // Corner moving static void Abort_Zone_Move_Corner_Or_Outlines( EDA_DRAW_PANEL* Panel, wxDC* DC ); static void Show_Zone_Corner_Or_Outline_While_Move_Mouse( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase ); /* Local variables */ static wxPoint s_CornerInitialPosition; // Used to abort a move corner command static bool s_CornerIsNew; // Used to abort a move corner command (if it is a new corner, it must be deleted) static bool s_AddCutoutToCurrentZone; // if true, the next outline will be added to s_CurrentZone static ZONE_CONTAINER* s_CurrentZone; // if != NULL, these ZONE_CONTAINER params will be used for the next zone static wxPoint s_CursorLastPosition; // in move zone outline, last cursor position. Used to calculate the move vector static PICKED_ITEMS_LIST s_PickedList; // a picked list to save zones for undo/redo command static PICKED_ITEMS_LIST _AuxiliaryList; // a picked list to store zones that are deleted or added when combined #include "dialog_copper_zones.h" void PCB_EDIT_FRAME::Add_Similar_Zone( wxDC* DC, ZONE_CONTAINER* zone_container ) { if ( zone_container == NULL ) return; s_AddCutoutToCurrentZone = false; s_CurrentZone = zone_container; /* set zones setup to the current zone */ g_Zone_Default_Setting.ImportSetting( *zone_container ); // Use the general event handle to set others params (like toolbar) */ wxCommandEvent evt; evt.SetId( ID_PCB_ZONES_BUTT ); OnSelectTool( evt ); } void PCB_EDIT_FRAME::Add_Zone_Cutout( wxDC* DC, ZONE_CONTAINER* zone_container ) { if ( zone_container == NULL ) return; s_AddCutoutToCurrentZone = true; s_CurrentZone = zone_container; /* set zones setup to the current zone */ g_Zone_Default_Setting.ImportSetting( *zone_container ); // Use the general event handle to set others params (like toolbar) */ wxCommandEvent evt; evt.SetId( ID_PCB_ZONES_BUTT ); OnSelectTool( evt ); } int PCB_EDIT_FRAME::Delete_LastCreatedCorner( wxDC* DC ) { ZONE_CONTAINER* zone = GetBoard()->m_CurrentZoneContour; if( zone == NULL ) return 0; if( zone->GetNumCorners() == 0 ) return 0; zone->DrawWhileCreateOutline( m_canvas, DC, GR_XOR ); if( zone->GetNumCorners() > 2 ) { zone->m_Poly->DeleteCorner( zone->GetNumCorners() - 1 ); if( m_canvas->IsMouseCaptured() ) m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); } else { m_canvas->SetMouseCapture( NULL, NULL ); SetCurItem( NULL ); zone->RemoveAllContours(); zone->ClearFlags(); } return zone->GetNumCorners(); } /** * Function Abort_Zone_Create_Outline * cancels the Begin_Zone command if at least one EDGE_ZONE was created. */ static void Abort_Zone_Create_Outline( EDA_DRAW_PANEL* Panel, wxDC* DC ) { PCB_EDIT_FRAME* pcbframe = (PCB_EDIT_FRAME*) Panel->GetParent(); ZONE_CONTAINER* zone = pcbframe->GetBoard()->m_CurrentZoneContour; if( zone ) { zone->DrawWhileCreateOutline( Panel, DC, GR_XOR ); zone->ClearFlags(); zone->RemoveAllContours(); } pcbframe->SetCurItem( NULL ); s_AddCutoutToCurrentZone = false; s_CurrentZone = NULL; Panel->SetMouseCapture( NULL, NULL ); } void PCB_EDIT_FRAME::Start_Move_Zone_Corner( wxDC* DC, ZONE_CONTAINER* zone_container, int corner_id, bool IsNewCorner ) { if( zone_container->IsOnCopperLayer() ) /* Show the Net */ { if( GetBoard()->IsHighLightNetON() && DC ) { HighLight( DC ); // Remove old highlight selection } g_Zone_Default_Setting.m_NetcodeSelection = zone_container->GetNet(); GetBoard()->SetHighLightNet( zone_container->GetNet() ); if( DC ) HighLight( DC ); } // Prepare copy of old zones, for undo/redo. // if the corner is new, remove it from list, save and insert it in list int cx = zone_container->m_Poly->GetX( corner_id ); int cy = zone_container->m_Poly->GetY( corner_id ); if ( IsNewCorner ) zone_container->m_Poly->DeleteCorner( corner_id ); _AuxiliaryList.ClearListAndDeleteItems(); s_PickedList.ClearListAndDeleteItems(); SaveCopyOfZones( s_PickedList, GetBoard(), zone_container->GetNet(), zone_container->GetLayer() ); if ( IsNewCorner ) zone_container->m_Poly->InsertCorner(corner_id-1, cx, cy ); zone_container->SetFlags( IN_EDIT ); m_canvas->SetMouseCapture( Show_Zone_Corner_Or_Outline_While_Move_Mouse, Abort_Zone_Move_Corner_Or_Outlines ); s_CornerInitialPosition = zone_container->GetCornerPosition( corner_id ); s_CornerIsNew = IsNewCorner; s_AddCutoutToCurrentZone = false; s_CurrentZone = NULL; } void PCB_EDIT_FRAME::Start_Move_Zone_Drag_Outline_Edge( wxDC* DC, ZONE_CONTAINER* zone_container, int corner_id ) { zone_container->SetFlags( IS_DRAGGED ); zone_container->m_CornerSelection = corner_id; m_canvas->SetMouseCapture( Show_Zone_Corner_Or_Outline_While_Move_Mouse, Abort_Zone_Move_Corner_Or_Outlines ); s_CursorLastPosition = s_CornerInitialPosition = GetScreen()->GetCrossHairPosition(); s_AddCutoutToCurrentZone = false; s_CurrentZone = NULL; s_PickedList.ClearListAndDeleteItems(); _AuxiliaryList.ClearListAndDeleteItems(); SaveCopyOfZones( s_PickedList, GetBoard(), zone_container->GetNet(), zone_container->GetLayer() ); } void PCB_EDIT_FRAME::Start_Move_Zone_Outlines( wxDC* DC, ZONE_CONTAINER* zone_container ) { /* Show the Net */ if( zone_container->IsOnCopperLayer() ) /* Show the Net */ { if( GetBoard()->IsHighLightNetON() ) { HighLight( DC ); // Remove old highlight selection } g_Zone_Default_Setting.m_NetcodeSelection = zone_container->GetNet(); GetBoard()->SetHighLightNet( zone_container->GetNet() ); HighLight( DC ); } s_PickedList.ClearListAndDeleteItems(); _AuxiliaryList.ClearListAndDeleteItems(); SaveCopyOfZones( s_PickedList, GetBoard(), zone_container->GetNet(), zone_container->GetLayer() ); zone_container->SetFlags( IS_MOVED ); m_canvas->SetMouseCapture( Show_Zone_Corner_Or_Outline_While_Move_Mouse, Abort_Zone_Move_Corner_Or_Outlines ); s_CursorLastPosition = s_CornerInitialPosition = GetScreen()->GetCrossHairPosition(); s_CornerIsNew = false; s_AddCutoutToCurrentZone = false; s_CurrentZone = NULL; } void PCB_EDIT_FRAME::End_Move_Zone_Corner_Or_Outlines( wxDC* DC, ZONE_CONTAINER* zone_container ) { zone_container->ClearFlags(); m_canvas->SetMouseCapture( NULL, NULL ); if( DC ) zone_container->Draw( m_canvas, DC, GR_OR ); OnModify(); s_AddCutoutToCurrentZone = false; s_CurrentZone = NULL; SetCurItem( NULL ); // This outline can be deleted when merging outlines /* Combine zones if possible */ wxBusyCursor dummy; GetBoard()->AreaPolygonModified( &_AuxiliaryList, zone_container, true, s_Verbose ); m_canvas->Refresh(); int ii = GetBoard()->GetAreaIndex( zone_container ); // test if zone_container exists if( ii < 0 ) zone_container = NULL; // was removed by combining zones UpdateCopyOfZonesList( s_PickedList, _AuxiliaryList, GetBoard() ); SaveCopyInUndoList(s_PickedList, UR_UNSPECIFIED); s_PickedList.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items int error_count = GetBoard()->Test_Drc_Areas_Outlines_To_Areas_Outlines( zone_container, true ); if( error_count ) { DisplayError( this, _( "Area: DRC outline error" ) ); } } void PCB_EDIT_FRAME::Remove_Zone_Corner( wxDC* DC, ZONE_CONTAINER* zone_container ) { OnModify(); if( zone_container->m_Poly->GetNumCorners() <= 3 ) { m_canvas->RefreshDrawingRect( zone_container->GetBoundingBox() ); if( DC ) { // Remove the full zone because this is no more an area zone_container->UnFill(); zone_container->DrawFilledArea( m_canvas, DC, GR_XOR ); } GetBoard()->Delete( zone_container ); return; } int layer = zone_container->GetLayer(); if( DC ) { GetBoard()->RedrawAreasOutlines( m_canvas, DC, GR_XOR, layer ); GetBoard()->RedrawFilledAreas( m_canvas, DC, GR_XOR, layer ); } _AuxiliaryList.ClearListAndDeleteItems(); s_PickedList. ClearListAndDeleteItems(); SaveCopyOfZones( s_PickedList, GetBoard(), zone_container->GetNet(), zone_container->GetLayer() ); zone_container->m_Poly->DeleteCorner( zone_container->m_CornerSelection ); // modify zones outlines according to the new zone_container shape GetBoard()->AreaPolygonModified( &_AuxiliaryList, zone_container, true, s_Verbose ); if( DC ) { GetBoard()->RedrawAreasOutlines( m_canvas, DC, GR_OR, layer ); GetBoard()->RedrawFilledAreas( m_canvas, DC, GR_OR, layer ); } UpdateCopyOfZonesList( s_PickedList, _AuxiliaryList, GetBoard() ); SaveCopyInUndoList(s_PickedList, UR_UNSPECIFIED); s_PickedList.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items int ii = GetBoard()->GetAreaIndex( zone_container ); // test if zone_container exists if( ii < 0 ) zone_container = NULL; // zone_container does not exist anymore, after combining zones int error_count = GetBoard()->Test_Drc_Areas_Outlines_To_Areas_Outlines( zone_container, true ); if( error_count ) { DisplayError( this, _( "Area: DRC outline error" ) ); } } /** * Function Abort_Zone_Move_Corner_Or_Outlines * cancels the Begin_Zone state if at least one EDGE_ZONE has been created. */ void Abort_Zone_Move_Corner_Or_Outlines( EDA_DRAW_PANEL* Panel, wxDC* DC ) { PCB_EDIT_FRAME* pcbframe = (PCB_EDIT_FRAME*) Panel->GetParent(); ZONE_CONTAINER* zone_container = (ZONE_CONTAINER*) pcbframe->GetCurItem(); if( zone_container->IsMoving() ) { wxPoint offset; offset = s_CornerInitialPosition - s_CursorLastPosition; zone_container->Move( offset ); } else if( zone_container->IsDragging() ) { wxPoint offset; offset = s_CornerInitialPosition - s_CursorLastPosition; zone_container->MoveEdge( offset ); } else { if( s_CornerIsNew ) { zone_container->m_Poly->DeleteCorner( zone_container->m_CornerSelection ); } else { wxPoint pos = s_CornerInitialPosition; zone_container->m_Poly->MoveCorner( zone_container->m_CornerSelection, pos.x, pos.y ); } } Panel->SetMouseCapture( NULL, NULL ); _AuxiliaryList.ClearListAndDeleteItems(); s_PickedList. ClearListAndDeleteItems(); Panel->Refresh(); pcbframe->SetCurItem( NULL ); zone_container->ClearFlags(); s_AddCutoutToCurrentZone = false; s_CurrentZone = NULL; } /* Redraws the zone outline when moving a corner according to the cursor position */ void Show_Zone_Corner_Or_Outline_While_Move_Mouse( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase ) { PCB_EDIT_FRAME* pcbframe = (PCB_EDIT_FRAME*) aPanel->GetParent(); ZONE_CONTAINER* zone = (ZONE_CONTAINER*) pcbframe->GetCurItem(); if( aErase ) /* Undraw edge in old position*/ { zone->Draw( aPanel, aDC, GR_XOR ); } wxPoint pos = pcbframe->GetScreen()->GetCrossHairPosition(); if( zone->IsMoving() ) { wxPoint offset; offset = pos - s_CursorLastPosition; zone->Move( offset ); s_CursorLastPosition = pos; } else if( zone->IsDragging() ) { wxPoint offset; offset = pos - s_CursorLastPosition; zone->MoveEdge( offset ); s_CursorLastPosition = pos; } else { zone->m_Poly->MoveCorner( zone->m_CornerSelection, pos.x, pos.y ); } zone->Draw( aPanel, aDC, GR_XOR ); } int PCB_EDIT_FRAME::Begin_Zone( wxDC* DC ) { // verify if s_CurrentZone exists (could be deleted since last selection) : int ii; for( ii = 0; ii < GetBoard()->GetAreaCount(); ii++ ) { if( s_CurrentZone == GetBoard()->GetArea( ii ) ) break; } if( ii >= GetBoard()->GetAreaCount() ) // Not found: could be deleted since last selection { s_AddCutoutToCurrentZone = false; s_CurrentZone = NULL; } // If no zone contour in progress, a new zone is being created: if( GetBoard()->m_CurrentZoneContour == NULL ) GetBoard()->m_CurrentZoneContour = new ZONE_CONTAINER( GetBoard() ); ZONE_CONTAINER* zone = GetBoard()->m_CurrentZoneContour; if( zone->GetNumCorners() == 0 ) // Start a new contour: init zone params (net, layer ...) { if( s_CurrentZone == NULL ) // A new outline is created, from scratch { int diag; // Init zone params to reasonable values zone->SetLayer( getActiveLayer() ); // Prompt user for parameters: m_canvas->SetIgnoreMouseEvents( true ); if( zone->IsOnCopperLayer() ) { // Put a zone on a copper layer if ( GetBoard()->GetHighLightNetCode() > 0 ) { g_Zone_Default_Setting.m_NetcodeSelection = GetBoard()->GetHighLightNetCode(); zone->SetNet( g_Zone_Default_Setting.m_NetcodeSelection ); zone->SetNetNameFromNetCode( ); } wxGetApp().GetSettings()->Read( ZONE_THERMAL_RELIEF_GAP_STRING_KEY, &g_Zone_Default_Setting.m_ThermalReliefGap ); wxGetApp().GetSettings()->Read( ZONE_THERMAL_RELIEF_COPPER_WIDTH_STRING_KEY, &g_Zone_Default_Setting.m_ThermalReliefCopperBridge ); g_Zone_Default_Setting.m_CurrentZone_Layer = zone->GetLayer(); DIALOG_COPPER_ZONE* frame = new DIALOG_COPPER_ZONE( this, &g_Zone_Default_Setting ); diag = frame->ShowModal(); frame->Destroy(); } else // Put a zone on a non copper layer (technical layer) { diag = InstallDialogNonCopperZonesEditor( zone ); g_Zone_Default_Setting.m_NetcodeSelection = 0; // No net for non copper zones } m_canvas->MoveCursorToCrossHair(); m_canvas->SetIgnoreMouseEvents( false ); if( diag == ZONE_ABORT ) return 0; // Switch active layer to the selected zone layer setActiveLayer( g_Zone_Default_Setting.m_CurrentZone_Layer ); } else // Start a new contour: init zone params (net and layer) from an existing { // zone (add cutout or similar zone) g_Zone_Default_Setting.m_CurrentZone_Layer = s_CurrentZone->GetLayer(); setActiveLayer( s_CurrentZone->GetLayer() ); g_Zone_Default_Setting.ImportSetting( * s_CurrentZone); } /* Show the Net for zones on copper layers */ if( g_Zone_Default_Setting.m_CurrentZone_Layer < FIRST_NO_COPPER_LAYER ) { if( s_CurrentZone ) g_Zone_Default_Setting.m_NetcodeSelection = s_CurrentZone->GetNet(); if( GetBoard()->IsHighLightNetON() ) { HighLight( DC ); // Remove old highlight selection } GetBoard()->SetHighLightNet( g_Zone_Default_Setting.m_NetcodeSelection ); HighLight( DC ); } if( !s_AddCutoutToCurrentZone ) s_CurrentZone = NULL; // the zone is used only once ("add similar zone" command) } // if first segment if( zone->GetNumCorners() == 0 ) { zone->SetFlags( IS_NEW ); zone->SetTimeStamp( GetNewTimeStamp() ); g_Zone_Default_Setting.ExportSetting( *zone ); zone->m_Poly->Start( g_Zone_Default_Setting.m_CurrentZone_Layer, GetScreen()->GetCrossHairPosition().x, GetScreen()->GetCrossHairPosition().y, zone->GetHatchStyle() ); zone->AppendCorner( GetScreen()->GetCrossHairPosition() ); if( Drc_On && (m_drc->Drc( zone, 0 ) == BAD_DRC) && zone->IsOnCopperLayer() ) { zone->ClearFlags(); zone->RemoveAllContours(); // use the form of SetCurItem() which does not write to the msg panel, // SCREEN::SetCurItem(), so the DRC error remains on screen. // PCB_EDIT_FRAME::SetCurItem() calls DisplayInfo(). GetScreen()->SetCurItem( NULL ); DisplayError( this, _( "DRC error: this start point is inside or too close an other area" ) ); return 0; } SetCurItem( zone ); m_canvas->SetMouseCapture( Show_New_Edge_While_Move_Mouse, Abort_Zone_Create_Outline ); } else // edge in progress: { ii = zone->GetNumCorners() - 1; /* edge in progress : the current corner coordinate was set by Show_New_Edge_While_Move_Mouse */ if( zone->GetCornerPosition( ii - 1 ) != zone->GetCornerPosition( ii ) ) { if( !Drc_On || !zone->IsOnCopperLayer() || ( m_drc->Drc( zone, ii - 1 ) == OK_DRC ) ) { // Ok, we can add a new corner zone->AppendCorner( GetScreen()->GetCrossHairPosition() ); SetCurItem( zone ); // calls DisplayInfo(). } } } return zone->GetNumCorners(); } bool PCB_EDIT_FRAME::End_Zone( wxDC* DC ) { ZONE_CONTAINER* zone = GetBoard()->m_CurrentZoneContour; if( zone == NULL ) return true; // Validate the current outline: if( zone->GetNumCorners() <= 2 ) // An outline must have 3 corners or more { Abort_Zone_Create_Outline( m_canvas, DC ); return true; } // Validate the current edge: int icorner = zone->GetNumCorners() - 1; if( zone->IsOnCopperLayer() ) { if( Drc_On && m_drc->Drc( zone, icorner - 1 ) == BAD_DRC ) // we can't validate last edge return false; if( Drc_On && m_drc->Drc( zone, icorner ) == BAD_DRC ) // we can't validate the closing edge { DisplayError( this, _( "DRC error: closing this area creates a drc error with an other area" ) ); m_canvas->MoveCursorToCrossHair(); return false; } } zone->ClearFlags(); zone->DrawWhileCreateOutline( m_canvas, DC, GR_XOR ); m_canvas->SetMouseCapture( NULL, NULL ); // Undraw old drawings, because they can have important changes int layer = zone->GetLayer(); GetBoard()->RedrawAreasOutlines( m_canvas, DC, GR_XOR, layer ); GetBoard()->RedrawFilledAreas( m_canvas, DC, GR_XOR, layer ); // Save initial zones configuration, for undo/redo, before adding new zone _AuxiliaryList.ClearListAndDeleteItems(); s_PickedList.ClearListAndDeleteItems(); SaveCopyOfZones(s_PickedList, GetBoard(), zone->GetNet(), zone->GetLayer() ); /* Put new zone in list */ if( s_CurrentZone == NULL ) { zone->m_Poly->Close(); // Close the current corner list GetBoard()->Add( zone ); GetBoard()->m_CurrentZoneContour = NULL; // Add this zone in picked list, as new item ITEM_PICKER picker( zone, UR_NEW ); s_PickedList.PushItem( picker ); } else // Append this outline as a cutout to an existing zone { for( int ii = 0; ii < zone->GetNumCorners(); ii++ ) { s_CurrentZone->AppendCorner( zone->GetCornerPosition( ii ) ); } s_CurrentZone->m_Poly->Close(); // Close the current corner list zone->RemoveAllContours(); // All corners are copied in s_CurrentZone. Free corner list. zone = s_CurrentZone; } s_AddCutoutToCurrentZone = false; s_CurrentZone = NULL; GetScreen()->SetCurItem( NULL ); // This outline can be deleted when merging outlines // Combine zones if possible : GetBoard()->AreaPolygonModified( &_AuxiliaryList, zone, true, s_Verbose ); // Redraw the real edge zone : GetBoard()->RedrawAreasOutlines( m_canvas, DC, GR_OR, layer ); GetBoard()->RedrawFilledAreas( m_canvas, DC, GR_OR, layer ); int ii = GetBoard()->GetAreaIndex( zone ); // test if zone_container exists if( ii < 0 ) zone = NULL; // was removed by combining zones int error_count = GetBoard()->Test_Drc_Areas_Outlines_To_Areas_Outlines( zone, true ); if( error_count ) { DisplayError( this, _( "Area: DRC outline error" ) ); } UpdateCopyOfZonesList( s_PickedList, _AuxiliaryList, GetBoard() ); SaveCopyInUndoList(s_PickedList, UR_UNSPECIFIED); s_PickedList.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items OnModify(); return true; } /* Redraws the zone outlines when moving mouse */ static void Show_New_Edge_While_Move_Mouse( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase ) { PCB_EDIT_FRAME* pcbframe = (PCB_EDIT_FRAME*) aPanel->GetParent(); wxPoint c_pos = pcbframe->GetScreen()->GetCrossHairPosition(); ZONE_CONTAINER* zone = pcbframe->GetBoard()->m_CurrentZoneContour; if( zone == NULL ) return; int icorner = zone->GetNumCorners() - 1; if ( icorner < 1 ) return; // We must have 2 (or more) corners if( aErase ) /* Undraw edge in old position*/ { zone->DrawWhileCreateOutline( aPanel, aDC ); } /* Redraw the current edge in its new position */ if( g_Zone_45_Only ) { // calculate the new position as allowed wxPoint StartPoint = zone->GetCornerPosition( icorner - 1 ); CalculateSegmentEndPoint( c_pos, StartPoint.x, StartPoint.y, &c_pos.x, &c_pos.y ); } zone->SetCornerPosition( icorner, c_pos ); zone->DrawWhileCreateOutline( aPanel, aDC ); } void PCB_EDIT_FRAME::Edit_Zone_Params( wxDC* DC, ZONE_CONTAINER* zone_container ) { int diag; m_canvas->SetIgnoreMouseEvents( true ); /* Save initial zones configuration, for undo/redo, before adding new zone * note the net name and the layer can be changed, so we must save all zones */ _AuxiliaryList.ClearListAndDeleteItems(); s_PickedList.ClearListAndDeleteItems(); SaveCopyOfZones(s_PickedList, GetBoard(), -1, -1 ); if( zone_container->GetLayer() < FIRST_NO_COPPER_LAYER ) { // edit a zone on a copper layer g_Zone_Default_Setting.ImportSetting(*zone_container); DIALOG_COPPER_ZONE* frame = new DIALOG_COPPER_ZONE( this, &g_Zone_Default_Setting ); diag = frame->ShowModal(); frame->Destroy(); } else // edit a zone on a non copper layer (technical layer) { diag = InstallDialogNonCopperZonesEditor( zone_container ); } m_canvas->MoveCursorToCrossHair(); m_canvas->SetIgnoreMouseEvents( false ); if( diag == ZONE_ABORT ) { _AuxiliaryList.ClearListAndDeleteItems(); s_PickedList.ClearListAndDeleteItems(); return; } if( diag == ZONE_EXPORT_VALUES ) { UpdateCopyOfZonesList( s_PickedList, _AuxiliaryList, GetBoard() ); SaveCopyInUndoList(s_PickedList, UR_UNSPECIFIED); s_PickedList.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items return; } // Undraw old zone outlines for( int ii = 0; ii < GetBoard()->GetAreaCount(); ii++ ) { ZONE_CONTAINER* edge_zone = GetBoard()->GetArea( ii ); edge_zone->Draw( m_canvas, DC, GR_XOR ); } g_Zone_Default_Setting.ExportSetting( *zone_container); NETINFO_ITEM* net = GetBoard()->FindNet( g_Zone_Default_Setting.m_NetcodeSelection ); if( net ) // net == NULL should not occur zone_container->m_Netname = net->GetNetname(); // Combine zones if possible : GetBoard()->AreaPolygonModified( &_AuxiliaryList, zone_container, true, s_Verbose ); // Redraw the real new zone outlines: GetBoard()->RedrawAreasOutlines( m_canvas, DC, GR_OR, -1 ); UpdateCopyOfZonesList( s_PickedList, _AuxiliaryList, GetBoard() ); SaveCopyInUndoList(s_PickedList, UR_UNSPECIFIED); s_PickedList.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items OnModify(); } void PCB_EDIT_FRAME::Delete_Zone_Contour( wxDC* DC, ZONE_CONTAINER* zone_container ) { int ncont = zone_container->m_Poly->GetContour( zone_container->m_CornerSelection ); EDA_RECT dirty = zone_container->GetBoundingBox(); // For compatibility with old boards: remove old SEGZONE fill segments Delete_OldZone_Fill( NULL, zone_container->GetTimeStamp() ); // Remove current filling: zone_container->UnFill(); if( ncont == 0 ) // This is the main outline: remove all { SaveCopyInUndoList( zone_container, UR_DELETED ); GetBoard()->Remove( zone_container ); } else { zone_container->m_Poly->RemoveContour( ncont ); } m_canvas->RefreshDrawingRect( dirty ); OnModify(); }