Commit cfdb2839 authored by charras's avatar charras

Pcbnew: Work on undo/redo in Pcbnew almost finished.

parent 856b7c79
...@@ -4,6 +4,11 @@ KiCad ChangeLog 2009 ...@@ -4,6 +4,11 @@ KiCad ChangeLog 2009
Please add newer entries at the top, list the date and your name with Please add newer entries at the top, list the date and your name with
email address. email address.
2009-aug-23 UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
================================================================================
++pcbnew
Work on undo/redo in pcbnew almost finished.
2009-Aug-16 UPDATE Dick Hollenbeck <dick@softplc.com> 2009-Aug-16 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================ ================================================================================
++pcbnew ++pcbnew
......
...@@ -479,12 +479,11 @@ public: ...@@ -479,12 +479,11 @@ public:
* The zone outline is a frontier, and can be complex (with holes) * The zone outline is a frontier, and can be complex (with holes)
* The filling starts from starting points like pads, tracks. * The filling starts from starting points like pads, tracks.
* If exists the old filling is removed * If exists the old filling is removed
* @param DC = current Device Context
* @param zone_container = zone to fill * @param zone_container = zone to fill
* @param verbose = true to show error messages * @param verbose = true to show error messages
* @return error level (0 = no error) * @return error level (0 = no error)
*/ */
int Fill_Zone( wxDC* DC, ZONE_CONTAINER* zone_container, bool verbose = TRUE ); int Fill_Zone( ZONE_CONTAINER* zone_container, bool verbose = TRUE );
/** Function Fill_All_Zones() /** Function Fill_All_Zones()
* Fill all zones on the board * Fill all zones on the board
......
...@@ -149,8 +149,10 @@ set(PCBNEW_SRCS ...@@ -149,8 +149,10 @@ set(PCBNEW_SRCS
work.cpp work.cpp
xchgmod.cpp xchgmod.cpp
zones_by_polygon.cpp zones_by_polygon.cpp
zones_by_polygon_fill_functions.cpp
zones_convert_brd_items_to_polygons.cpp zones_convert_brd_items_to_polygons.cpp
zone_filling_algorithm.cpp zone_filling_algorithm.cpp
zones_functions_for_undo_redo.cpp
zones_polygons_insulated_copper_islands.cpp zones_polygons_insulated_copper_islands.cpp
zones_polygons_test_connections.cpp zones_polygons_test_connections.cpp
zones_test_and_combine_areas.cpp zones_test_and_combine_areas.cpp
......
...@@ -424,7 +424,8 @@ void WinEDA_PcbFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList, ...@@ -424,7 +424,8 @@ void WinEDA_PcbFrame::SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList,
*/ */
if( commandToUndo->GetPickedItemLink( ii ) == NULL ) if( commandToUndo->GetPickedItemLink( ii ) == NULL )
commandToUndo->SetPickedItemLink( DuplicateStruct( item ), ii ); commandToUndo->SetPickedItemLink( DuplicateStruct( item ), ii );
wxASSERT( commandToUndo->GetPickedItemLink( ii ) ); if( commandToUndo->GetPickedItemLink( ii ) == NULL )
wxMessageBox( wxT( "SaveCopyInUndoList() in UR_CHANGED mode: NULL link" ) );
break; break;
case UR_MOVED: case UR_MOVED:
......
...@@ -252,7 +252,14 @@ void BOARD::Add( BOARD_ITEM* aBoardItem, int aControl ) ...@@ -252,7 +252,14 @@ void BOARD::Add( BOARD_ITEM* aBoardItem, int aControl )
// other types may use linked list // other types may use linked list
default: default:
wxFAIL_MSG( wxT( "BOARD::Add() needs work: BOARD_ITEM type not handled" ) ); {
wxString msg;
msg.Printf(
wxT( "BOARD::Add() needs work: BOARD_ITEM type (%d) not handled" ),
aBoardItem->Type() );
wxFAIL_MSG(msg );
}
break;
} }
} }
......
/**************************************************************/ /*************************************************/
/* class_board.h - Class BOARD to handle a board */ /* class_board.h - Class BOARD to handle a board */
/**************************************************************/ /*************************************************/
#ifndef CLASS_BOARD_H #ifndef CLASS_BOARD_H
#define CLASS_BOARD_H #define CLASS_BOARD_H
...@@ -474,19 +474,18 @@ public: ...@@ -474,19 +474,18 @@ public:
/* Functions used in test, merge and cut outlines */ /* Functions used in test, merge and cut outlines */
/** /** Function AddArea
* Function AddArea * Add an empty copper area to board areas list
* add empty copper area to net * @param aNewZonesList = a PICKED_ITEMS_LIST * where to store new areas pickers (useful in undo commands)
* can be NULL
* @param aNetcode = the necode of the copper area (0 = no net)
* @param aLayer = the layer of area
* @param aStartPointPosition = position of the first point of the polygon outline of this area
* @param aHatch = hacth option
* @return pointer to the new area * @return pointer to the new area
*/ */
ZONE_CONTAINER* AddArea( int netcode, int layer, int x, int y, int hatch ); ZONE_CONTAINER* AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode,
int aLayer, wxPoint aStartPointPosition, int aHatch );
/**
* remove copper area from net
* @param area = area to remove
* @return 0
*/
int RemoveArea( ZONE_CONTAINER* area_to_remove );
/** /**
* Function InsertArea * Function InsertArea
...@@ -522,15 +521,20 @@ public: ...@@ -522,15 +521,20 @@ public:
* Function ClipAreaPolygon * Function ClipAreaPolygon
* Process an area that has been modified, by clipping its polygon against itself. * Process an area that has been modified, by clipping its polygon against itself.
* This may change the number and order of copper areas in the net. * This may change the number and order of copper areas in the net.
* @param bMessageBoxInt == TRUE, shows message when clipping occurs. * @param aNewZonesList = a PICKED_ITEMS_LIST * where to store new areas pickers (useful in undo commands)
* @param bMessageBoxArc == TRUE, shows message when clipping can't be done due to arcs. * can be NULL
* @param aCurrArea = the zone to process
* @param bMessageBoxInt == true, shows message when clipping occurs.
* @param bMessageBoxArc == true, shows message when clipping can't be done due to arcs.
* @param bRetainArcs = true to handle arcs (not really used in kicad)
* @return: * @return:
* -1 if arcs intersect other sides, so polygon can't be clipped * -1 if arcs intersect other sides, so polygon can't be clipped
* 0 if no intersecting sides * 0 if no intersecting sides
* 1 if intersecting sides * 1 if intersecting sides
* Also sets areas->utility1 flags if areas are modified * Also sets areas->utility1 flags if areas are modified
*/ */
int ClipAreaPolygon( ZONE_CONTAINER* CurrArea, int ClipAreaPolygon( PICKED_ITEMS_LIST * aNewZonesList,
ZONE_CONTAINER* aCurrArea,
bool bMessageBoxArc, bool bMessageBoxArc,
bool bMessageBoxInt, bool bMessageBoxInt,
bool bRetainArcs = TRUE ); bool bRetainArcs = TRUE );
...@@ -539,6 +543,8 @@ public: ...@@ -539,6 +543,8 @@ public:
* Process an area that has been modified, by clipping its polygon against * Process an area that has been modified, by clipping its polygon against
* itself and the polygons for any other areas on the same net. * itself and the polygons for any other areas on the same net.
* This may change the number and order of copper areas in the net. * This may change the number and order of copper areas in the net.
* @param aModifiedZonesList = a PICKED_ITEMS_LIST * where to store deleted or added areas
* (useful in undo commands. Can be NULL
* @param modified_area = area to test * @param modified_area = area to test
* @param bMessageBox : if TRUE, shows message boxes when clipping occurs. * @param bMessageBox : if TRUE, shows message boxes when clipping occurs.
* @return : * @return :
...@@ -546,20 +552,31 @@ public: ...@@ -546,20 +552,31 @@ public:
* 0 if no intersecting sides * 0 if no intersecting sides
* 1 if intersecting sides, polygon clipped * 1 if intersecting sides, polygon clipped
*/ */
int AreaPolygonModified( ZONE_CONTAINER* modified_area, int AreaPolygonModified( PICKED_ITEMS_LIST* aModifiedZonesList,
ZONE_CONTAINER* modified_area,
bool bMessageBoxArc, bool bMessageBoxArc,
bool bMessageBoxInt ); bool bMessageBoxInt );
/** /**
* Function CombineAllAreasInNet * Function CombineAllAreasInNet
* Checks all copper areas in net for intersections, combining them if found * Checks all copper areas in net for intersections, combining them if found
* @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in undo commands
* can be NULL
* @param aNetCode = net to consider * @param aNetCode = net to consider
* @param bMessageBox : if true display warning message box * @param bMessageBox : if true display warning message box
* @param bUseUtility : if true, don't check areas if both utility flags are 0 * @param bUseUtility : if true, don't check areas if both utility flags are 0
* Sets utility flag = 1 for any areas modified * Sets utility flag = 1 for any areas modified
* If an area has self-intersecting arcs, doesn't try to combine it * If an area has self-intersecting arcs, doesn't try to combine it
*/ */
int CombineAllAreasInNet( int aNetCode, bool bMessageBox, bool bUseUtility ); int CombineAllAreasInNet( PICKED_ITEMS_LIST* aDeletedList, int aNetCode, bool bMessageBox, bool bUseUtility );
/** Function RemoveArea
* remove copper area from net, and put it in a deleted list (if exists)
* @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in undo commands
* can be NULL
* @param area_to_remove = area to delete or put in deleted list
*/
void RemoveArea( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_to_remove );
/** /**
* Function TestAreaIntersections * Function TestAreaIntersections
...@@ -583,13 +600,17 @@ public: ...@@ -583,13 +600,17 @@ public:
/** /**
* Function CombineAreas * Function CombineAreas
* If possible, combine 2 copper areas * If possible, combine 2 copper areas
* @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in undo commands
* can be NULL
* @param area_ref = tje main area (zone)
* @param area_to_combine = the zone that can be merged with area_ref
* area_ref must be BEFORE area_to_combine * area_ref must be BEFORE area_to_combine
* area_to_combine will be deleted, if areas are combined * area_to_combine will be deleted, if areas are combined
* @return : 0 if no intersection * @return : 0 if no intersection
* 1 if intersection * 1 if intersection
* 2 if arcs intersect * 2 if arcs intersect
*/ */
int CombineAreas( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_combine ); int CombineAreas( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_combine );
/** /**
* Function Test_Drc_Areas_Outlines_To_Areas_Outlines * Function Test_Drc_Areas_Outlines_To_Areas_Outlines
......
...@@ -1133,13 +1133,19 @@ void ZONE_CONTAINER::Copy( ZONE_CONTAINER* src ) ...@@ -1133,13 +1133,19 @@ void ZONE_CONTAINER::Copy( ZONE_CONTAINER* src )
m_Layer = src->m_Layer; m_Layer = src->m_Layer;
SetNet( src->GetNet() ); SetNet( src->GetNet() );
m_TimeStamp = src->m_TimeStamp; m_TimeStamp = src->m_TimeStamp;
m_Poly->RemoveAllContours();
m_Poly->Copy( src->m_Poly ); // copy outlines m_Poly->Copy( src->m_Poly ); // copy outlines
m_CornerSelection = -1; // For corner moving, corner index to drag, or -1 if no selection m_CornerSelection = -1; // For corner moving, corner index to drag, or -1 if no selection
m_ZoneClearance = src->m_ZoneClearance; // clearance value m_ZoneClearance = src->m_ZoneClearance; // clearance value
m_FillMode = src->m_FillMode; // Grid used for filling m_FillMode = src->m_FillMode; // Filling mode (segments/polygons)
m_ArcToSegmentsCount = src->m_ArcToSegmentsCount;
m_PadOption = src->m_PadOption; m_PadOption = src->m_PadOption;
m_ThermalReliefGapValue = src->m_ThermalReliefGapValue;
m_ThermalReliefCopperBridgeValue = src->m_ThermalReliefCopperBridgeValue;
m_Poly->SetHatch( src->m_Poly->GetHatchStyle() ); m_Poly->SetHatch( src->m_Poly->GetHatchStyle() );
m_FilledPolysList.clear();
m_FilledPolysList = src->m_FilledPolysList; m_FilledPolysList = src->m_FilledPolysList;
m_FillSegmList.clear();
m_FillSegmList = src->m_FillSegmList; m_FillSegmList = src->m_FillSegmList;
} }
......
...@@ -42,7 +42,7 @@ public: ...@@ -42,7 +42,7 @@ public:
int m_ZoneClearance; // clearance value int m_ZoneClearance; // clearance value
int m_ZoneMinThickness; // Min thickness value in filled areas int m_ZoneMinThickness; // Min thickness value in filled areas
int m_FillMode; // How to fillingareas: 0 = use polygonal areas , != 0 fill with segments int m_FillMode; // How to fillingareas: 0 = use polygonal areas , != 0 fill with segments
int m_ArcToSegmentsCount; // number of segments to convert a cirlce to a polygon (uses 16 or 32) int m_ArcToSegmentsCount; // number of segments to convert a circle to a polygon (uses 16 or 32)
int m_PadOption; // int m_PadOption; //
int m_ThermalReliefGapValue; // tickness of the gap in thermal reliefs int m_ThermalReliefGapValue; // tickness of the gap in thermal reliefs
int m_ThermalReliefCopperBridgeValue; // tickness of the copper bridge in thermal reliefs int m_ThermalReliefCopperBridgeValue; // tickness of the copper bridge in thermal reliefs
...@@ -369,6 +369,13 @@ public: ...@@ -369,6 +369,13 @@ public:
{ {
return m_Poly->GetHatchStyle(); return m_Poly->GetHatchStyle();
} }
/** function IsSame()
* test is 2 zones are equivalent:
* 2 zones are equivalent if they have same parameters and same outlines
* info relative to filling is not take in account
* @param aZoneToCompare = zone to compare with "this"
*/
bool IsSame( const ZONE_CONTAINER &aZoneToCompare);
}; };
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
/// Licence: GNU License /// Licence: GNU License
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#if defined (__GNUG__) && !defined (NO_GCC_PRAGMA) #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "zones.h" #pragma implementation "zones.h"
#endif #endif
...@@ -33,6 +33,8 @@ dialog_copper_zone::dialog_copper_zone( WinEDA_PcbFrame* parent, ZONE_SETTING* z ...@@ -33,6 +33,8 @@ dialog_copper_zone::dialog_copper_zone( WinEDA_PcbFrame* parent, ZONE_SETTING* z
m_Config = wxGetApp().m_EDA_Config; m_Config = wxGetApp().m_EDA_Config;
m_Zone_Setting = zone_setting; m_Zone_Setting = zone_setting;
m_NetSorting = 1; // 0 = alphabetic sort, 1 = pad count sort, and filtering net names m_NetSorting = 1; // 0 = alphabetic sort, 1 = pad count sort, and filtering net names
m_OnExitCode = ZONE_ABORT;
if( m_Config ) if( m_Config )
{ {
m_NetSorting = m_Config->Read( ZONE_NET_SORT_OPTION_KEY, 1l ); m_NetSorting = m_Config->Read( ZONE_NET_SORT_OPTION_KEY, 1l );
...@@ -207,7 +209,7 @@ void dialog_copper_zone::OnInitDialog( wxInitDialogEvent& event ) ...@@ -207,7 +209,7 @@ void dialog_copper_zone::OnInitDialog( wxInitDialogEvent& event )
void dialog_copper_zone::OnButtonCancelClick( wxCommandEvent& event ) void dialog_copper_zone::OnButtonCancelClick( wxCommandEvent& event )
/********************************************************************/ /********************************************************************/
{ {
EndModal( ZONE_ABORT ); EndModal( m_OnExitCode );
} }
...@@ -270,7 +272,7 @@ bool dialog_copper_zone::AcceptOptions( bool aPromptForErrors, bool aUseExportab ...@@ -270,7 +272,7 @@ bool dialog_copper_zone::AcceptOptions( bool aPromptForErrors, bool aUseExportab
// Test if this is a reasonnable value for this parameter // Test if this is a reasonnable value for this parameter
// A too large value can hang pcbnew // A too large value can hang pcbnew
#define CLEARANCE_MAX_VALUE 5000 // in 1/10000 inch #define CLEARANCE_MAX_VALUE 5000 // in 1/10000 inch
if ( m_Zone_Setting->m_ZoneClearance > CLEARANCE_MAX_VALUE ) if( m_Zone_Setting->m_ZoneClearance > CLEARANCE_MAX_VALUE )
{ {
DisplayError( this, _( "Error : Zone clearance is set to an unreasonnable value" ) ); DisplayError( this, _( "Error : Zone clearance is set to an unreasonnable value" ) );
return false; return false;
...@@ -336,13 +338,13 @@ bool dialog_copper_zone::AcceptOptions( bool aPromptForErrors, bool aUseExportab ...@@ -336,13 +338,13 @@ bool dialog_copper_zone::AcceptOptions( bool aPromptForErrors, bool aUseExportab
return false; return false;
} }
if ( ii == 0 ) // the not connected option was selected: this is not a good practice: warn: if( ii == 0 ) // the not connected option was selected: this is not a good practice: warn:
{ {
if( ! IsOK( this, _( if( !IsOK( this, _(
"You have chosen the \"not connected\" option. This will create insulated copper islands. Are you sure ?") ) "You have chosen the \"not connected\" option. This will create insulated copper islands. Are you sure ?" ) )
) )
return false; return false;
} }
wxString net_name = m_ListNetNameSelection->GetString( ii ); wxString net_name = m_ListNetNameSelection->GetString( ii );
...@@ -351,7 +353,7 @@ bool dialog_copper_zone::AcceptOptions( bool aPromptForErrors, bool aUseExportab ...@@ -351,7 +353,7 @@ bool dialog_copper_zone::AcceptOptions( bool aPromptForErrors, bool aUseExportab
/* Search net_code for this net, if a net was selected */ /* Search net_code for this net, if a net was selected */
if( m_ListNetNameSelection->GetSelection() > 0 ) if( m_ListNetNameSelection->GetSelection() > 0 )
{ {
NETINFO_ITEM* net = m_Parent->GetBoard()->FindNet(net_name); NETINFO_ITEM* net = m_Parent->GetBoard()->FindNet( net_name );
if( net ) if( net )
g_Zone_Default_Setting.m_NetcodeSelection = net->GetNet(); g_Zone_Default_Setting.m_NetcodeSelection = net->GetNet();
} }
...@@ -435,6 +437,7 @@ void dialog_copper_zone::ExportSetupToOtherCopperZones( wxCommandEvent& event ) ...@@ -435,6 +437,7 @@ void dialog_copper_zone::ExportSetupToOtherCopperZones( wxCommandEvent& event )
m_Zone_Setting->ExportSetting( *zone, false ); // false = partiel export m_Zone_Setting->ExportSetting( *zone, false ); // false = partiel export
m_Parent->GetScreen()->SetModify(); m_Parent->GetScreen()->SetModify();
} }
m_OnExitCode = ZONE_EXPORT_VALUES; // values are exported to others zones
} }
......
...@@ -6,25 +6,30 @@ ...@@ -6,25 +6,30 @@
#include "dialog_copper_zones_base.h" #include "dialog_copper_zones_base.h"
/* here is the derivated class from dialog_copper_zone_frame created by wxFormBuilder /* here is the derivated class from dialog_copper_zone_frame created by wxFormBuilder
*/ */
class dialog_copper_zone: public dialog_copper_zone_base class dialog_copper_zone : public dialog_copper_zone_base
{ {
public: public:
WinEDA_PcbFrame* m_Parent; WinEDA_PcbFrame* m_Parent;
wxConfig* m_Config; // Current config wxConfig* m_Config; // Current config
ZONE_SETTING * m_Zone_Setting; int m_OnExitCode; /* exit code: ZONE_ABORT if no change,
long m_NetSorting; * ZONE_OK if new values accepted
int m_LayerId[LAYER_COUNT]; // Handle the real layer number from layer name position in m_LayerSelectionCtrl * ZONE_EXPORT_VALUES if values are exported to others zones
*/
ZONE_SETTING* m_Zone_Setting;
long m_NetSorting;
int m_LayerId[LAYER_COUNT]; // Handle the real layer number from layer name position in m_LayerSelectionCtrl
public: public:
dialog_copper_zone( WinEDA_PcbFrame* parent, ZONE_SETTING * zone_setting); dialog_copper_zone( WinEDA_PcbFrame* parent, ZONE_SETTING* zone_setting );
void OnInitDialog( wxInitDialogEvent& event ); void OnInitDialog( wxInitDialogEvent& event );
void OnButtonOkClick( wxCommandEvent& event ); void OnButtonOkClick( wxCommandEvent& event );
void OnButtonCancelClick( wxCommandEvent& event ); void OnButtonCancelClick( wxCommandEvent& event );
bool AcceptOptions(bool aPromptForErrors, bool aUseExportableSetupOnly = false); bool AcceptOptions( bool aPromptForErrors, bool aUseExportableSetupOnly = false );
void OnNetSortingOptionSelected( wxCommandEvent& event ); void OnNetSortingOptionSelected( wxCommandEvent& event );
void ExportSetupToOtherCopperZones( wxCommandEvent& event ); void ExportSetupToOtherCopperZones( wxCommandEvent& event );
void OnPadsInZoneClick( wxCommandEvent& event ); void OnPadsInZoneClick( wxCommandEvent& event );
}; };
#endif // #ifndef DIALOG_COPPER_ZONES #endif // #ifndef DIALOG_COPPER_ZONES
...@@ -66,13 +66,14 @@ public: ...@@ -66,13 +66,14 @@ public:
public: public:
DialogPadProperties( WinEDA_BasePcbFrame* parent, D_PAD* Pad, wxDC* DC ); DialogPadProperties( WinEDA_BasePcbFrame* parent, D_PAD* Pad, wxDC* DC );
void InitDialog( wxInitDialogEvent& event ); void Init( );
void OnPadShapeSelection( wxCommandEvent& event ); void OnPadShapeSelection( wxCommandEvent& event );
void OnDrillShapeSelected( wxCommandEvent& event ); void OnDrillShapeSelected( wxCommandEvent& event );
void PadOrientEvent( wxCommandEvent& event ); void PadOrientEvent( wxCommandEvent& event );
void PadTypeSelected( wxCommandEvent& event ); void PadTypeSelected( wxCommandEvent& event );
void PadPropertiesAccept( wxCommandEvent& event ); void PadPropertiesAccept( wxCommandEvent& event );
void SetPadLayersList( long layer_mask ); void SetPadLayersList( long layer_mask );
void OnCancelButtonClick( wxCommandEvent& event );
}; };
...@@ -90,6 +91,12 @@ DialogPadProperties::DialogPadProperties( WinEDA_BasePcbFrame* parent, D_PAD* Pa ...@@ -90,6 +91,12 @@ DialogPadProperties::DialogPadProperties( WinEDA_BasePcbFrame* parent, D_PAD* Pa
Current_PadNetName = m_CurrentPad->GetNetname(); Current_PadNetName = m_CurrentPad->GetNetname();
g_Current_PadName = m_CurrentPad->ReturnStringPadName(); g_Current_PadName = m_CurrentPad->ReturnStringPadName();
} }
Init( );
if( GetSizer() )
{
GetSizer()->SetSizeHints( this );
}
} }
...@@ -104,7 +111,7 @@ void WinEDA_BasePcbFrame::InstallPadOptionsFrame( D_PAD* Pad, wxDC* DC, const wx ...@@ -104,7 +111,7 @@ void WinEDA_BasePcbFrame::InstallPadOptionsFrame( D_PAD* Pad, wxDC* DC, const wx
/**************************************************************/ /**************************************************************/
void DialogPadProperties::InitDialog( wxInitDialogEvent& event ) void DialogPadProperties::Init( )
/**************************************************************/ /**************************************************************/
{ {
int tmp; int tmp;
...@@ -235,11 +242,6 @@ void DialogPadProperties::InitDialog( wxInitDialogEvent& event ) ...@@ -235,11 +242,6 @@ void DialogPadProperties::InitDialog( wxInitDialogEvent& event )
cmd_event.SetId( m_PadType->GetSelection() ); cmd_event.SetId( m_PadType->GetSelection() );
PadTypeSelected( cmd_event ); PadTypeSelected( cmd_event );
} }
if( GetSizer() )
{
GetSizer()->SetSizeHints( this );
}
} }
...@@ -475,8 +477,8 @@ void DialogPadProperties::PadPropertiesAccept( wxCommandEvent& event ) ...@@ -475,8 +477,8 @@ void DialogPadProperties::PadPropertiesAccept( wxCommandEvent& event )
if( m_CurrentPad ) // Set Pad Name & Num if( m_CurrentPad ) // Set Pad Name & Num
{ {
m_Parent->SaveCopyInUndoList( m_Parent->GetBoard()->m_Modules, UR_CHANGED );
MODULE* Module = (MODULE*) m_CurrentPad->GetParent(); MODULE* Module = (MODULE*) m_CurrentPad->GetParent();
m_Parent->SaveCopyInUndoList( Module, UR_CHANGED );
Module->m_LastEdit_Time = time( NULL ); Module->m_LastEdit_Time = time( NULL );
if( m_DC ) // redraw the area where the pad was, without pad (delete pad on screen) if( m_DC ) // redraw the area where the pad was, without pad (delete pad on screen)
...@@ -580,10 +582,18 @@ void DialogPadProperties::PadPropertiesAccept( wxCommandEvent& event ) ...@@ -580,10 +582,18 @@ void DialogPadProperties::PadPropertiesAccept( wxCommandEvent& event )
m_Parent->GetScreen()->SetModify(); m_Parent->GetScreen()->SetModify();
} }
Close(); EndModal(1);
if( m_DC ) if( m_DC )
m_Parent->DrawPanel->CursorOn( m_DC ); m_Parent->DrawPanel->CursorOn( m_DC );
if( RastnestIsChanged ) // The net ratsnest must be recalculated if( RastnestIsChanged ) // The net ratsnest must be recalculated
m_Parent->GetBoard()->m_Status_Pcb = 0; m_Parent->GetBoard()->m_Status_Pcb = 0;
} }
/*********************************************************************/
void DialogPadProperties::OnCancelButtonClick( wxCommandEvent& event )
/*********************************************************************/
{
EndModal(0);
}
...@@ -166,21 +166,21 @@ DialogPadPropertiesBase::DialogPadPropertiesBase( wxWindow* parent, wxWindowID i ...@@ -166,21 +166,21 @@ DialogPadPropertiesBase::DialogPadPropertiesBase( wxWindow* parent, wxWindowID i
this->Centre( wxBOTH ); this->Centre( wxBOTH );
// Connect Events // Connect Events
this->Connect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DialogPadPropertiesBase::InitDialog ) );
m_PadShape->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DialogPadPropertiesBase::OnPadShapeSelection ), NULL, this ); m_PadShape->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DialogPadPropertiesBase::OnPadShapeSelection ), NULL, this );
m_DrillShapeCtrl->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DialogPadPropertiesBase::OnDrillShapeSelected ), NULL, this ); m_DrillShapeCtrl->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DialogPadPropertiesBase::OnDrillShapeSelected ), NULL, this );
m_PadOrient->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DialogPadPropertiesBase::PadOrientEvent ), NULL, this ); m_PadOrient->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DialogPadPropertiesBase::PadOrientEvent ), NULL, this );
m_PadType->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DialogPadPropertiesBase::PadTypeSelected ), NULL, this ); m_PadType->Connect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DialogPadPropertiesBase::PadTypeSelected ), NULL, this );
m_buttonOk->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DialogPadPropertiesBase::PadPropertiesAccept ), NULL, this ); m_buttonOk->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DialogPadPropertiesBase::PadPropertiesAccept ), NULL, this );
m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DialogPadPropertiesBase::OnCancelButtonClick ), NULL, this );
} }
DialogPadPropertiesBase::~DialogPadPropertiesBase() DialogPadPropertiesBase::~DialogPadPropertiesBase()
{ {
// Disconnect Events // Disconnect Events
this->Disconnect( wxEVT_INIT_DIALOG, wxInitDialogEventHandler( DialogPadPropertiesBase::InitDialog ) );
m_PadShape->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DialogPadPropertiesBase::OnPadShapeSelection ), NULL, this ); m_PadShape->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DialogPadPropertiesBase::OnPadShapeSelection ), NULL, this );
m_DrillShapeCtrl->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DialogPadPropertiesBase::OnDrillShapeSelected ), NULL, this ); m_DrillShapeCtrl->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DialogPadPropertiesBase::OnDrillShapeSelected ), NULL, this );
m_PadOrient->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DialogPadPropertiesBase::PadOrientEvent ), NULL, this ); m_PadOrient->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DialogPadPropertiesBase::PadOrientEvent ), NULL, this );
m_PadType->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DialogPadPropertiesBase::PadTypeSelected ), NULL, this ); m_PadType->Disconnect( wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler( DialogPadPropertiesBase::PadTypeSelected ), NULL, this );
m_buttonOk->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DialogPadPropertiesBase::PadPropertiesAccept ), NULL, this ); m_buttonOk->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DialogPadPropertiesBase::PadPropertiesAccept ), NULL, this );
m_buttonCancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DialogPadPropertiesBase::OnCancelButtonClick ), NULL, this );
} }
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
<event name="OnHibernate"></event> <event name="OnHibernate"></event>
<event name="OnIconize"></event> <event name="OnIconize"></event>
<event name="OnIdle"></event> <event name="OnIdle"></event>
<event name="OnInitDialog">InitDialog</event> <event name="OnInitDialog"></event>
<event name="OnKeyDown"></event> <event name="OnKeyDown"></event>
<event name="OnKeyUp"></event> <event name="OnKeyUp"></event>
<event name="OnKillFocus"></event> <event name="OnKillFocus"></event>
...@@ -760,7 +760,7 @@ ...@@ -760,7 +760,7 @@
<property name="window_extra_style"></property> <property name="window_extra_style"></property>
<property name="window_name"></property> <property name="window_name"></property>
<property name="window_style"></property> <property name="window_style"></property>
<event name="OnButtonClick"></event> <event name="OnButtonClick">OnCancelButtonClick</event>
<event name="OnChar"></event> <event name="OnChar"></event>
<event name="OnEnterWindow"></event> <event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event> <event name="OnEraseBackground"></event>
......
...@@ -78,12 +78,12 @@ class DialogPadPropertiesBase : public wxDialog ...@@ -78,12 +78,12 @@ class DialogPadPropertiesBase : public wxDialog
wxCheckBox* m_PadLayerDraft; wxCheckBox* m_PadLayerDraft;
// Virtual event handlers, overide them in your derived class // Virtual event handlers, overide them in your derived class
virtual void InitDialog( wxInitDialogEvent& event ){ event.Skip(); }
virtual void OnPadShapeSelection( wxCommandEvent& event ){ event.Skip(); } virtual void OnPadShapeSelection( wxCommandEvent& event ){ event.Skip(); }
virtual void OnDrillShapeSelected( wxCommandEvent& event ){ event.Skip(); } virtual void OnDrillShapeSelected( wxCommandEvent& event ){ event.Skip(); }
virtual void PadOrientEvent( wxCommandEvent& event ){ event.Skip(); } virtual void PadOrientEvent( wxCommandEvent& event ){ event.Skip(); }
virtual void PadTypeSelected( wxCommandEvent& event ){ event.Skip(); } virtual void PadTypeSelected( wxCommandEvent& event ){ event.Skip(); }
virtual void PadPropertiesAccept( wxCommandEvent& event ){ event.Skip(); } virtual void PadPropertiesAccept( wxCommandEvent& event ){ event.Skip(); }
virtual void OnCancelButtonClick( wxCommandEvent& event ){ event.Skip(); }
public: public:
......
...@@ -609,8 +609,7 @@ void WinEDA_PcbFrame::Process_Special_Functions( wxCommandEvent& event ) ...@@ -609,8 +609,7 @@ void WinEDA_PcbFrame::Process_Special_Functions( wxCommandEvent& event )
*/ */
zone_cont->Draw( DrawPanel, &dc, GR_XOR ); zone_cont->Draw( DrawPanel, &dc, GR_XOR );
zone_cont->m_Poly->InsertCorner( zone_cont->m_CornerSelection, zone_cont->m_Poly->InsertCorner( zone_cont->m_CornerSelection,
pos.x, pos.x, pos.y );
pos.y );
zone_cont->m_CornerSelection++; zone_cont->m_CornerSelection++;
zone_cont->Draw( DrawPanel, &dc, GR_XOR ); zone_cont->Draw( DrawPanel, &dc, GR_XOR );
DrawPanel->m_AutoPAN_Request = true; DrawPanel->m_AutoPAN_Request = true;
...@@ -669,7 +668,7 @@ void WinEDA_PcbFrame::Process_Special_Functions( wxCommandEvent& event ) ...@@ -669,7 +668,7 @@ void WinEDA_PcbFrame::Process_Special_Functions( wxCommandEvent& event )
case ID_POPUP_PCB_FILL_ZONE: case ID_POPUP_PCB_FILL_ZONE:
DrawPanel->MouseToCursorSchema(); DrawPanel->MouseToCursorSchema();
Fill_Zone( NULL, (ZONE_CONTAINER*) GetCurItem() ); Fill_Zone( (ZONE_CONTAINER*) GetCurItem() );
test_1_net_connexion( NULL, ( (ZONE_CONTAINER*) GetCurItem() )->GetNet() ); test_1_net_connexion( NULL, ( (ZONE_CONTAINER*) GetCurItem() )->GetNet() );
GetBoard()->DisplayInfo( this ); GetBoard()->DisplayInfo( this );
DrawPanel->Refresh(); DrawPanel->Refresh();
......
...@@ -16,9 +16,11 @@ ...@@ -16,9 +16,11 @@
#define ZONE_THERMAL_RELIEF_GAP_STRING_KEY wxT( "Zone_TH_Gap" ) #define ZONE_THERMAL_RELIEF_GAP_STRING_KEY wxT( "Zone_TH_Gap" )
#define ZONE_THERMAL_RELIEF_COPPER_WIDTH_STRING_KEY wxT( "Zone_TH_Copper_Width" ) #define ZONE_THERMAL_RELIEF_COPPER_WIDTH_STRING_KEY wxT( "Zone_TH_Copper_Width" )
// Exit codes for dialog edit zones
enum zone_cmd { enum zone_cmd {
ZONE_ABORT, ZONE_ABORT, // if no change
ZONE_OK ZONE_OK, // if new values accepted
ZONE_EXPORT_VALUES // if values are exported to others zones
}; };
......
...@@ -14,10 +14,9 @@ ...@@ -14,10 +14,9 @@
#include "zones.h" #include "zones.h"
#include "id.h" #include "id.h"
#include "protos.h" #include "protos.h"
#include "zones_functions_for_undo_redo.h"
using namespace std; bool s_Verbose = false; // false if zone outline diags must not be shown
bool verbose = false; // false if zone outline diags must not be shown
// Outline creation: // Outline creation:
static void Abort_Zone_Create_Outline( WinEDA_DrawPanel* Panel, wxDC* DC ); static void Abort_Zone_Create_Outline( WinEDA_DrawPanel* Panel, wxDC* DC );
...@@ -30,11 +29,13 @@ static void Show_Zone_Corner_Or_Outline_While_Move_Mouse( WinEDA_DrawPanel* pane ...@@ -30,11 +29,13 @@ static void Show_Zone_Corner_Or_Outline_While_Move_Mouse( WinEDA_DrawPanel* pane
bool erase ); bool erase );
/* Local variables */ /* Local variables */
static wxPoint s_CornerInitialPosition; // Used to abort a move corner command 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_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 addes to s_CurrentZone static bool s_AddCutoutToCurrentZone; // if true, the next outline will be addes to s_CurrentZone
static ZONE_CONTAINER* s_CurrentZone; // if != NULL, these ZONE_CONTAINER params will be used for the next zone 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 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" #include "dialog_copper_zones.h"
...@@ -91,59 +92,6 @@ void WinEDA_PcbFrame::Add_Zone_Cutout( wxDC* DC, ZONE_CONTAINER* zone_container ...@@ -91,59 +92,6 @@ void WinEDA_PcbFrame::Add_Zone_Cutout( wxDC* DC, ZONE_CONTAINER* zone_container
} }
/**********************************************************************************/
void WinEDA_PcbFrame::Delete_Zone_Fill( SEGZONE* aZone, long aTimestamp )
/**********************************************************************************/
/** Function Delete_Zone_Fill
* Remove the zone fillig which include the segment aZone, or the zone which have the given time stamp.
* A zone is a group of segments which have the same TimeStamp
* @param DC = current Device Context (can be NULL)
* @param aZone = zone segment within the zone to delete. Can be NULL
* @param aTimestamp = Timestamp for the zone to delete, used if aZone == NULL
*/
{
bool modify = false;
unsigned long TimeStamp;
if( aZone == NULL )
TimeStamp = aTimestamp;
else
TimeStamp = aZone->m_TimeStamp; // Save reference time stamp (aZone will be deleted)
SEGZONE* next;
for( SEGZONE* zone = GetBoard()->m_Zone; zone != NULL; zone = next )
{
next = zone->Next();
if( zone->m_TimeStamp == TimeStamp )
{
modify = TRUE;
/* remove item from linked list and free memory */
zone->DeleteStructure();
}
}
// Now delete the outlines of the corresponding copper areas (deprecated)
for( int ii = 0; ii < GetBoard()->GetAreaCount(); ii++ )
{
ZONE_CONTAINER* zone = GetBoard()->GetArea( ii );
if( zone->m_TimeStamp == TimeStamp )
{
modify = TRUE;
zone->m_FilledPolysList.clear();
zone->m_FillSegmList.clear();
zone->m_IsFilled = false;
}
}
if( modify )
{
GetScreen()->SetModify();
GetScreen()->SetRefreshReq();
}
}
/*******************************************************/ /*******************************************************/
int WinEDA_PcbFrame::Delete_LastCreatedCorner( wxDC* DC ) int WinEDA_PcbFrame::Delete_LastCreatedCorner( wxDC* DC )
/*******************************************************/ /*******************************************************/
...@@ -232,6 +180,22 @@ void WinEDA_PcbFrame::Start_Move_Zone_Corner( wxDC* DC, ZONE_CONTAINER* zone_con ...@@ -232,6 +180,22 @@ void WinEDA_PcbFrame::Start_Move_Zone_Corner( wxDC* DC, ZONE_CONTAINER* zone_con
Hight_Light( DC ); Hight_Light( 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->m_Flags = IN_EDIT; zone_container->m_Flags = IN_EDIT;
DrawPanel->ManageCurseur = Show_Zone_Corner_Or_Outline_While_Move_Mouse; DrawPanel->ManageCurseur = Show_Zone_Corner_Or_Outline_While_Move_Mouse;
DrawPanel->ForceCloseManageCurseur = Abort_Zone_Move_Corner_Or_Outlines; DrawPanel->ForceCloseManageCurseur = Abort_Zone_Move_Corner_Or_Outlines;
...@@ -249,7 +213,7 @@ void WinEDA_PcbFrame::Start_Move_Zone_Drag_Outline_Edge( wxDC* DC, ...@@ -249,7 +213,7 @@ void WinEDA_PcbFrame::Start_Move_Zone_Drag_Outline_Edge( wxDC* DC,
/**************************************************************************************/ /**************************************************************************************/
/** /**
* Function Start_Move_Zone_Corner * Function Start_Move_Zone_Drag_Outline_Edge
* Prepares a drag edge for an existing zone outline, * Prepares a drag edge for an existing zone outline,
*/ */
{ {
...@@ -260,6 +224,11 @@ void WinEDA_PcbFrame::Start_Move_Zone_Drag_Outline_Edge( wxDC* DC, ...@@ -260,6 +224,11 @@ void WinEDA_PcbFrame::Start_Move_Zone_Drag_Outline_Edge( wxDC* DC,
s_CursorLastPosition = s_CornerInitialPosition = GetScreen()->m_Curseur; s_CursorLastPosition = s_CornerInitialPosition = GetScreen()->m_Curseur;
s_AddCutoutToCurrentZone = false; s_AddCutoutToCurrentZone = false;
s_CurrentZone = NULL; s_CurrentZone = NULL;
s_PickedList.ClearListAndDeleteItems();
_AuxiliaryList.ClearListAndDeleteItems();
SaveCopyOfZones(s_PickedList, GetBoard(), zone_container->GetNet(), zone_container->GetLayer() );
} }
...@@ -284,6 +253,10 @@ void WinEDA_PcbFrame::Start_Move_Zone_Outlines( wxDC* DC, ZONE_CONTAINER* zone_c ...@@ -284,6 +253,10 @@ void WinEDA_PcbFrame::Start_Move_Zone_Outlines( wxDC* DC, ZONE_CONTAINER* zone_c
Hight_Light( DC ); Hight_Light( DC );
} }
s_PickedList.ClearListAndDeleteItems();
_AuxiliaryList.ClearListAndDeleteItems();
SaveCopyOfZones(s_PickedList, GetBoard(), zone_container->GetNet(), zone_container->GetLayer() );
zone_container->m_Flags = IS_MOVED; zone_container->m_Flags = IS_MOVED;
DrawPanel->ManageCurseur = Show_Zone_Corner_Or_Outline_While_Move_Mouse; DrawPanel->ManageCurseur = Show_Zone_Corner_Or_Outline_While_Move_Mouse;
DrawPanel->ForceCloseManageCurseur = Abort_Zone_Move_Corner_Or_Outlines; DrawPanel->ForceCloseManageCurseur = Abort_Zone_Move_Corner_Or_Outlines;
...@@ -318,7 +291,7 @@ void WinEDA_PcbFrame::End_Move_Zone_Corner_Or_Outlines( wxDC* DC, ZONE_CONTAINER ...@@ -318,7 +291,7 @@ void WinEDA_PcbFrame::End_Move_Zone_Corner_Or_Outlines( wxDC* DC, ZONE_CONTAINER
/* Combine zones if possible */ /* Combine zones if possible */
wxBusyCursor dummy; wxBusyCursor dummy;
GetBoard()->AreaPolygonModified( zone_container, true, verbose ); GetBoard()->AreaPolygonModified( &_AuxiliaryList, zone_container, true, s_Verbose );
DrawPanel->Refresh(); DrawPanel->Refresh();
...@@ -326,6 +299,10 @@ void WinEDA_PcbFrame::End_Move_Zone_Corner_Or_Outlines( wxDC* DC, ZONE_CONTAINER ...@@ -326,6 +299,10 @@ void WinEDA_PcbFrame::End_Move_Zone_Corner_Or_Outlines( wxDC* DC, ZONE_CONTAINER
if( ii < 0 ) if( ii < 0 )
zone_container = NULL; // was removed by combining zones 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 ); int error_count = GetBoard()->Test_Drc_Areas_Outlines_To_Areas_Outlines( zone_container, true );
if( error_count ) if( error_count )
{ {
...@@ -342,7 +319,7 @@ void WinEDA_PcbFrame::Remove_Zone_Corner( wxDC* DC, ZONE_CONTAINER* zone_contain ...@@ -342,7 +319,7 @@ void WinEDA_PcbFrame::Remove_Zone_Corner( wxDC* DC, ZONE_CONTAINER* zone_contain
* Function Remove_Zone_Corner * Function Remove_Zone_Corner
* Remove the currently selected corner in a zone outline * Remove the currently selected corner in a zone outline
* the .m_CornerSelection is used as corner selection * the .m_CornerSelection is used as corner selection
* @param DC = Current deice context (can be NULL ) * @param DC = Current device context (can be NULL )
* @param zone_container = the zone that contains the selected corner * @param zone_container = the zone that contains the selected corner
* the member .m_CornerSelection is used as selected corner * the member .m_CornerSelection is used as selected corner
*/ */
...@@ -369,16 +346,23 @@ void WinEDA_PcbFrame::Remove_Zone_Corner( wxDC* DC, ZONE_CONTAINER* zone_contain ...@@ -369,16 +346,23 @@ void WinEDA_PcbFrame::Remove_Zone_Corner( wxDC* DC, ZONE_CONTAINER* zone_contain
GetBoard()->RedrawFilledAreas( DrawPanel, DC, GR_XOR, layer ); GetBoard()->RedrawFilledAreas( DrawPanel, 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 ); zone_container->m_Poly->DeleteCorner( zone_container->m_CornerSelection );
// modify zones outlines according to the new zone_container shape // modify zones outlines according to the new zone_container shape
GetBoard()->AreaPolygonModified( zone_container, true, verbose ); GetBoard()->AreaPolygonModified( &_AuxiliaryList, zone_container, true, s_Verbose );
if( DC ) if( DC )
{ {
GetBoard()->RedrawAreasOutlines( DrawPanel, DC, GR_OR, layer ); GetBoard()->RedrawAreasOutlines( DrawPanel, DC, GR_OR, layer );
GetBoard()->RedrawFilledAreas( DrawPanel, DC, GR_OR, layer ); GetBoard()->RedrawFilledAreas( DrawPanel, 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 int ii = GetBoard()->GetAreaIndex( zone_container ); // test if zone_container exists
if( ii < 0 ) if( ii < 0 )
zone_container = NULL; // zone_container does not exist anymaore, after combining zones zone_container = NULL; // zone_container does not exist anymaore, after combining zones
...@@ -402,8 +386,6 @@ void Abort_Zone_Move_Corner_Or_Outlines( WinEDA_DrawPanel* Panel, wxDC* DC ) ...@@ -402,8 +386,6 @@ void Abort_Zone_Move_Corner_Or_Outlines( WinEDA_DrawPanel* Panel, wxDC* DC )
WinEDA_PcbFrame* pcbframe = (WinEDA_PcbFrame*) Panel->m_Parent; WinEDA_PcbFrame* pcbframe = (WinEDA_PcbFrame*) Panel->m_Parent;
ZONE_CONTAINER* zone_container = (ZONE_CONTAINER*) pcbframe->GetCurItem(); ZONE_CONTAINER* zone_container = (ZONE_CONTAINER*) pcbframe->GetCurItem();
// zone_container->Draw( Panel, DC, GR_XOR );
if( zone_container->m_Flags == IS_MOVED ) if( zone_container->m_Flags == IS_MOVED )
{ {
wxPoint offset; wxPoint offset;
...@@ -429,10 +411,10 @@ void Abort_Zone_Move_Corner_Or_Outlines( WinEDA_DrawPanel* Panel, wxDC* DC ) ...@@ -429,10 +411,10 @@ void Abort_Zone_Move_Corner_Or_Outlines( WinEDA_DrawPanel* Panel, wxDC* DC )
} }
} }
// zone_container->Draw( Panel, DC, GR_XOR ); _AuxiliaryList.ClearListAndDeleteItems();
s_PickedList. ClearListAndDeleteItems();
Panel->Refresh(); Panel->Refresh();
Panel->ManageCurseur = NULL; Panel->ManageCurseur = NULL;
Panel->ForceCloseManageCurseur = NULL; Panel->ForceCloseManageCurseur = NULL;
pcbframe->SetCurItem( NULL ); pcbframe->SetCurItem( NULL );
...@@ -644,7 +626,7 @@ bool WinEDA_PcbFrame::End_Zone( wxDC* DC ) ...@@ -644,7 +626,7 @@ bool WinEDA_PcbFrame::End_Zone( wxDC* DC )
if( zone == NULL ) if( zone == NULL )
return true; return true;
// Validate the curren outline: // Validate the current outline:
if( zone->GetNumCorners() <= 2 ) // An outline must have 3 corners or more if( zone->GetNumCorners() <= 2 ) // An outline must have 3 corners or more
{ {
Abort_Zone_Create_Outline( DrawPanel, DC ); Abort_Zone_Create_Outline( DrawPanel, DC );
...@@ -678,12 +660,20 @@ bool WinEDA_PcbFrame::End_Zone( wxDC* DC ) ...@@ -678,12 +660,20 @@ bool WinEDA_PcbFrame::End_Zone( wxDC* DC )
GetBoard()->RedrawAreasOutlines( DrawPanel, DC, GR_XOR, layer ); GetBoard()->RedrawAreasOutlines( DrawPanel, DC, GR_XOR, layer );
GetBoard()->RedrawFilledAreas( DrawPanel, DC, GR_XOR, layer ); GetBoard()->RedrawFilledAreas( DrawPanel, DC, GR_XOR, layer );
/* Put edges in list */ // 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 ) if( s_CurrentZone == NULL )
{ {
zone->m_Poly->Close(); // Close the current corner list zone->m_Poly->Close(); // Close the current corner list
GetBoard()->Add( zone ); GetBoard()->Add( zone );
GetBoard()->m_CurrentZoneContour = NULL; 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 else // Append this outline as a cutout to an existing zone
{ {
...@@ -703,7 +693,7 @@ bool WinEDA_PcbFrame::End_Zone( wxDC* DC ) ...@@ -703,7 +693,7 @@ bool WinEDA_PcbFrame::End_Zone( wxDC* DC )
GetScreen()->SetCurItem( NULL ); // This outine can be deleted when merging outlines GetScreen()->SetCurItem( NULL ); // This outine can be deleted when merging outlines
// Combine zones if possible : // Combine zones if possible :
GetBoard()->AreaPolygonModified( zone, true, verbose ); GetBoard()->AreaPolygonModified( &_AuxiliaryList, zone, true, s_Verbose );
// Redraw the real edge zone : // Redraw the real edge zone :
GetBoard()->RedrawAreasOutlines( DrawPanel, DC, GR_OR, layer ); GetBoard()->RedrawAreasOutlines( DrawPanel, DC, GR_OR, layer );
...@@ -712,12 +702,17 @@ bool WinEDA_PcbFrame::End_Zone( wxDC* DC ) ...@@ -712,12 +702,17 @@ bool WinEDA_PcbFrame::End_Zone( wxDC* DC )
int ii = GetBoard()->GetAreaIndex( zone ); // test if zone_container exists int ii = GetBoard()->GetAreaIndex( zone ); // test if zone_container exists
if( ii < 0 ) if( ii < 0 )
zone = NULL; // was removed by combining zones zone = NULL; // was removed by combining zones
int error_count = GetBoard()->Test_Drc_Areas_Outlines_To_Areas_Outlines( zone, true ); int error_count = GetBoard()->Test_Drc_Areas_Outlines_To_Areas_Outlines( zone, true );
if( error_count ) if( error_count )
{ {
DisplayError( this, _( "Area: DRC outline error" ) ); 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
GetScreen()->SetModify(); GetScreen()->SetModify();
return true; return true;
} }
...@@ -727,7 +722,7 @@ bool WinEDA_PcbFrame::End_Zone( wxDC* DC ) ...@@ -727,7 +722,7 @@ bool WinEDA_PcbFrame::End_Zone( wxDC* DC )
static void Show_New_Edge_While_Move_Mouse( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ) static void Show_New_Edge_While_Move_Mouse( WinEDA_DrawPanel* panel, wxDC* DC, bool erase )
/******************************************************************************************/ /******************************************************************************************/
/* Redraws the edge zone when moving mouse /* Redraws the zone outlines when moving mouse
*/ */
{ {
WinEDA_PcbFrame* pcbframe = (WinEDA_PcbFrame*) panel->m_Parent; WinEDA_PcbFrame* pcbframe = (WinEDA_PcbFrame*) panel->m_Parent;
...@@ -772,6 +767,14 @@ void WinEDA_PcbFrame::Edit_Zone_Params( wxDC* DC, ZONE_CONTAINER* zone_container ...@@ -772,6 +767,14 @@ void WinEDA_PcbFrame::Edit_Zone_Params( wxDC* DC, ZONE_CONTAINER* zone_container
{ {
int diag; int diag;
DrawPanel->m_IgnoreMouseEvents = TRUE; DrawPanel->m_IgnoreMouseEvents = 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 ) if( zone_container->GetLayer() < FIRST_NO_COPPER_LAYER )
{ // edit a zone on a copper layer { // edit a zone on a copper layer
g_Zone_Default_Setting.ImportSetting(*zone_container); g_Zone_Default_Setting.ImportSetting(*zone_container);
...@@ -786,7 +789,18 @@ void WinEDA_PcbFrame::Edit_Zone_Params( wxDC* DC, ZONE_CONTAINER* zone_container ...@@ -786,7 +789,18 @@ void WinEDA_PcbFrame::Edit_Zone_Params( wxDC* DC, ZONE_CONTAINER* zone_container
DrawPanel->m_IgnoreMouseEvents = FALSE; DrawPanel->m_IgnoreMouseEvents = FALSE;
if( diag == ZONE_ABORT ) 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; return;
}
// Undraw old zone outlines // Undraw old zone outlines
for( int ii = 0; ii < GetBoard()->GetAreaCount(); ii++ ) for( int ii = 0; ii < GetBoard()->GetAreaCount(); ii++ )
...@@ -797,16 +811,19 @@ void WinEDA_PcbFrame::Edit_Zone_Params( wxDC* DC, ZONE_CONTAINER* zone_container ...@@ -797,16 +811,19 @@ void WinEDA_PcbFrame::Edit_Zone_Params( wxDC* DC, ZONE_CONTAINER* zone_container
g_Zone_Default_Setting.ExportSetting( *zone_container); g_Zone_Default_Setting.ExportSetting( *zone_container);
NETINFO_ITEM* net = GetBoard()->FindNet( g_Zone_Default_Setting.m_NetcodeSelection ); NETINFO_ITEM* net = GetBoard()->FindNet( g_Zone_Default_Setting.m_NetcodeSelection );
if( net ) // net === NULL should not occur if( net ) // net == NULL should not occur
zone_container->m_Netname = net->GetNetname(); zone_container->m_Netname = net->GetNetname();
// Combine zones if possible : // Combine zones if possible :
GetBoard()->AreaPolygonModified( zone_container, true, verbose ); GetBoard()->AreaPolygonModified( &_AuxiliaryList, zone_container, true, s_Verbose );
// Redraw the real new zone outlines: // Redraw the real new zone outlines:
GetBoard()->RedrawAreasOutlines( DrawPanel, DC, GR_OR, -1 ); GetBoard()->RedrawAreasOutlines( DrawPanel, 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
GetScreen()->SetModify(); GetScreen()->SetModify();
} }
...@@ -847,106 +864,3 @@ void WinEDA_PcbFrame::Delete_Zone_Contour( wxDC* DC, ZONE_CONTAINER* zone_contai ...@@ -847,106 +864,3 @@ void WinEDA_PcbFrame::Delete_Zone_Contour( wxDC* DC, ZONE_CONTAINER* zone_contai
GetScreen()->SetModify(); GetScreen()->SetModify();
} }
/***************************************************************************************/
int WinEDA_PcbFrame::Fill_Zone( wxDC* DC, ZONE_CONTAINER* zone_container, bool verbose )
/***************************************************************************************/
/** Function Fill_Zone()
* Calculate the zone filling for the outline zone_container
* The zone outline is a frontier, and can be complex (with holes)
* The filling starts from starting points like pads, tracks.
* If exists, the old filling is removed
* @param DC = current Device Context
* @param zone_container = zone to fill
* @param verbose = true to show error messages
* @return error level (0 = no error)
*/
{
wxString msg;
MsgPanel->EraseMsgBox();
if( GetBoard()->ComputeBoundaryBox() == FALSE )
{
if( verbose )
DisplayError( this, wxT( "Board is empty!" ), 10 );
return -1;
}
/* Shows the Net */
g_Zone_Default_Setting.m_NetcodeSelection = zone_container->GetNet();
if( g_HightLigt_Status && (g_HightLigth_NetCode != g_Zone_Default_Setting.m_NetcodeSelection) && DC )
{
Hight_Light( DC ); // Remove old highlight selection
}
g_HightLigth_NetCode = g_Zone_Default_Setting.m_NetcodeSelection;
if( DC )
Hight_Light( DC );
if( g_HightLigth_NetCode > 0 )
{
NETINFO_ITEM* net = GetBoard()->FindNet( g_HightLigth_NetCode );
if( net == NULL )
{
if( g_HightLigth_NetCode > 0 )
{
if( verbose )
DisplayError( this, wxT( "Unable to find Net name" ) );
return -2;
}
}
else
msg = net->GetNetname();
}
else
msg = _( "No Net" );
Affiche_1_Parametre( this, 22, _( "NetName" ), msg, RED );
wxBusyCursor dummy; // Shows an hourglass cursor (removed by its destructor)
int error_level = 0;
zone_container->m_FilledPolysList.clear();
Delete_Zone_Fill( NULL, zone_container->m_TimeStamp );
zone_container->BuildFilledPolysListData( GetBoard() );
if ( DC )
DrawPanel->Refresh();
GetScreen()->SetModify();
return error_level;
}
/************************************************************/
int WinEDA_PcbFrame::Fill_All_Zones( bool verbose )
/************************************************************/
/** Function Fill_All_Zones()
* Fill all zones on the board
* The old fillings are removed
* @param verbose = true to show error messages
* @return error level (0 = no error)
*/
{
ZONE_CONTAINER* zone_container;
int error_level = 0;
// Remove all zones :
GetBoard()->m_Zone.DeleteAll();
for( int ii = 0; ii < GetBoard()->GetAreaCount(); ii++ )
{
zone_container = GetBoard()->GetArea( ii );
error_level = Fill_Zone( NULL, zone_container, verbose );
if( error_level && !verbose )
break;
}
test_connexions( NULL );
Tst_Ratsnest( NULL, 0 ); // Recalculate the active ratsnest, i.e. the unconnected links */
DrawPanel->Refresh( true );
return error_level;
}
/////////////////////////////////////////////////////////////////////////////
// Name: zones_by_polygon_fill_functions.cpp
/////////////////////////////////////////////////////////////////////////////
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2009 Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
* Copyright (C) 2007 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 "fctsys.h"
#include "appl_wxstruct.h"
#include "common.h"
#include "class_drawpanel.h"
#include "pcbnew.h"
#include "wxPcbStruct.h"
#include "zones.h"
/**********************************************************************************/
void WinEDA_PcbFrame::Delete_Zone_Fill( SEGZONE* aZone, long aTimestamp )
/**********************************************************************************/
/** Function Delete_Zone_Fill
* Remove the zone fillig which include the segment aZone, or the zone which have the given time stamp.
* A zone is a group of segments which have the same TimeStamp
* @param DC = current Device Context (can be NULL)
* @param aZone = zone segment within the zone to delete. Can be NULL
* @param aTimestamp = Timestamp for the zone to delete, used if aZone == NULL
*/
{
bool modify = false;
unsigned long TimeStamp;
if( aZone == NULL )
TimeStamp = aTimestamp;
else
TimeStamp = aZone->m_TimeStamp; // Save reference time stamp (aZone will be deleted)
SEGZONE* next;
for( SEGZONE* zone = GetBoard()->m_Zone; zone != NULL; zone = next )
{
next = zone->Next();
if( zone->m_TimeStamp == TimeStamp )
{
modify = TRUE;
/* remove item from linked list and free memory */
zone->DeleteStructure();
}
}
// Now delete the outlines of the corresponding copper areas (deprecated)
for( int ii = 0; ii < GetBoard()->GetAreaCount(); ii++ )
{
ZONE_CONTAINER* zone = GetBoard()->GetArea( ii );
if( zone->m_TimeStamp == TimeStamp )
{
modify = TRUE;
zone->m_FilledPolysList.clear();
zone->m_FillSegmList.clear();
zone->m_IsFilled = false;
}
}
if( modify )
{
GetScreen()->SetModify();
GetScreen()->SetRefreshReq();
}
}
/***************************************************************************************/
int WinEDA_PcbFrame::Fill_Zone( ZONE_CONTAINER* zone_container, bool verbose )
/***************************************************************************************/
/** Function Fill_Zone()
* Calculate the zone filling for the outline zone_container
* The zone outline is a frontier, and can be complex (with holes)
* The filling starts from starting points like pads, tracks.
* If exists, the old filling is removed
* @param zone_container = zone to fill
* @param verbose = true to show error messages
* @return error level (0 = no error)
*/
{
wxString msg;
MsgPanel->EraseMsgBox();
if( GetBoard()->ComputeBoundaryBox() == false )
{
if( verbose )
wxMessageBox( wxT( "Board is empty!" ) );
return -1;
}
/* Shows the Net */
g_Zone_Default_Setting.m_NetcodeSelection = zone_container->GetNet();
if( zone_container->GetNet() > 0 )
{
NETINFO_ITEM* net = GetBoard()->FindNet( zone_container->GetNet() );
if( net == NULL )
{
if( verbose )
wxMessageBox( wxT( "Unable to find Net name" ) );
return -2;
}
else
msg = net->GetNetname();
}
else
msg = _( "No Net" );
Affiche_1_Parametre( this, 22, _( "NetName" ), msg, RED );
wxBusyCursor dummy; // Shows an hourglass cursor (removed by its destructor)
zone_container->m_FilledPolysList.clear();
Delete_Zone_Fill( NULL, zone_container->m_TimeStamp );
zone_container->BuildFilledPolysListData( GetBoard() );
GetScreen()->SetModify();
return 0;
}
/************************************************************/
int WinEDA_PcbFrame::Fill_All_Zones( bool verbose )
/************************************************************/
/** Function Fill_All_Zones()
* Fill all zones on the board
* The old fillings are removed
* @param verbose = true to show error messages
* @return error level (0 = no error)
*/
{
ZONE_CONTAINER* zone_container;
int error_level = 0;
// Remove all zones :
GetBoard()->m_Zone.DeleteAll();
for( int ii = 0; ii < GetBoard()->GetAreaCount(); ii++ )
{
zone_container = GetBoard()->GetArea( ii );
error_level = Fill_Zone( zone_container, verbose );
if( error_level && !verbose )
break;
}
test_connexions( NULL );
Tst_Ratsnest( NULL, 0 ); // Recalculate the active ratsnest, i.e. the unconnected links */
DrawPanel->Refresh( true );
return error_level;
}
...@@ -356,8 +356,8 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) ...@@ -356,8 +356,8 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
} }
// Now we remove all unused thermal stubs. // Now we remove all unused thermal stubs.
//define REMOVE_UNUSED_THERMAL_STUBS // Can be commented to skip unused thermal stubs calculations #define REMOVE_UNUSED_THERMAL_STUBS // Can be commented to skip unused thermal stubs calculations
//#ifdef REMOVE_UNUSED_THERMAL_STUBS #ifdef REMOVE_UNUSED_THERMAL_STUBS
/* Add the main (corrected) polygon (i.e. the filled area using only one outline) /* Add the main (corrected) polygon (i.e. the filled area using only one outline)
* in GroupA in Bool_Engine to do a BOOL_A_SUB_B operation * in GroupA in Bool_Engine to do a BOOL_A_SUB_B operation
...@@ -500,7 +500,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) ...@@ -500,7 +500,7 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb )
delete booleng; delete booleng;
//#endif #endif
} }
...@@ -807,7 +807,7 @@ void AddThermalReliefPadPolygon( Bool_Engine* aBooleng, ...@@ -807,7 +807,7 @@ void AddThermalReliefPadPolygon( Bool_Engine* aBooleng,
// this seems a bug in kbool polygon (exists in 1.9 kbool version) // this seems a bug in kbool polygon (exists in 1.9 kbool version)
// angle = 450 (45.0 degrees orientation) seems work fine. // angle = 450 (45.0 degrees orientation) seems work fine.
// angle = 0 with thermal shapes without angle < 90 deg has problems in rare circumstances // angle = 0 with thermal shapes without angle < 90 deg has problems in rare circumstances
// Note: with the 2 step build ( thermal shpaes after correr areas build), 0 seems work // Note: with the 2 step build ( thermal shapes added after areas are built), 0 seems work
angle = 450; angle = 450;
int angle_pad = aPad.m_Orient; // Pad orientation int angle_pad = aPad.m_Orient; // Pad orientation
for( unsigned ihole = 0; ihole < 4; ihole++ ) for( unsigned ihole = 0; ihole < 4; ihole++ )
...@@ -1247,7 +1247,7 @@ void AddTextBoxWithClearancePolygon( Bool_Engine* aBooleng, ...@@ -1247,7 +1247,7 @@ void AddTextBoxWithClearancePolygon( Bool_Engine* aBooleng,
corners[3].y = corners[2].y; corners[3].y = corners[2].y;
corners[3].x = corners[0].x; corners[3].x = corners[0].x;
if( aBooleng->StartPolygonAdd( GROUP_B ) ) if( aBooleng->StartPolygonAdd( GROUP_B ) )
{ {
for( int ii = 0; ii < 4; ii ++ ) for( int ii = 0; ii < 4; ii ++ )
......
/////////////////////////////////////////////////////////////////////////////
// Name: zones_functions_for_undo_redo.cpp
/////////////////////////////////////////////////////////////////////////////
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2009 Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
* Copyright (C) 2007 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
*/
/* These functions are relative to undo redo function, when zones are involved.
* When a zone outline is modified (or created) this zone, or others zones on the same layer
* and with the same netcode can change or can be deleted
* This is due to the fact overlapping zones are merged
* Also, when a zone outline is modified by adding a cutout area,
* this zone can be converted to more than one area, if the outline is break to 2 or more outlines
* and therefore new zones are created
*
* Due to the complexity of potential changes, and the fact there are only few zones
* in a board, and a zone has only few segments outlines, the more easy way to
* undo redo changes is to make a copy of all zones that can be changed
* and see after zone edition or creation what zones that are really modified,
* and ones they are modified (changes, deletion or addition)
*/
#include "fctsys.h"
#include "appl_wxstruct.h"
#include "common.h"
#include "class_drawpanel.h"
#include "pcbnew.h"
#include "wxPcbStruct.h"
#include "zones.h"
#include "zones_functions_for_undo_redo.h"
/** function ZONE_CONTAINER::IsSame()
* test is 2 zones are equivalent:
* 2 zones are equivalent if they have same parameters and same outlines
* info relative to filling is not take in account
* @param aZoneToCompare = zone to compare with "this"
*/
bool ZONE_CONTAINER::IsSame( const ZONE_CONTAINER& aZoneToCompare )
{
// compare basic parameters:
if( GetLayer() != aZoneToCompare.GetLayer() )
return false;
if( m_Netname != aZoneToCompare.m_Netname )
return false;
// Compare zone specfic parameters
if( m_ZoneClearance != aZoneToCompare.m_ZoneClearance )
return false;
if( m_ZoneMinThickness != aZoneToCompare.m_ZoneMinThickness )
return false;
if( m_FillMode != aZoneToCompare.m_FillMode )
return false;
if( m_ArcToSegmentsCount != aZoneToCompare.m_ArcToSegmentsCount )
return false;
if( m_PadOption != aZoneToCompare.m_PadOption )
return false;
if( m_ThermalReliefGapValue != aZoneToCompare.m_ThermalReliefGapValue )
return false;
if( m_ThermalReliefCopperBridgeValue != aZoneToCompare.m_ThermalReliefCopperBridgeValue )
return false;
// Compare outlines
wxASSERT( m_Poly ); // m_Poly == NULL Should never happen
wxASSERT( aZoneToCompare.m_Poly );
if( m_Poly->corner != aZoneToCompare.m_Poly->corner ) // Compare vector
return false;
return true;
}
/** function SaveCopyOfZones()
* creates a copy of zones having a given netcode on a given layer,
* and fill a pick list with pickers to handle these copies
* the UndoRedo status is set to UR_CHANGED for all items in list
* Later, UpdateCopyOfZonesList will change and update these pickers after a zone edition
* @param aPickList = the pick list
* @param aPcb = the Board
* @param aNetCode = the reference netcode. if aNetCode < 0 all netcodes are used
* @param aLayer = the layer of zones. if aLayer < 0, all layers are used
* @return the count of saved copies
*/
int SaveCopyOfZones( PICKED_ITEMS_LIST& aPickList, BOARD* aPcb, int aNetCode, int aLayer )
{
int copyCount = 0;
for( unsigned ii = 0; ; ii++ )
{
ZONE_CONTAINER* zone = aPcb->GetArea( ii );
if( zone == NULL ) // End of list
break;
if( aNetCode >= 0 && aNetCode != zone->GetNet() )
continue;
if( aLayer >= 0 && aLayer != zone->GetLayer() )
continue;
ZONE_CONTAINER* zoneDup = new ZONE_CONTAINER( aPcb );
zoneDup->Copy( zone );
ITEM_PICKER picker( zone, UR_CHANGED );
picker.m_Link = zoneDup;
picker.m_PickedItemType = zone->Type();
aPickList.PushItem( picker );
copyCount++;
}
return copyCount;
}
/** function UpdateCopyOfZonesList()
* check a pick list to remove zones identical to their copies
* and set the type of operation in picker (UR_DELETED, UR_CHANGED)
* if an item is deleted, the initial values are retrievered,
* because they can have changed in edition
* @param aPickList = the main pick list
* @param aAuxiliaryList = the list of deleted or added (new created) items after calculations
* @param aPcb = the Board
*
* aAuxiliaryList is a list of pickers updated by zone algorithms:
* In this list are put zone taht were added or deleted during the zone combine process
* aPickList :is a list of zone that can be modified (changed or deleted, or not modified)
* >> if the picked zone is not changed, it is removed from list
* >> if the picked zone was deleted (i.e. not found in boad list), the picker is modified:
* - its status becomes UR_DELETED
* - the aAuxiliaryList corresponding picker is removed (if not found : set an error)
* >> if the picked zone was flagged as UR_NEW, and was deleted (i.e. not found in boad list),
* - the picker is removed
* - the zone itself if really deleted
* - the aAuxiliaryList corresponding picker is removed (if not found : set an error)
* After aPickList is cleaned, the aAuxiliaryList is read
* All pickers flagged UR_NEW are moved to aPickList
* (the corresponding zones are zone that were created by the zone combine process, mainly when adding cutaout areas)
* At the end of the update process the aAuxiliaryList must be void, because all pickers created by the combine process
* must have been removed (removed for new and deleted zones, or moved in aPickList.)
* If not an error is set.
*/
void UpdateCopyOfZonesList( PICKED_ITEMS_LIST& aPickList,
PICKED_ITEMS_LIST& aAuxiliaryList,
BOARD* aPcb )
{
for( unsigned kk = 0; kk < aPickList.GetCount(); kk++ )
{
UndoRedoOpType status = aPickList.GetPickedItemStatus( kk );
ZONE_CONTAINER* ref = (ZONE_CONTAINER*) aPickList.GetPickedItem( kk );
for( unsigned ii = 0; ; ii++ ) // analyse the main picked list
{
ZONE_CONTAINER* zone = aPcb->GetArea( ii );
if( zone == NULL )
{
/* End of list: the stored item is not found:
* it must be in aDeletedList:
* search it and restore initial values
* or
* if flagged UR_NEW: remove it definitively
*/
if( status == UR_NEW )
{
delete ref;
aPickList.RemovePicker( kk );
kk--;
}
else
{
ZONE_CONTAINER* zcopy = (ZONE_CONTAINER*) aPickList.GetPickedItemLink( kk );
aPickList.SetPickedItemStatus( UR_DELETED, kk );
if( zcopy )
ref->Copy( zcopy );
else
wxMessageBox( wxT( "UpdateCopyOfZonesList() error: link = NULL" ) );
aPickList.SetPickedItemLink( NULL, kk ); // the copy was deleted; the link does not exists now
delete zcopy;
}
// Remove this item from aAuxiliaryList, mainly for tests purpose
bool notfound = true;
for( unsigned nn = 0; nn < aAuxiliaryList.GetCount(); nn++ )
{
if( aAuxiliaryList.GetPickedItem( nn ) == ref )
{
aAuxiliaryList.RemovePicker( nn );
notfound = false;
break;
}
}
if( notfound )
wxMessageBox( wxT(
"UpdateCopyOfZonesList() error: item not found in aAuxiliaryList" ) );
break;
}
if( zone == ref ) // picked zone found
{
if( aPickList.GetPickedItemStatus( kk ) != UR_NEW )
{
ZONE_CONTAINER* zcopy = (ZONE_CONTAINER*) aPickList.GetPickedItemLink( kk );
if( zone->IsSame( *zcopy ) ) // Remove picked, because no changes
{
delete zcopy; // Delete copy
aPickList.RemovePicker( kk );
kk--;
}
}
break;
}
}
}
// Add new zones in main pick list, and remove pickers from Auxiliary List
for( unsigned ii = 0; ii < aAuxiliaryList.GetCount(); ii++ )
{
if( aAuxiliaryList.GetPickedItemStatus( ii ) == UR_NEW )
{
ITEM_PICKER picker = aAuxiliaryList.GetItemWrapper( ii );
aPickList.PushItem( picker );
aAuxiliaryList.RemovePicker( ii );
ii--;
}
}
// Should not occur:
if( aAuxiliaryList.GetCount()> 0 )
{
wxString msg;
msg.Printf( wxT(
"UpdateCopyOfZonesList() error: aAuxiliaryList not void: %d item left (status %d)" ),
aAuxiliaryList.GetCount(), aAuxiliaryList.GetPickedItemStatus( 0 ) );
wxMessageBox( msg );
while( aAuxiliaryList.GetCount()> 0 )
{
delete aAuxiliaryList.GetPickedItemLink( 0 );
aAuxiliaryList.RemovePicker( 0 );
}
}
}
/////////////////////////////////////////////////////////////////////////////
// Name: zones_functions_for_undo_redo.h
/////////////////////////////////////////////////////////////////////////////
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2009 Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
* Copyright (C) 2007 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
*/
/* These functions are relative to undo redo function, when zones are involved.
* When a zone outline is modified (or created) this zone, or others zones on the same layer
* and with the same netcode can change or can be deleted
* This is due to the fact overlapping zones are merged
* Also, when a zone outline is modified by adding a cutout area,
* this zone can be converted to more than one area, if the outline is break to 2 or more outlines
* and therefore new zones are created
*
* Due to the complexity of potential changes, and the fact there are only few zones
* in a board, and a zone has only few segments outlines, the more easy way to
* undo redo changes is to make a copy of all zones that can be changed
* and see after zone edition or creation what zones that are really modified,
* and ones they are modified (changes, deletion or addition)
*/
#ifndef ZONES_FUNCTIONS_TO_UNDO_REDO_H
#define ZONES_FUNCTIONS_TO_UNDO_REDO_H
/** function SaveCopyOfZones()
* creates a copy of zones having a given netcode on a given layer,
* and fill a pick list with pickers to handle these copies
* @param aPickList = the pick list
* @param aPcb = the Board
* @param aNetCode = the reference netcode. if aNetCode < 0 all netcodes are used
* @param aLayer = the layer of zones. if aLayer < 0, all layers are used
* @return the count of saved copies
*/
int SaveCopyOfZones(PICKED_ITEMS_LIST & aPickList, BOARD* aPcb, int aNetCode, int aLayer );
/** function UpdateCopyOfZonesList()
* check a pick list to remove zones identical to their copies
* and set the type of operation in picker (UR_DELETED, UR_CHANGED)
* @param aPickList = the main pick list
* @param aDeletedList = the list of dleted items
* @param aPcb = the Board
*/
void UpdateCopyOfZonesList( PICKED_ITEMS_LIST& aPickList, PICKED_ITEMS_LIST& aDeletedList, BOARD* aPcb );
#endif // ZONES_FUNCTIONS_TO_UNDO_REDO_H
...@@ -18,29 +18,52 @@ bool bDontShowIntersectionArcsWarning; ...@@ -18,29 +18,52 @@ bool bDontShowIntersectionArcsWarning;
bool bDontShowIntersectionWarning; bool bDontShowIntersectionWarning;
/** /** Function AddArea
* Function AddArea * Add an empty copper area to board areas list
* add empty copper area to net * @param aNewZonesList = a PICKED_ITEMS_LIST * where to store new areas pickers (useful in undo commands)
* can be NULL
* @param aNetcode = the necode of the copper area (0 = no net)
* @param aLayer = the layer of area
* @param aStartPointPosition = position of the first point of the polygon outline of this area
* @param aHatch = hacth option
* @return pointer to the new area * @return pointer to the new area
*/ */
ZONE_CONTAINER* BOARD::AddArea( int netcode, int layer, int x, int y, int hatch ) ZONE_CONTAINER* BOARD::AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode,
int aLayer, wxPoint aStartPointPosition, int aHatch )
{ {
ZONE_CONTAINER* new_area = InsertArea( netcode, m_ZoneDescriptorList.size( ZONE_CONTAINER* new_area = InsertArea( aNetcode,
) - 1, layer, x, y, hatch ); m_ZoneDescriptorList.size( ) - 1,
aLayer, aStartPointPosition.x, aStartPointPosition.y, aHatch );
if( aNewZonesList )
{
ITEM_PICKER picker( new_area, UR_NEW );
picker.m_PickedItemType = new_area->Type();
aNewZonesList->PushItem( picker );
}
return new_area; return new_area;
} }
/** /** Function RemoveArea
* remove copper area from net * remove copper area from net, and put it in a deleted list (if exists)
* @param area = area to remove * @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in undo commands)
* @return 0 * can be NULL
* @param area_to_remove = area to delete or put in deleted list
*/ */
int BOARD::RemoveArea( ZONE_CONTAINER* area_to_remove ) void BOARD::RemoveArea( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_to_remove )
{ {
Delete( area_to_remove ); if( area_to_remove == NULL )
return 0; return;
if( aDeletedList )
{
ITEM_PICKER picker( area_to_remove, UR_DELETED );
picker.m_PickedItemType = area_to_remove->Type();
aDeletedList->PushItem( picker );
Remove( area_to_remove ); // remove from zone list, but does not delete it
}
else
Delete( area_to_remove );
} }
...@@ -82,9 +105,8 @@ int BOARD::CompleteArea( ZONE_CONTAINER* area_to_complete, int style ) ...@@ -82,9 +105,8 @@ int BOARD::CompleteArea( ZONE_CONTAINER* area_to_complete, int style )
return 1; return 1;
} }
else else
{ Delete( area_to_complete );
RemoveArea( area_to_complete );
}
return 0; return 0;
} }
...@@ -206,19 +228,24 @@ int BOARD::TestAreaPolygon( ZONE_CONTAINER* CurrArea ) ...@@ -206,19 +228,24 @@ int BOARD::TestAreaPolygon( ZONE_CONTAINER* CurrArea )
* Function ClipAreaPolygon * Function ClipAreaPolygon
* Process an area that has been modified, by clipping its polygon against itself. * Process an area that has been modified, by clipping its polygon against itself.
* This may change the number and order of copper areas in the net. * This may change the number and order of copper areas in the net.
* @param aNewZonesList = a PICKED_ITEMS_LIST * where to store new areas pickers (useful in undo commands)
* can be NULL
* @param aCurrArea = the zone to process
* @param bMessageBoxInt == true, shows message when clipping occurs. * @param bMessageBoxInt == true, shows message when clipping occurs.
* @param bMessageBoxArc == true, shows message when clipping can't be done due to arcs. * @param bMessageBoxArc == true, shows message when clipping can't be done due to arcs.
* @param bRetainArcs = true to handle arcs (not really used in kicad)
* @return: * @return:
* -1 if arcs intersect other sides, so polygon can't be clipped * -1 if arcs intersect other sides, so polygon can't be clipped
* 0 if no intersecting sides * 0 if no intersecting sides
* 1 if intersecting sides * 1 if intersecting sides
* Also sets areas->utility1 flags if areas are modified * Also sets areas->utility1 flags if areas are modified
*/ */
int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea, int BOARD::ClipAreaPolygon( PICKED_ITEMS_LIST * aNewZonesList,
ZONE_CONTAINER* aCurrArea,
bool bMessageBoxArc, bool bMessageBoxInt, bool bRetainArcs ) bool bMessageBoxArc, bool bMessageBoxInt, bool bRetainArcs )
{ {
CPolyLine* curr_polygon = CurrArea->m_Poly; CPolyLine* curr_polygon = aCurrArea->m_Poly;
int test = TestAreaPolygon( CurrArea ); // this sets utility2 flag int test = TestAreaPolygon( aCurrArea ); // this sets utility2 flag
if( test == -1 && !bRetainArcs ) if( test == -1 && !bRetainArcs )
test = 1; test = 1;
...@@ -229,7 +256,7 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea, ...@@ -229,7 +256,7 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea,
{ {
wxString str; wxString str;
str.Printf( wxT( "Area %8.8X of net \"%s\" has arcs intersecting other sides.\n" ), str.Printf( wxT( "Area %8.8X of net \"%s\" has arcs intersecting other sides.\n" ),
CurrArea->m_TimeStamp, CurrArea->m_Netname.GetData() ); aCurrArea->m_TimeStamp, aCurrArea->m_Netname.GetData() );
str += wxT( "This may cause problems with other editing operations,\n" ); str += wxT( "This may cause problems with other editing operations,\n" );
str += wxT( "such as adding cutouts. It can't be fixed automatically.\n" ); str += wxT( "such as adding cutouts. It can't be fixed automatically.\n" );
str += wxT( "Manual correction is recommended." ); str += wxT( "Manual correction is recommended." );
...@@ -242,7 +269,7 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea, ...@@ -242,7 +269,7 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea,
for( unsigned ia = 0; ia < m_ZoneDescriptorList.size(); ia++ ) for( unsigned ia = 0; ia < m_ZoneDescriptorList.size(); ia++ )
m_ZoneDescriptorList[ia]->utility = 0; m_ZoneDescriptorList[ia]->utility = 0;
CurrArea->utility = 1; aCurrArea->utility = 1;
if( test == 1 ) if( test == 1 )
{ {
...@@ -252,7 +279,7 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea, ...@@ -252,7 +279,7 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea,
wxString str; wxString str;
str.Printf( wxT( str.Printf( wxT(
"Area %8.8X of net \"%s\" is self-intersecting and will be clipped.\n" ), "Area %8.8X of net \"%s\" is self-intersecting and will be clipped.\n" ),
CurrArea->m_TimeStamp, CurrArea->m_Netname.GetData() ); aCurrArea->m_TimeStamp, aCurrArea->m_Netname.GetData() );
str += wxT( "This may result in splitting the area.\n" ); str += wxT( "This may result in splitting the area.\n" );
str += wxT( "If the area is complex, this may take a few seconds." ); str += wxT( "If the area is complex, this may take a few seconds." );
wxMessageBox( str ); wxMessageBox( str );
...@@ -266,7 +293,7 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea, ...@@ -266,7 +293,7 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea,
{ {
std::vector<CPolyLine*>* pa = new std::vector<CPolyLine*>; std::vector<CPolyLine*>* pa = new std::vector<CPolyLine*>;
curr_polygon->Undraw(); curr_polygon->Undraw();
int n_poly = CurrArea->m_Poly->NormalizeAreaOutlines( pa, bRetainArcs ); int n_poly = aCurrArea->m_Poly->NormalizeAreaOutlines( pa, bRetainArcs );
if( n_poly > 1 ) // i.e if clipping has created some polygons, we must add these new copper areas if( n_poly > 1 ) // i.e if clipping has created some polygons, we must add these new copper areas
{ {
ZONE_CONTAINER* NewArea; ZONE_CONTAINER* NewArea;
...@@ -274,7 +301,8 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea, ...@@ -274,7 +301,8 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea,
{ {
// create new copper area and copy poly into it // create new copper area and copy poly into it
CPolyLine* new_p = (*pa)[ip - 1]; CPolyLine* new_p = (*pa)[ip - 1];
NewArea = AddArea( CurrArea->GetNet(), CurrArea->GetLayer(), 0, 0, 0 ); NewArea = AddArea( aNewZonesList, aCurrArea->GetNet(), aCurrArea->GetLayer(),
wxPoint(0, 0), CPolyLine::NO_HATCH );
// remove the poly that was automatically created for the new area // remove the poly that was automatically created for the new area
// and replace it with a poly from NormalizeWithKbool // and replace it with a poly from NormalizeWithKbool
...@@ -295,6 +323,8 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea, ...@@ -295,6 +323,8 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea,
* Process an area that has been modified, by clipping its polygon against * Process an area that has been modified, by clipping its polygon against
* itself and the polygons for any other areas on the same net. * itself and the polygons for any other areas on the same net.
* This may change the number and order of copper areas in the net. * This may change the number and order of copper areas in the net.
* @param aModifiedZonesList = a PICKED_ITEMS_LIST * where to store deleted or added areas (useful in undo commands
* can be NULL
* @param modified_area = area to test * @param modified_area = area to test
* @param bMessageBoxInt == true, shows message when clipping occurs. * @param bMessageBoxInt == true, shows message when clipping occurs.
* @param bMessageBoxArc == true, shows message when clipping can't be done due to arcs. * @param bMessageBoxArc == true, shows message when clipping can't be done due to arcs.
...@@ -303,12 +333,13 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea, ...@@ -303,12 +333,13 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea,
* 0 if no intersecting sides * 0 if no intersecting sides
* 1 if intersecting sides, polygon clipped * 1 if intersecting sides, polygon clipped
*/ */
int BOARD::AreaPolygonModified( ZONE_CONTAINER* modified_area, int BOARD::AreaPolygonModified( PICKED_ITEMS_LIST* aModifiedZonesList,
ZONE_CONTAINER* modified_area,
bool bMessageBoxArc, bool bMessageBoxArc,
bool bMessageBoxInt ) bool bMessageBoxInt )
{ {
// clip polygon against itself // clip polygon against itself
int test = ClipAreaPolygon( modified_area, bMessageBoxArc, bMessageBoxInt ); int test = ClipAreaPolygon( aModifiedZonesList, modified_area, bMessageBoxArc, bMessageBoxInt );
if( test == -1 ) if( test == -1 )
return test; return test;
...@@ -321,7 +352,7 @@ int BOARD::AreaPolygonModified( ZONE_CONTAINER* modified_area, ...@@ -321,7 +352,7 @@ int BOARD::AreaPolygonModified( ZONE_CONTAINER* modified_area,
else else
bCheckAllAreas = TestAreaIntersections( modified_area ); bCheckAllAreas = TestAreaIntersections( modified_area );
if( bCheckAllAreas ) if( bCheckAllAreas )
CombineAllAreasInNet( modified_area->GetNet(), bMessageBoxInt, true ); CombineAllAreasInNet( aModifiedZonesList, modified_area->GetNet(), bMessageBoxInt, true );
if( layer >= FIRST_NO_COPPER_LAYER ) // Refill non copper zones on this layer if( layer >= FIRST_NO_COPPER_LAYER ) // Refill non copper zones on this layer
{ {
...@@ -343,7 +374,7 @@ int BOARD::AreaPolygonModified( ZONE_CONTAINER* modified_area, ...@@ -343,7 +374,7 @@ int BOARD::AreaPolygonModified( ZONE_CONTAINER* modified_area,
// Remove zone because it is incorrect: // Remove zone because it is incorrect:
else else
RemoveArea( zone ); RemoveArea( aModifiedZonesList, zone );
} }
return test; return test;
...@@ -353,13 +384,15 @@ int BOARD::AreaPolygonModified( ZONE_CONTAINER* modified_area, ...@@ -353,13 +384,15 @@ int BOARD::AreaPolygonModified( ZONE_CONTAINER* modified_area,
/** /**
* Function CombineAllAreasInNet * Function CombineAllAreasInNet
* Checks all copper areas in net for intersections, combining them if found * Checks all copper areas in net for intersections, combining them if found
* @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in undo commands
* can be NULL
* @param aNetCode = net to consider * @param aNetCode = net to consider
* @param bMessageBox : if true display warning message box * @param bMessageBox : if true display warning message box
* @param bUseUtility : if true, don't check areas if both utility flags are 0 * @param bUseUtility : if true, don't check areas if both utility flags are 0
* Sets utility flag = 1 for any areas modified * Sets utility flag = 1 for any areas modified
* If an area has self-intersecting arcs, doesn't try to combine it * If an area has self-intersecting arcs, doesn't try to combine it
*/ */
int BOARD::CombineAllAreasInNet( int aNetCode, bool bMessageBox, bool bUseUtility ) int BOARD::CombineAllAreasInNet( PICKED_ITEMS_LIST* aDeletedList, int aNetCode, bool bMessageBox, bool bUseUtility )
{ {
if( m_ZoneDescriptorList.size() <= 1 ) if( m_ZoneDescriptorList.size() <= 1 )
return 0; return 0;
...@@ -397,7 +430,7 @@ int BOARD::CombineAllAreasInNet( int aNetCode, bool bMessageBox, bool bUseUtilit ...@@ -397,7 +430,7 @@ int BOARD::CombineAllAreasInNet( int aNetCode, bool bMessageBox, bool bUseUtilit
{ {
int ret = TestAreaIntersection( curr_area, area2 ); int ret = TestAreaIntersection( curr_area, area2 );
if( ret == 1 ) if( ret == 1 )
ret = CombineAreas( curr_area, area2 ); ret = CombineAreas( aDeletedList, curr_area, area2 );
if( ret == 1 ) if( ret == 1 )
{ {
mod_ia1 = true; mod_ia1 = true;
...@@ -671,13 +704,17 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_ ...@@ -671,13 +704,17 @@ int BOARD::TestAreaIntersection( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_
/** /**
* Function CombineAreas * Function CombineAreas
* If possible, combine 2 copper areas * If possible, combine 2 copper areas
* area_ref must be BEFORE area_to_combine in m_ZoneDescriptorList * @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in undo commands
* can be NULL
* @param area_ref = tje main area (zone)
* @param area_to_combine = the zone that can be merged with area_ref
* area_ref must be BEFORE area_to_combine
* area_to_combine will be deleted, if areas are combined * area_to_combine will be deleted, if areas are combined
* @return : 0 if no intersection * @return : 0 if no intersection
* 1 if intersection * 1 if intersection
* 2 if arcs intersect * 2 if arcs intersect
*/ */
int BOARD::CombineAreas( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_combine ) int BOARD::CombineAreas( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_combine )
{ {
if( area_ref == area_to_combine ) if( area_ref == area_to_combine )
{ {
...@@ -780,7 +817,7 @@ int BOARD::CombineAreas( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_combi ...@@ -780,7 +817,7 @@ int BOARD::CombineAreas( ZONE_CONTAINER* area_ref, ZONE_CONTAINER* area_to_combi
} }
if( !keep_area_to_combine ) if( !keep_area_to_combine )
RemoveArea( area_to_combine ); RemoveArea( aDeletedList, area_to_combine );
area_ref->utility = 1; area_ref->utility = 1;
area_ref->m_Poly->RestoreArcs( &arc_array1 ); area_ref->m_Poly->RestoreArcs( &arc_array1 );
......
...@@ -1489,14 +1489,11 @@ bool CPolyLine::TestPointInsideContour( int icont, int px, int py ) ...@@ -1489,14 +1489,11 @@ bool CPolyLine::TestPointInsideContour( int icont, int px, int py )
void CPolyLine::Copy( CPolyLine* src ) void CPolyLine::Copy( CPolyLine* src )
{ {
Undraw(); Undraw();
m_HatchStyle = src->m_HatchStyle;
// copy corners // copy corners, using vector copy
for( unsigned ii = 0; ii < src->corner.size(); ii++ ) corner = src->corner;
corner.push_back( src->corner[ii] ); // copy side styles, using vector copy
side_style = src->side_style;
// copy side styles
for( unsigned ii = 0; ii < src->side_style.size(); ii++ )
side_style.push_back( src->side_style[ii] );
} }
......
...@@ -102,6 +102,12 @@ public: ...@@ -102,6 +102,12 @@ public:
int y; int y;
bool end_contour; bool end_contour;
int utility; int utility;
bool operator == (const CPolyPt& cpt2 ) const
{ return (x == cpt2.x) && (y == cpt2.y) && (end_contour == cpt2.end_contour); }
bool operator != (CPolyPt& cpt2 ) const
{ return (x != cpt2.x) || (y != cpt2.y) || (end_contour != cpt2.end_contour); }
}; };
#include "polygon_test_point_inside.h" #include "polygon_test_point_inside.h"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment