/* 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 )
        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( pcbframe->GetZoneSettings().m_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 );
}
int PCB_EDIT_FRAME::Delete_LastCreatedCorner( wxDC* DC )
{
    ZONE_CONTAINER* zone = GetBoard()->m_CurrentZoneContour;

    if( !zone )
        return 0;

    if( !zone->GetNumCorners() )
        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 );
}
bool PCB_EDIT_FRAME::End_Zone( wxDC* DC )
{
    ZONE_CONTAINER* zone = GetBoard()->m_CurrentZoneContour;

    if( !zone )
        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;
    }

    // Remove the last corner if is is at the same location as the prevoius corner
    zone->m_Poly->RemoveNullSegments();

    // 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
    s_AuxiliaryList.ClearListAndDeleteItems();
    s_PickedList.ClearListAndDeleteItems();
    SaveCopyOfZones(s_PickedList, GetBoard(), zone->GetNet(), zone->GetLayer() );

    // Put new zone in list
    if( !s_CurrentZone )
    {
        zone->m_Poly->CloseLastContour(); // 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->CloseLastContour(); // 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()->OnAreaPolygonModified( &s_AuxiliaryList, zone );

    // 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 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, s_AuxiliaryList, GetBoard() );
    SaveCopyInUndoList(s_PickedList, UR_UNSPECIFIED);
    s_PickedList.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items

    OnModify();
    return true;
}