← Back to team overview

kicad-developers team mailing list archive

Re: Zone keepouts within modules

 

Hi Jon,

Oh yes I missed some of the code style policy...

I have attached an updated patch.


Regards,


Simon


El 19/03/2018 a las 21:07, Jon Evans escribió:
Hi Simon,

Thanks for the updated patch, I was able to give it a quick try and it so far I haven't found any issues (I edited a footprint to create a keepout, and then saw that it correctly caused DRC warnings)

I noticed a number of coding style policy issues with your patch though; these would have to be fixed before it is merged. (some issues with spacing around parentheses, use of tabs instead of spaces, etc)
See here for details:
https://kicad-source-mirror.readthedocs.io/en/stable/Documentation/development/coding-style-policy/

Best,
Jon

On Mon, Mar 19, 2018 at 2:11 PM, Simon Santesteban <tech@xxxxxxxxxxxx <mailto:tech@xxxxxxxxxxxx>> wrote:

    I think I have it updated correctly now. There was a conflict in
    pcbnew/menubar_footprint_editor.cpp

    See patch attached.

    Simon


    El 19/03/2018 a las 15:28, Jon Evans escribió:
    Hi Simon,

    Thanks for sharing your work! This sounds like a neat feature and
    I'd like to test it and give feedback.
    Unfortunately your patch does not apply against current master,
    and it looks like it is based on an old enough point that I
    couldn't fix the merge issues manually.
    Could you please rebase your patch against the latest master and
    re-send it?

    Please note in case you haven't been following the developer
    list, we are in feature freeze for the 5.0 release and so we
    would only be able to merge new features like this once 6.0
    development starts, so you'll likely need to rebase it once more
    before it can be merged at that point.

    Thanks,
    Jon

    On Mon, Mar 19, 2018 at 8:02 AM, Simon Santesteban
    <tech@xxxxxxxxxxxx <mailto:tech@xxxxxxxxxxxx>> wrote:

        Hi everyone,

        I am a new developer in kicad community. I have been working
        on adding zones to modules, so I would like to share this work.
        Find attached a patch to have this functionality.

        Regards,

        Simon

        _______________________________________________
        Mailing list: https://launchpad.net/~kicad-developers
        <https://launchpad.net/%7Ekicad-developers>
        Post to     : kicad-developers@xxxxxxxxxxxxxxxxxxx
        <mailto:kicad-developers@xxxxxxxxxxxxxxxxxxx>
        Unsubscribe : https://launchpad.net/~kicad-developers
        <https://launchpad.net/%7Ekicad-developers>
        More help   : https://help.launchpad.net/ListHelp
        <https://help.launchpad.net/ListHelp>




    _______________________________________________
    Mailing list: https://launchpad.net/~kicad-developers
    <https://launchpad.net/%7Ekicad-developers>
    Post to     : kicad-developers@xxxxxxxxxxxxxxxxxxx
    <mailto:kicad-developers@xxxxxxxxxxxxxxxxxxx>
    Unsubscribe : https://launchpad.net/~kicad-developers
    <https://launchpad.net/%7Ekicad-developers>
    More help   : https://help.launchpad.net/ListHelp
    <https://help.launchpad.net/ListHelp>



From e1f12769bca0489818fd53063722d6ab129f1598 Mon Sep 17 00:00:00 2001
From: embeblue <tech@xxxxxxxxxxxx>
Date: Mon, 19 Mar 2018 16:23:18 +0100
Subject: [PATCH 1/2] fix keepout area menu conflict

Signed-off-by: embeblue <tech@xxxxxxxxxxxx>
---
 pcbnew/board_commit.cpp                  |   4 +
 pcbnew/class_board.cpp                   |   6 ++
 pcbnew/class_board.h                     |  74 +++++++++++++
 pcbnew/class_module.cpp                  | 102 ++++++++++++++++++
 pcbnew/class_module.h                    |  45 ++++++++
 pcbnew/collectors.cpp                    |   2 +
 pcbnew/controle.cpp                      |   1 +
 pcbnew/drc.cpp                           |  24 ++---
 pcbnew/footprint_editor_onclick.cpp      |  91 +++++++++++++++-
 pcbnew/footprint_editor_utils.cpp        |   4 +
 pcbnew/kicad_clipboard.cpp               |   7 +-
 pcbnew/kicad_plugin.cpp                  |  21 +++-
 pcbnew/menubar_footprint_editor.cpp      |   7 +-
 pcbnew/pcb_parser.cpp                    |  23 +++-
 pcbnew/pcbnew_id.h                       |   1 +
 pcbnew/tool_footprint_editor.cpp         |   4 +
 pcbnew/tools/drawing_tool.cpp            |   8 +-
 pcbnew/tools/pcb_actions.cpp             |   1 +
 pcbnew/tools/pcbnew_control.cpp          |   5 +
 pcbnew/tools/selection_tool.cpp          |  11 ++
 pcbnew/tools/zone_create_helper.cpp      |   9 ++
 pcbnew/zone_filler.cpp                   |   5 +-
 pcbnew/zones_functions_for_undo_redo.cpp | 173 +++++++++++++++++++++++++++++++
 pcbnew/zones_functions_for_undo_redo.h   |  24 +++++
 24 files changed, 630 insertions(+), 22 deletions(-)

diff --git a/pcbnew/board_commit.cpp b/pcbnew/board_commit.cpp
index 57e0e68..fbbeeea 100644
--- a/pcbnew/board_commit.cpp
+++ b/pcbnew/board_commit.cpp
@@ -298,6 +298,10 @@ EDA_ITEM* BOARD_COMMIT::parentObject( EDA_ITEM* aItem ) const
         case PCB_MODULE_EDGE_T:
         case PCB_MODULE_TEXT_T:
             return aItem->GetParent();
+        case PCB_ZONE_AREA_T:
+			if(aItem->GetParent() && aItem->GetParent()->Type() == PCB_MODULE_T)
+				return aItem->GetParent();
+			// else do default
         default:
             return aItem;
     }
diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp
index c5486d8..3067f95 100644
--- a/pcbnew/class_board.cpp
+++ b/pcbnew/class_board.cpp
@@ -955,6 +955,12 @@ void BOARD::Remove( BOARD_ITEM* aBoardItem )
                 break;
             }
         }
+        
+		// search inside modules
+		for( MODULE* module = m_Modules; module; module = module->Next() )
+        {
+			module->Remove(aBoardItem);
+		}
         break;
 
     case PCB_MODULE_T:
diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h
index 81a048e..22389cd 100644
--- a/pcbnew/class_board.h
+++ b/pcbnew/class_board.h
@@ -47,6 +47,8 @@
 
 #include <memory>
 
+#include <class_module.h>
+
 using std::unique_ptr;
 
 class PCB_BASE_FRAME;
@@ -1013,6 +1015,78 @@ public:
         return (int) m_ZoneDescriptorList.size();
     }
 
+
+    /**
+     * Function GetAreaIncludingModules
+     * returns the Area (Zone Container) at a given index, including modules.
+     * @param index The array type index into a collection of ZONE_CONTAINER *.
+     * @return ZONE_CONTAINER* - a pointer to the Area or NULL if index out of range.
+     */
+    ZONE_CONTAINER* GetAreaIncludingModules( int index ) const
+    {
+        if( (unsigned) index < m_ZoneDescriptorList.size() )
+            return m_ZoneDescriptorList[index];
+
+		int count = (int) m_ZoneDescriptorList.size();
+		for( MODULE* module = m_Modules; module; module = module->Next() )
+        {
+			int n_mod = module->GetAreaCount();
+			
+			if(index < count + n_mod) {
+				// is inside this module
+				int idx = index - count;
+				return module->GetArea(idx);
+			}
+			count += n_mod;
+		}
+		
+        return NULL;
+    }
+
+    /**
+     * Function GetAreaIndexIncludingModules
+     * returns the Area Index  for the given Zone Container, including modules.
+     * @param  aArea :The ZONE_CONTAINER to find.
+     * @return an Area Index in m_ZoneDescriptorList or -1 if non found.
+     */
+    int GetAreaIndexIncludingModules( const ZONE_CONTAINER* aArea ) const
+    {
+        for( int ii = 0; ii < GetAreaCount(); ii++ )    // Search for aArea in list
+        {
+            if( aArea == GetArea( ii ) )                // Found !
+                return ii;
+        }
+
+		int count = GetAreaCount();
+		for( MODULE* module = m_Modules; module; module = module->Next() )
+        {
+			int n_mod = module->GetAreaCount();
+			int idx = module->GetAreaIndex(aArea);
+			
+			if(idx >= 0) {
+				return idx + count;
+			}
+			count += n_mod;
+		}
+        return -1;
+    }
+
+    /**
+     * Function GetAreaCountIncludingModules
+     * @return int - The number of Areas or ZONE_CONTAINER including modules.
+     */
+    int GetAreaCountIncludingModules() const
+    {
+        int ret = GetAreaCount();
+        
+        for( MODULE* module = m_Modules; module; module = module->Next() )
+        {
+			ret += module->GetAreaCount();
+		}
+        
+        return ret;
+    }
+	
     /* Functions used in test, merge and cut outlines */
 
     /**
diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp
index 515dcee..0509f38 100644
--- a/pcbnew/class_module.cpp
+++ b/pcbnew/class_module.cpp
@@ -78,6 +78,8 @@ MODULE::MODULE( BOARD* parent ) :
     m_Value = new TEXTE_MODULE( this, TEXTE_MODULE::TEXT_is_VALUE );
 
     m_3D_Drawings.clear();
+    
+    m_ZoneDescriptorList.clear();
 }
 
 
@@ -140,6 +142,15 @@ MODULE::MODULE( const MODULE& aModule ) :
 
     m_arflag = 0;
 
+	// Copy zones
+	m_ZoneDescriptorList.clear();
+	for( int ii = 0; ii < aModule.GetAreaCount(); ii++ )
+	{
+		ZONE_CONTAINER* zone = aModule.GetArea( ii );
+		ZONE_CONTAINER* zone_clone = new ZONE_CONTAINER(*zone);
+		Add(static_cast<BOARD_ITEM*>(zone_clone), ADD_APPEND );
+	}
+
     // Ensure auxiliary data is up to date
     CalculateBoundingBox();
 
@@ -150,6 +161,12 @@ MODULE::MODULE( const MODULE& aModule ) :
 
 MODULE::~MODULE()
 {
+	while( m_ZoneDescriptorList.size() )
+    {
+        ZONE_CONTAINER* area_to_remove = m_ZoneDescriptorList[0];
+        Delete( area_to_remove );
+    }
+    
     delete m_Reference;
     delete m_Value;
     delete m_initial_comments;
@@ -218,6 +235,15 @@ MODULE& MODULE::operator=( const MODULE& aOther )
     m_Doc         = aOther.m_Doc;
     m_KeyWord     = aOther.m_KeyWord;
 
+	// Copy zones
+	m_ZoneDescriptorList.clear();
+	for( int ii = 0; ii < aOther.GetAreaCount(); ii++ )
+	{
+		ZONE_CONTAINER* zone = aOther.GetArea( ii );
+		ZONE_CONTAINER* zone_clone = new ZONE_CONTAINER(*zone);
+		Add(static_cast<BOARD_ITEM*>(zone_clone), ADD_APPEND );
+	}
+
     // Ensure auxiliary data is up to date
     CalculateBoundingBox();
 
@@ -225,6 +251,16 @@ MODULE& MODULE::operator=( const MODULE& aOther )
 }
 
 
+void MODULE::DeleteZONEOutlines()
+{
+    // the vector does not know how to delete the ZONE Outlines, it holds
+    // pointers
+    for( unsigned i = 0; i<m_ZoneDescriptorList.size(); ++i )
+        delete m_ZoneDescriptorList[i];
+
+    m_ZoneDescriptorList.clear();
+}
+
 void MODULE::ClearAllNets()
 {
     // Force the ORPHANED dummy net info for all pads.
@@ -274,6 +310,11 @@ void MODULE::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode )
             m_Pads.PushFront( static_cast<D_PAD*>( aBoardItem ) );
         break;
 
+    // this one uses a vector 
+    case PCB_ZONE_AREA_T:
+			m_ZoneDescriptorList.push_back( (ZONE_CONTAINER*) aBoardItem );
+        break;
+        
     default:
     {
         wxString msg;
@@ -302,6 +343,11 @@ void MODULE::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode )
         static_cast<D_PAD*>( aBoardItem )->SetLocalCoord();
         break;
 
+	case PCB_ZONE_AREA_T:
+		//static_cast<ZONE_CONTAINER*>( aBoardItem )->SetLocalCoord();
+		// TODO : create setlocalcoord function
+        break;
+    
     default:
         // Huh? It should have been filtered out by the previous switch
         assert(false);
@@ -328,6 +374,18 @@ void MODULE::Remove( BOARD_ITEM* aBoardItem )
         m_Pads.Remove( static_cast<D_PAD*>( aBoardItem ) );
         break;
 
+    case PCB_ZONE_AREA_T:    // this one uses a vector 
+        // find the item in the vector, then delete then erase it.
+        for( unsigned i = 0; i<m_ZoneDescriptorList.size(); ++i )
+        {
+            if( m_ZoneDescriptorList[i] == (ZONE_CONTAINER*) aBoardItem )
+            {
+                m_ZoneDescriptorList.erase( m_ZoneDescriptorList.begin() + i );
+                break;
+            }
+        }
+        break;
+        
     default:
     {
         wxString msg;
@@ -870,6 +928,19 @@ SEARCH_RESULT MODULE::Visit( INSPECTOR inspector, void* testData, const KICAD_T
 
             break;
 
+        case PCB_ZONE_AREA_T:
+            // PCB_ZONE_AREA_T are in the m_ZoneDescriptorList std::vector
+            for( unsigned i = 0; i< m_ZoneDescriptorList.size(); ++i )
+            {
+                result = m_ZoneDescriptorList[i]->Visit( inspector, testData, p );
+
+                if( result == SEARCH_QUIT )
+                    break;
+            }
+
+            ++p;
+            break;
+
         default:
             done = true;
             break;
@@ -916,6 +987,15 @@ void MODULE::RunOnChildren( const std::function<void (BOARD_ITEM*)>& aFunction )
         for( BOARD_ITEM* drawing = m_Drawings; drawing; drawing = drawing->Next() )
             aFunction( drawing );
 
+    	// for each module, its zones
+		for( int ii = 0; ii < m_ZoneDescriptorList.size(); ii++ )
+		{
+			ZONE_CONTAINER* zone = this->GetArea( ii );
+
+		
+			aFunction( static_cast<BOARD_ITEM*>( zone ) );
+		}
+
         aFunction( static_cast<BOARD_ITEM*>( m_Reference ) );
         aFunction( static_cast<BOARD_ITEM*>( m_Value ) );
     }
@@ -1101,6 +1181,13 @@ void MODULE::Flip( const wxPoint& aCentre )
             break;
         }
     }
+    
+	for( int ii = 0; ii < m_ZoneDescriptorList.size(); ii++ )
+	{
+		ZONE_CONTAINER* zone = this->GetArea( ii );
+
+		zone->Flip( m_Pos );	
+	}
 
     CalculateBoundingBox();
 }
@@ -1143,6 +1230,14 @@ void MODULE::SetPosition( const wxPoint& newpos )
             break;
         }
     }
+    
+	for( int ii = 0; ii < m_ZoneDescriptorList.size(); ii++ )
+	{
+		ZONE_CONTAINER* zone = this->GetArea( ii );
+
+		zone->Move( delta );
+	}
+
 
     CalculateBoundingBox();
 }
@@ -1251,6 +1346,13 @@ void MODULE::SetOrientation( double newangle )
         }
     }
 
+	for( int ii = 0; ii < m_ZoneDescriptorList.size(); ii++ )
+	{
+		ZONE_CONTAINER* zone = this->GetArea( ii );
+
+		zone->Rotate( GetPosition(), angleChange );		
+	}
+    
     CalculateBoundingBox();
 }
 
diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h
index 8b82b69..d705b6d 100644
--- a/pcbnew/class_module.h
+++ b/pcbnew/class_module.h
@@ -48,6 +48,9 @@
 
 #include <functional>
 
+#include <class_zone.h>
+
+
 class LINE_READER;
 class EDA_3D_CANVAS;
 class EDA_DRAW_PANEL;
@@ -102,6 +105,8 @@ class MODULE_3D_SETTINGS
         wxString m_Filename;    ///< The 3D shape filename in 3D library
 };
 
+DECL_VEC_FOR_SWIG(ZONE_CONTAINERS, ZONE_CONTAINER*)
+
 class MODULE : public BOARD_ITEM_CONTAINER
 {
 public:
@@ -710,13 +715,53 @@ public:
      */
     bool BuildPolyCourtyard();
 
+	void DeleteZONEOutlines();
+
     virtual void SwapData( BOARD_ITEM* aImage ) override;
 
+    ZONE_CONTAINERS& Zones() { return m_ZoneDescriptorList; }
+    
+    ZONE_CONTAINER* GetArea( int index ) const
+    {
+        if( (unsigned) index < m_ZoneDescriptorList.size() )
+            return m_ZoneDescriptorList[index];
+
+        return NULL;
+    }
+
+    /**
+     * Function GetAreaIndex
+     * returns the Area Index  for the given Zone Container.
+     * @param  aArea :The ZONE_CONTAINER to find.
+     * @return an Area Index in m_ZoneDescriptorList or -1 if non found.
+     */
+    int GetAreaIndex( const ZONE_CONTAINER* aArea ) const
+    {
+        for( int ii = 0; ii < GetAreaCount(); ii++ )    // Search for aArea in list
+        {
+            if( aArea == GetArea( ii ) )                // Found !
+                return ii;
+        }
+
+        return -1;
+    }
+
+    /**
+     * Function GetAreaCount
+     * @return int - The number of Areas or ZONE_CONTAINER.
+     */
+    int GetAreaCount() const
+    {
+        return (int) m_ZoneDescriptorList.size();
+    }
+
 #if defined(DEBUG)
     virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
 #endif
 
 private:
+    ZONE_CONTAINERS         m_ZoneDescriptorList;
+
     DLIST<D_PAD> m_Pads;                ///< Linked list of pads.
     DLIST<BOARD_ITEM> m_Drawings;       ///< Linked list of graphical items.
     std::list<MODULE_3D_SETTINGS> m_3D_Drawings;  ///< Linked list of 3D models.
diff --git a/pcbnew/collectors.cpp b/pcbnew/collectors.cpp
index 2219886..141cff5 100644
--- a/pcbnew/collectors.cpp
+++ b/pcbnew/collectors.cpp
@@ -115,6 +115,7 @@ const KICAD_T GENERAL_COLLECTOR::ModulesAndTheirItems[] = {
     PCB_MODULE_EDGE_T,
     PCB_PAD_T,
     PCB_MODULE_T,
+    PCB_ZONE_AREA_T,
     EOT
 };
 
@@ -123,6 +124,7 @@ const KICAD_T GENERAL_COLLECTOR::ModuleItems[] = {
     PCB_MODULE_TEXT_T,
     PCB_MODULE_EDGE_T,
     PCB_PAD_T,
+    PCB_ZONE_AREA_T,
     EOT
 };
 
diff --git a/pcbnew/controle.cpp b/pcbnew/controle.cpp
index 8ae024a..9e5e617 100644
--- a/pcbnew/controle.cpp
+++ b/pcbnew/controle.cpp
@@ -143,6 +143,7 @@ BOARD_ITEM* PCB_BASE_FRAME::PcbGeneralLocateAndDisplay( int aHotKeyCode )
 
         case ID_PCB_ZONES_BUTT:
         case ID_PCB_KEEPOUT_AREA_BUTT:
+        case ID_MODEDIT_KEEPOUT_AREA_TOOL:
             scanList = GENERAL_COLLECTOR::Zones;
             break;
 
diff --git a/pcbnew/drc.cpp b/pcbnew/drc.cpp
index f66e39c..0aa9a4b 100644
--- a/pcbnew/drc.cpp
+++ b/pcbnew/drc.cpp
@@ -190,9 +190,9 @@ int DRC::TestZoneToZoneOutline( ZONE_CONTAINER* aZone, bool aCreateMarkers )
     int nerrors = 0;
 
     // iterate through all areas
-    for( int ia = 0; ia < board->GetAreaCount(); ia++ )
+    for( int ia = 0; ia < board->GetAreaCountIncludingModules(); ia++ )
     {
-        ZONE_CONTAINER* zoneRef = board->GetArea( ia );
+		ZONE_CONTAINER* zoneRef = board->GetAreaIncludingModules( ia );
         SHAPE_POLY_SET refSmoothedPoly;
 
         zoneRef->BuildSmoothedPoly( refSmoothedPoly );
@@ -204,9 +204,9 @@ int DRC::TestZoneToZoneOutline( ZONE_CONTAINER* aZone, bool aCreateMarkers )
         if( aZone && ( aZone != zoneRef) )
             continue;
 
-        for( int ia2 = 0; ia2 < board->GetAreaCount(); ia2++ )
+        for( int ia2 = 0; ia2 < board->GetAreaCountIncludingModules(); ia2++ )
         {
-            ZONE_CONTAINER* zoneToTest = board->GetArea( ia2 );
+            ZONE_CONTAINER* zoneToTest = board->GetAreaIncludingModules( ia2 );
             SHAPE_POLY_SET testSmoothedPoly;
 
             zoneToTest->BuildSmoothedPoly( testSmoothedPoly );
@@ -762,9 +762,9 @@ void DRC::testZones()
     // In recent Pcbnew versions, the netcode is always >= 0, but an internal net name
     // is stored, and initialized from the file or the zone properties editor.
     // if it differs from the net name from net code, there is a DRC issue
-    for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
+    for( int ii = 0; ii < m_pcb->GetAreaCountIncludingModules(); ii++ )
     {
-        ZONE_CONTAINER* test_area = m_pcb->GetArea( ii );
+		ZONE_CONTAINER* test_area = m_pcb->GetAreaIncludingModules( ii );
 
         if( !test_area->IsOnCopperLayer() )
             continue;
@@ -792,10 +792,10 @@ void DRC::testZones()
 
 void DRC::testKeepoutAreas()
 {
-    // Test keepout areas for vias, tracks and pads inside keepout areas
-    for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
+    // Test keepout areas for vias, tracks and pads inside keepout areas, including modules'
+    for( int ii = 0; ii < m_pcb->GetAreaCountIncludingModules(); ii++ )
     {
-        ZONE_CONTAINER* area = m_pcb->GetArea( ii );
+		ZONE_CONTAINER* area = m_pcb->GetAreaIncludingModules( ii );
 
         if( !area->GetIsKeepout() )
         {
@@ -970,10 +970,10 @@ void DRC::testTexts()
 
 bool DRC::doTrackKeepoutDrc( TRACK* aRefSeg )
 {
-    // Test keepout areas for vias, tracks and pads inside keepout areas
-    for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
+    // Test keepout areas for vias, tracks and pads inside keepout areas, including modules'
+    for( int ii = 0; ii < m_pcb->GetAreaCountIncludingModules(); ii++ )
     {
-        ZONE_CONTAINER* area = m_pcb->GetArea( ii );
+		ZONE_CONTAINER* area = m_pcb->GetAreaIncludingModules( ii );
 
         if( !area->GetIsKeepout() )
             continue;
diff --git a/pcbnew/footprint_editor_onclick.cpp b/pcbnew/footprint_editor_onclick.cpp
index 333d9cb..3518052 100644
--- a/pcbnew/footprint_editor_onclick.cpp
+++ b/pcbnew/footprint_editor_onclick.cpp
@@ -44,6 +44,12 @@
 #include <dialog_edit_footprint_for_fp_editor.h>
 #include <menus_helpers.h>
 
+#include <zones_functions_for_undo_redo.h>
+#include <board_commit.h>
+#include <zone_filler.h>
+
+static PICKED_ITEMS_LIST s_PickedList;              // a picked list to save zones for undo/redo command
+static PICKED_ITEMS_LIST s_AuxiliaryList;           // a picked list to store zones that are deleted or added when combined
 
 void FOOTPRINT_EDIT_FRAME::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
 {
@@ -522,7 +528,6 @@ void FOOTPRINT_EDIT_FRAME::OnLeftDClick( wxDC* DC, const wxPoint& MousePos )
     }
 }
 
-
 void FOOTPRINT_EDIT_FRAME::OnEditItemRequest( wxDC* aDC, BOARD_ITEM* aItem )
 {
     switch( aItem->Type() )
@@ -553,6 +558,90 @@ void FOOTPRINT_EDIT_FRAME::OnEditItemRequest( wxDC* aDC, BOARD_ITEM* aItem )
         m_canvas->Refresh();
         break;
 
+	case PCB_ZONE_AREA_T:
+		{
+			ZONE_EDIT_T     edited;
+			ZONE_SETTINGS   zoneInfo = GetZoneSettings();
+
+			BOARD_COMMIT commit( this );
+			m_canvas->SetIgnoreMouseEvents( true );
+
+			ZONE_CONTAINER* aZone = static_cast<ZONE_CONTAINER*> ( aItem );
+			wxDC* DC = aDC;
+			
+			MODULE* parentModule = static_cast<MODULE*> ( aZone->GetParent() );
+			
+			if( !parentModule ) {
+				return;
+			}
+			
+			// 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
+			s_AuxiliaryList.ClearListAndDeleteItems();
+			s_PickedList.ClearListAndDeleteItems();
+			SaveCopyOfZones( s_PickedList, parentModule, -1, UNDEFINED_LAYER );
+
+			if( aZone->GetIsKeepout() )
+			{
+				// edit a keepout area on a copper layer
+				zoneInfo << *aZone;
+				edited = InvokeKeepoutAreaEditor( this, &zoneInfo );
+			}
+			else if( IsCopperLayer( aZone->GetLayer() ) )
+			{
+				// edit a zone on a copper layer
+
+				zoneInfo << *aZone;
+
+				edited = InvokeCopperZonesEditor( this, &zoneInfo );
+			}
+			else
+			{
+				edited = InvokeNonCopperZonesEditor( this, aZone, &zoneInfo );
+			}
+
+			m_canvas->MoveCursorToCrossHair();
+			m_canvas->SetIgnoreMouseEvents( false );
+
+			if( edited == ZONE_ABORT )
+			{
+				s_AuxiliaryList.ClearListAndDeleteItems();
+				s_PickedList.ClearListAndDeleteItems();
+				return;
+			}
+
+			if( edited == ZONE_EXPORT_VALUES )
+			{
+				UpdateCopyOfZonesList( s_PickedList, s_AuxiliaryList, parentModule );
+				commit.Stage( s_PickedList );
+				commit.Push( _( "Modify zone properties" ) );
+				s_PickedList.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items
+				return;
+			}
+
+			wxBusyCursor dummy;
+
+			// Undraw old zone outlines
+			for( int ii = 0; ii < parentModule->GetAreaCount(); ii++ )
+			{
+				ZONE_CONTAINER* edge_zone = parentModule->GetArea( ii );
+				edge_zone->Draw( m_canvas, DC, GR_XOR );
+
+				if( IsGalCanvasActive() )
+				{
+					GetGalCanvas()->GetView()->Update( edge_zone );
+				}
+			}
+
+			zoneInfo.ExportSetting( *aZone );
+
+			commit.Stage( s_PickedList );
+			commit.Push( _( "Modify zone properties" ) );
+
+			s_PickedList.ClearItemsList();  // s_ItemsListPicker is no longer owner of picked items
+		}
+        break;
+
     default:
         break;
     }
diff --git a/pcbnew/footprint_editor_utils.cpp b/pcbnew/footprint_editor_utils.cpp
index 7bc0c80..7be4d7c 100644
--- a/pcbnew/footprint_editor_utils.cpp
+++ b/pcbnew/footprint_editor_utils.cpp
@@ -959,6 +959,10 @@ void FOOTPRINT_EDIT_FRAME::OnVerticalToolbar( wxCommandEvent& aEvent )
         SetToolID( id, wxCURSOR_PENCIL, _( "Set grid origin" ) );
         break;
 
+    case ID_MODEDIT_KEEPOUT_AREA_TOOL:
+        SetToolID( id, wxCURSOR_PENCIL, _( "Add keepout" ) );
+        break;
+
     case ID_MODEDIT_PAD_TOOL:
         if( GetBoard()->m_Modules )
         {
diff --git a/pcbnew/kicad_clipboard.cpp b/pcbnew/kicad_clipboard.cpp
index 9b8c2f0..19d2da6 100644
--- a/pcbnew/kicad_clipboard.cpp
+++ b/pcbnew/kicad_clipboard.cpp
@@ -78,10 +78,13 @@ void CLIPBOARD_IO::SaveSelection( const SELECTION& aSelected )
     bool onlyModuleParts = true;
     for( const auto i : aSelected )
     {
-        // check if it not one of the module primitives
+        // check if it not one of the module primitives               
         if( ( i->Type() != PCB_MODULE_EDGE_T ) &&
                 ( i->Type() != PCB_MODULE_TEXT_T ) &&
-                ( i->Type() != PCB_PAD_T ) )
+                ( i->Type() != PCB_PAD_T ) &&
+                !( (i->Type() == PCB_ZONE_AREA_T ) && 
+					(i->GetParent()) && 
+					(i->GetParent()->Type() == PCB_MODULE_T) ) )
         {
             onlyModuleParts = false;
             continue;
diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp
index eef47d7..c83d1a9 100644
--- a/pcbnew/kicad_plugin.cpp
+++ b/pcbnew/kicad_plugin.cpp
@@ -1161,7 +1161,14 @@ void PCB_IO::format( MODULE* aModule, int aNestLevel ) const
         }
         ++bs3D;
     }
-
+    
+    // save zones
+	for( int ii = 0; ii < aModule->GetAreaCount(); ii++ )
+	{
+		ZONE_CONTAINER* zone = aModule->GetArea( ii );
+		format( zone, aNestLevel+1 );
+	};
+		
     m_out->Print( aNestLevel, ")\n" );
 }
 
@@ -1183,6 +1190,11 @@ void PCB_IO::formatLayers( LSET aLayerMask, int aNestLevel ) const
     static const LSET mask(  2, B_Mask,     F_Mask );
     static const LSET crt_yd(2, B_CrtYd,    F_CrtYd );
     static const LSET fab(   2, B_Fab,      F_Fab );
+    static const LSET inner(   30,
+		In1_Cu, In2_Cu, In3_Cu, In4_Cu, In5_Cu, In6_Cu, In7_Cu, In8_Cu, In9_Cu, In10_Cu,
+		In11_Cu, In12_Cu, In13_Cu, In14_Cu, In15_Cu, In16_Cu, In17_Cu, In18_Cu, In19_Cu, In20_Cu,
+		In21_Cu, In22_Cu, In23_Cu, In24_Cu, In25_Cu, In26_Cu, In27_Cu, In28_Cu, In29_Cu, In30_Cu
+	);
 
     LSET cu_mask = cu_all;
 
@@ -1238,6 +1250,13 @@ void PCB_IO::formatLayers( LSET aLayerMask, int aNestLevel ) const
         aLayerMask &= ~fab;
     }
 
+    if( ( aLayerMask & inner ) == inner )
+    {
+        output += " In*.Cu";
+        aLayerMask &= ~inner;
+    }
+
+
     // output any individual layers not handled in wildcard combos above
 
     if( m_board )
diff --git a/pcbnew/menubar_footprint_editor.cpp b/pcbnew/menubar_footprint_editor.cpp
index 17d8dae..1ae64a5 100644
--- a/pcbnew/menubar_footprint_editor.cpp
+++ b/pcbnew/menubar_footprint_editor.cpp
@@ -360,6 +360,12 @@ void FOOTPRINT_EDIT_FRAME::ReCreateMenuBar()
 
     placeMenu->AppendSeparator();
 
+	// Keepout Area
+    AddMenuItem( placeMenu, ID_MODEDIT_KEEPOUT_AREA_TOOL,
+                 _( "&Keepout Area" ), _( "Add keepout areas" ), KiBitmap( add_keepout_area_xpm ) );
+
+    placeMenu->AppendSeparator();
+
     // Text
     AddMenuItem( placeMenu, ID_MODEDIT_TEXT_TOOL,
                  _( "&Text" ), _( "Add graphic text" ),
@@ -428,7 +434,6 @@ void FOOTPRINT_EDIT_FRAME::ReCreateMenuBar()
                  _( "Choose and delete a footprint from the active library" ),
                  KiBitmap( delete_xpm ) );
 
-
     //----- Preferences menu -----------------
     wxMenu* prefs_menu = new wxMenu;
 
diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp
index 1de9777..1aade08 100644
--- a/pcbnew/pcb_parser.cpp
+++ b/pcbnew/pcb_parser.cpp
@@ -79,6 +79,11 @@ void PCB_PARSER::init()
     m_layerMasks[ "*.SilkS" ]   = LSET( 2, B_SilkS, F_SilkS );
     m_layerMasks[ "*.Fab" ]     = LSET( 2, B_Fab,   F_Fab );
     m_layerMasks[ "*.CrtYd" ]   = LSET( 2, B_CrtYd, F_CrtYd );
+    m_layerMasks[ "In*.Cu" ]   = LSET( 30,
+		In1_Cu, In2_Cu, In3_Cu, In4_Cu, In5_Cu, In6_Cu, In7_Cu, In8_Cu, In9_Cu, In10_Cu,
+		In11_Cu, In12_Cu, In13_Cu, In14_Cu, In15_Cu, In16_Cu, In17_Cu, In18_Cu, In19_Cu, In20_Cu,
+		In21_Cu, In22_Cu, In23_Cu, In24_Cu, In25_Cu, In26_Cu, In27_Cu, In28_Cu, In29_Cu, In30_Cu
+	);
 
     // This is for the first pretty & *.kicad_pcb formats, which had
     // Inner1_Cu - Inner14_Cu with the numbering sequence
@@ -2009,6 +2014,10 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments )
             module->Add3DModel( parse3DModel() );
             break;
 
+        case T_zone:
+			module->Add( parseZONE_CONTAINER(), ADD_APPEND );
+            break;
+
         default:
             Expecting( "locked, placed, tedit, tstamp, at, descr, tags, path, "
                        "autoplace_cost90, autoplace_cost180, solder_mask_margin, "
@@ -2834,7 +2843,19 @@ ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER()
     // bigger scope since each filled_polygon is concatenated in here
     SHAPE_POLY_SET pts;
 
-    std::unique_ptr< ZONE_CONTAINER > zone( new ZONE_CONTAINER( m_board ) );
+	std::unique_ptr< ZONE_CONTAINER > zone;
+	if(m_board != nullptr)
+	{
+		zone = std::unique_ptr< ZONE_CONTAINER > ( new ZONE_CONTAINER( m_board ) );
+	}else {
+		std::unique_ptr<BOARD> aBoard( new BOARD( ) );
+		//zone = std::unique_ptr< ZONE_CONTAINER > ( new ZONE_CONTAINER( nullptr ) );
+		//aBoard.get()->GetZoneSettings().ExportSetting( *(zone.get()) );
+		//aBoard->GetZoneSettings().ExportSetting( *zone );
+		
+		zone = std::unique_ptr< ZONE_CONTAINER > ( new ZONE_CONTAINER( aBoard.get() ) );
+		zone->SetParent( nullptr );
+	}
 
     zone->SetPriority( 0 );
 
diff --git a/pcbnew/pcbnew_id.h b/pcbnew/pcbnew_id.h
index 86fc676..3db49d8 100644
--- a/pcbnew/pcbnew_id.h
+++ b/pcbnew/pcbnew_id.h
@@ -339,6 +339,7 @@ enum pcbnew_ids
 
     // Module editor right vertical tool bar commands.
     ID_MODEDIT_PAD_TOOL,
+    ID_MODEDIT_KEEPOUT_AREA_TOOL,
     ID_MODEDIT_LINE_TOOL,
     ID_MODEDIT_CIRCLE_TOOL,
     ID_MODEDIT_ARC_TOOL,
diff --git a/pcbnew/tool_footprint_editor.cpp b/pcbnew/tool_footprint_editor.cpp
index c8498be..5b0b30a 100644
--- a/pcbnew/tool_footprint_editor.cpp
+++ b/pcbnew/tool_footprint_editor.cpp
@@ -164,6 +164,10 @@ void FOOTPRINT_EDIT_FRAME::ReCreateVToolbar()
     m_drawToolBar->AddTool( ID_MODEDIT_PAD_TOOL, wxEmptyString, KiScaledBitmap( pad_xpm, this ),
                             _( "Add pad" ), wxITEM_CHECK );
 
+    m_drawToolBar->AddTool( ID_MODEDIT_KEEPOUT_AREA_TOOL, wxEmptyString,
+                            KiScaledBitmap( add_keepout_area_xpm, this ),
+                            _( "Add keepout areas" ), wxITEM_CHECK );
+
     KiScaledSeparator( m_drawToolBar, this );
     m_drawToolBar->AddTool( ID_MODEDIT_LINE_TOOL, wxEmptyString, KiScaledBitmap( add_graphical_segments_xpm, this ),
                             _( "Add graphic line" ), wxITEM_CHECK );
diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp
index f085ce9..55fadc8 100644
--- a/pcbnew/tools/drawing_tool.cpp
+++ b/pcbnew/tools/drawing_tool.cpp
@@ -644,7 +644,13 @@ int DRAWING_TOOL::DrawZoneKeepout( const TOOL_EVENT& aEvent )
 {
     SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::KEEPOUT );
 
-    m_frame->SetToolID( ID_PCB_KEEPOUT_AREA_BUTT, wxCURSOR_PENCIL, _( "Add keepout" ) );
+	if( m_editModules )
+	{
+		m_frame->SetToolID( ID_MODEDIT_KEEPOUT_AREA_TOOL, wxCURSOR_PENCIL, _( "Add keepout" ) );
+	} else
+	{
+		m_frame->SetToolID( ID_PCB_KEEPOUT_AREA_BUTT, wxCURSOR_PENCIL, _( "Add keepout" ) );
+	}
 
     return drawZone( true, ZONE_MODE::ADD );
 }
diff --git a/pcbnew/tools/pcb_actions.cpp b/pcbnew/tools/pcb_actions.cpp
index 2569bc3..6ac54a4 100644
--- a/pcbnew/tools/pcb_actions.cpp
+++ b/pcbnew/tools/pcb_actions.cpp
@@ -61,6 +61,7 @@ OPT<TOOL_EVENT> PCB_ACTIONS::TranslateLegacyId( int aId )
     case ID_PCB_DRAW_VIA_BUTT:
         return PCB_ACTIONS::drawVia.MakeEvent();
 
+    case ID_MODEDIT_KEEPOUT_AREA_TOOL:
     case ID_PCB_KEEPOUT_AREA_BUTT:
         return PCB_ACTIONS::drawZoneKeepout.MakeEvent();
 
diff --git a/pcbnew/tools/pcbnew_control.cpp b/pcbnew/tools/pcbnew_control.cpp
index ea7a892..320094d 100644
--- a/pcbnew/tools/pcbnew_control.cpp
+++ b/pcbnew/tools/pcbnew_control.cpp
@@ -889,6 +889,11 @@ int PCBNEW_CONTROL::PasteItemsFromClipboard( const TOOL_EVENT& aEvent )
                     item->SetParent ( board()->m_Modules.GetFirst() );
                     items.push_back( item );
                 }
+                for( auto zone : mod->Zones() )
+				{
+					zone->SetParent ( board()->m_Modules.GetFirst() );
+					items.push_back( zone );
+				}
             }
             else
             {
diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp
index fe66646..83575f3 100644
--- a/pcbnew/tools/selection_tool.cpp
+++ b/pcbnew/tools/selection_tool.cpp
@@ -1535,6 +1535,17 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const
         {
             auto* zone = static_cast<const ZONE_CONTAINER*>( aItem );
 
+			//check if zone has a parent of type module
+			if( zone && zone->GetParent() && (zone->GetParent()->Type() == PCB_MODULE_T) )
+			{
+				// only if not editing module
+				if(m_frame->IsType(FRAME_PCB_MODULE_EDITOR) == false)
+				{
+					return false;
+				}	
+				
+			}
+			
             if( zone && zone->GetIsKeepout() )
             {
                 auto zoneLayers = zone->GetLayerSet().Seq();
diff --git a/pcbnew/tools/zone_create_helper.cpp b/pcbnew/tools/zone_create_helper.cpp
index 933a56a..b1e3f02 100644
--- a/pcbnew/tools/zone_create_helper.cpp
+++ b/pcbnew/tools/zone_create_helper.cpp
@@ -92,6 +92,15 @@ std::unique_ptr<ZONE_CONTAINER> ZONE_CREATE_HELPER::createNewZone( bool aKeepout
 
     // Apply the selected settings
     zoneInfo.ExportSetting( *newZone );
+    
+    if(frame.IsType(FRAME_PCB_MODULE_EDITOR)) {
+		for( auto module : board.Modules() )
+		{
+			newZone->SetParent(module);
+			break;
+		}
+		
+	}
 
     return newZone;
 }
diff --git a/pcbnew/zone_filler.cpp b/pcbnew/zone_filler.cpp
index 32a98fd..a66f03e 100644
--- a/pcbnew/zone_filler.cpp
+++ b/pcbnew/zone_filler.cpp
@@ -551,10 +551,9 @@ void ZONE_FILLER::buildZoneFeatureHoleList( const ZONE_CONTAINER* aZone,
         }
     }
 
-    // Add zones outlines having an higher priority and keepout
-    for( int ii = 0; ii < m_board->GetAreaCount(); ii++ )
+    for( int ii = 0; ii < m_board->GetAreaCountIncludingModules(); ii++ )
     {
-        ZONE_CONTAINER* zone = m_board->GetArea( ii );
+        ZONE_CONTAINER* zone = m_board->GetAreaIncludingModules( ii );
 
         // If the zones share no common layers
         if( !aZone->CommonLayerExists( zone->GetLayerSet() ) )
diff --git a/pcbnew/zones_functions_for_undo_redo.cpp b/pcbnew/zones_functions_for_undo_redo.cpp
index 97b02cb..9322f96 100644
--- a/pcbnew/zones_functions_for_undo_redo.cpp
+++ b/pcbnew/zones_functions_for_undo_redo.cpp
@@ -162,6 +162,33 @@ int SaveCopyOfZones( PICKED_ITEMS_LIST& aPickList, BOARD* aPcb, int aNetCode, LA
     return copyCount;
 }
 
+/**
+ * Function SaveCopyOfZones
+ * creates a copy of zones in a module 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 aModule = the Module
+ * @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, MODULE* aModule, int aNetCode, LAYER_NUM aLayer )
+{
+    int copyCount = 0;
+
+	MODULE* moduleDup = new MODULE( *aModule );
+	moduleDup->SetParent ( aModule->GetParent () );
+	ITEM_PICKER picker( aModule, UR_CHANGED );
+	picker.SetLink( moduleDup );
+	aPickList.PushItem( picker );
+	copyCount++;	
+
+    return copyCount;
+}
+
+
 
 /**
  * Function UpdateCopyOfZonesList
@@ -307,3 +334,149 @@ void UpdateCopyOfZonesList( PICKED_ITEMS_LIST& aPickList,
     wxASSERT_MSG( aAuxiliaryList.GetCount() == 0,
                   wxT( "UpdateCopyOfZonesList() error: aAuxiliaryList not empty." ) );
 }
+
+/**
+ * Function UpdateCopyOfZonesList
+ * check a pick list to remove zones identical to their copies in a module
+ * 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 aModule = the Module
+ *
+ * aAuxiliaryList is a list of pickers updated by zone algorithms:
+ *  This list contains zones which were added or deleted during the zones combine process
+ * aPickList :is a list of zones that can be modified (changed or deleted, or not modified)
+ *  Typically, this is the list of existing zones on the layer of the edited zone,
+ *  before any change.
+ *  >> if the picked zone is not changed, it is removed from list
+ *  >> if the picked zone was deleted (i.e. not found in board 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 after deleted ,
+ *  perhaps combined with an other zone  (i.e. not found in board 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 normalize and combine process,
+ * mainly when adding cutout areas, or creating self intersecting contours)
+ *  All pickers flagged UR_DELETED are removed, and the coresponding zones actually deleted
+ * (the corresponding zones are new zone that were created by the zone normalize process,
+ * when creating self intersecting contours, and after combined with an existing zone.
+ * 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,
+                            MODULE*             aModule )
+{
+    for( unsigned kk = 0; kk < aPickList.GetCount(); kk++ )
+    {
+        UNDO_REDO_T  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 = aModule->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;
+                    ref = NULL;
+                    aPickList.RemovePicker( kk );
+                    kk--;
+                }
+                else
+                {
+                    ZONE_CONTAINER* zcopy = (ZONE_CONTAINER*) aPickList.GetPickedItemLink( kk );
+                    aPickList.SetPickedItemStatus( UR_DELETED, kk );
+
+                    wxASSERT_MSG( zcopy != NULL,
+                                  wxT( "UpdateCopyOfZonesList() error: link = NULL" ) );
+
+                    *ref = *zcopy;
+
+                    // the copy was deleted; the link does not exists now.
+                    aPickList.SetPickedItemLink( NULL, kk );
+                    delete zcopy;
+                }
+
+                // Remove this item from aAuxiliaryList, mainly for tests purpose
+                bool notfound = true;
+
+                for( unsigned nn = 0; nn < aAuxiliaryList.GetCount(); nn++ )
+                {
+                    if( ref != NULL && aAuxiliaryList.GetPickedItem( nn ) == ref )
+                    {
+                        aAuxiliaryList.RemovePicker( nn );
+                        notfound = false;
+                        break;
+                    }
+                }
+
+                if( notfound )  // happens when the new zone overlaps an existing zone
+                                // and these zones are combined
+                {
+                    DBG( printf(
+                        "UpdateCopyOfZonesList(): item not found in aAuxiliaryList,"
+                        "combined with an other zone\n" ) );
+                }
+                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(); )
+    {
+        if( aAuxiliaryList.GetPickedItemStatus( ii ) == UR_NEW )
+        {
+            ITEM_PICKER picker = aAuxiliaryList.GetItemWrapper( ii );
+            aPickList.PushItem( picker );
+            aAuxiliaryList.RemovePicker( ii );
+        }
+        else if( aAuxiliaryList.GetPickedItemStatus( ii ) == UR_DELETED )
+        {
+            delete aAuxiliaryList.GetPickedItemLink( ii );
+            aAuxiliaryList.RemovePicker( ii );
+        }
+        else
+            ii++;
+    }
+
+    // Should not occur:
+    wxASSERT_MSG( aAuxiliaryList.GetCount() == 0,
+                  wxT( "UpdateCopyOfZonesList() error: aAuxiliaryList not empty." ) );
+}
+
diff --git a/pcbnew/zones_functions_for_undo_redo.h b/pcbnew/zones_functions_for_undo_redo.h
index a5260a3..c420dde 100644
--- a/pcbnew/zones_functions_for_undo_redo.h
+++ b/pcbnew/zones_functions_for_undo_redo.h
@@ -58,6 +58,17 @@
  */
 int SaveCopyOfZones(PICKED_ITEMS_LIST & aPickList, BOARD* aPcb, int aNetCode, LAYER_NUM aLayer );
 
+/**
+ * Function SaveCopyOfZones
+ * creates a copy of zones in a module 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 aModule = the Module
+ * @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, MODULE* aModule, int aNetCode, LAYER_NUM aLayer );
 
 /**
  * Function UpdateCopyOfZonesList
@@ -69,4 +80,17 @@ int SaveCopyOfZones(PICKED_ITEMS_LIST & aPickList, BOARD* aPcb, int aNetCode, LA
  */
 void UpdateCopyOfZonesList( PICKED_ITEMS_LIST& aPickList, PICKED_ITEMS_LIST& aAuxiliaryList, BOARD* aPcb );
 
+
+/**
+ * Function UpdateCopyOfZonesList
+ * check a pick list to remove zones identical to their copies in a module
+ * and set the type of operation in picker (UR_DELETED, UR_CHANGED)
+ * @param aPickList = the main pick list
+ * @param aAuxiliaryList = the list of deleted or added (new created) items after calculations
+ * @param aModule = the Module
+ */
+void UpdateCopyOfZonesList( PICKED_ITEMS_LIST& aPickList,
+                            PICKED_ITEMS_LIST& aAuxiliaryList,
+                            MODULE*             aModule );
+
 #endif      // ZONES_FUNCTIONS_TO_UNDO_REDO_H
-- 
2.7.4


From a5c7041292a9b8370b032f3aea336afdde43a567 Mon Sep 17 00:00:00 2001
From: embeblue <tech@xxxxxxxxxxxx>
Date: Tue, 20 Mar 2018 00:55:29 +0100
Subject: [PATCH 2/2] Zones in modules

---
 pcbnew/board_commit.cpp                  |   6 +-
 pcbnew/class_board.cpp                   |   8 +-
 pcbnew/class_board.h                     |  50 +++++-----
 pcbnew/class_module.cpp                  |  88 ++++++++---------
 pcbnew/class_module.h                    |   5 +-
 pcbnew/drc.cpp                           |   8 +-
 pcbnew/footprint_editor_onclick.cpp      | 164 +++++++++++++++----------------
 pcbnew/kicad_clipboard.cpp               |   6 +-
 pcbnew/kicad_plugin.cpp                  |  22 ++---
 pcbnew/menubar_footprint_editor.cpp      |   5 +-
 pcbnew/pcb_parser.cpp                    |  39 ++++----
 pcbnew/tools/drawing_tool.cpp            |  14 +--
 pcbnew/tools/pcbnew_control.cpp          |  10 +-
 pcbnew/tools/selection_tool.cpp          |  22 ++---
 pcbnew/tools/zone_create_helper.cpp      |  15 ++-
 pcbnew/zones_functions_for_undo_redo.cpp |  12 +--
 16 files changed, 235 insertions(+), 239 deletions(-)

diff --git a/pcbnew/board_commit.cpp b/pcbnew/board_commit.cpp
index fbbeeea..1513015 100644
--- a/pcbnew/board_commit.cpp
+++ b/pcbnew/board_commit.cpp
@@ -299,9 +299,9 @@ EDA_ITEM* BOARD_COMMIT::parentObject( EDA_ITEM* aItem ) const
         case PCB_MODULE_TEXT_T:
             return aItem->GetParent();
         case PCB_ZONE_AREA_T:
-			if(aItem->GetParent() && aItem->GetParent()->Type() == PCB_MODULE_T)
-				return aItem->GetParent();
-			// else do default
+            if( aItem->GetParent() && aItem->GetParent()->Type() == PCB_MODULE_T )
+                return aItem->GetParent();
+            // else do default
         default:
             return aItem;
     }
diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp
index 3067f95..5ae484e 100644
--- a/pcbnew/class_board.cpp
+++ b/pcbnew/class_board.cpp
@@ -956,11 +956,11 @@ void BOARD::Remove( BOARD_ITEM* aBoardItem )
             }
         }
         
-		// search inside modules
-		for( MODULE* module = m_Modules; module; module = module->Next() )
+        // search inside modules
+        for( MODULE* module = m_Modules; module; module = module->Next() )
         {
-			module->Remove(aBoardItem);
-		}
+            module->Remove( aBoardItem );
+        }
         break;
 
     case PCB_MODULE_T:
diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h
index 22389cd..e0c56bf 100644
--- a/pcbnew/class_board.h
+++ b/pcbnew/class_board.h
@@ -1027,19 +1027,19 @@ public:
         if( (unsigned) index < m_ZoneDescriptorList.size() )
             return m_ZoneDescriptorList[index];
 
-		int count = (int) m_ZoneDescriptorList.size();
-		for( MODULE* module = m_Modules; module; module = module->Next() )
+        int count = (int) m_ZoneDescriptorList.size();
+        for( MODULE* module = m_Modules; module; module = module->Next() )
         {
-			int n_mod = module->GetAreaCount();
-			
-			if(index < count + n_mod) {
-				// is inside this module
-				int idx = index - count;
-				return module->GetArea(idx);
-			}
-			count += n_mod;
-		}
-		
+            int n_mod = module->GetAreaCount();
+            
+            if( index < count + n_mod ) {
+                // is inside this module
+                int idx = index - count;
+                return module->GetArea( idx );
+            }
+            count += n_mod;
+        }
+        
         return NULL;
     }
 
@@ -1057,17 +1057,17 @@ public:
                 return ii;
         }
 
-		int count = GetAreaCount();
-		for( MODULE* module = m_Modules; module; module = module->Next() )
+        int count = GetAreaCount();
+        for( MODULE* module = m_Modules; module; module = module->Next() )
         {
-			int n_mod = module->GetAreaCount();
-			int idx = module->GetAreaIndex(aArea);
-			
-			if(idx >= 0) {
-				return idx + count;
-			}
-			count += n_mod;
-		}
+            int n_mod = module->GetAreaCount();
+            int idx = module->GetAreaIndex( aArea );
+            
+            if( idx >= 0 ) {
+                return idx + count;
+            }
+            count += n_mod;
+        }
         return -1;
     }
 
@@ -1081,12 +1081,12 @@ public:
         
         for( MODULE* module = m_Modules; module; module = module->Next() )
         {
-			ret += module->GetAreaCount();
-		}
+            ret += module->GetAreaCount();
+        }
         
         return ret;
     }
-	
+    
     /* Functions used in test, merge and cut outlines */
 
     /**
diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp
index 0509f38..54c59b3 100644
--- a/pcbnew/class_module.cpp
+++ b/pcbnew/class_module.cpp
@@ -78,7 +78,7 @@ MODULE::MODULE( BOARD* parent ) :
     m_Value = new TEXTE_MODULE( this, TEXTE_MODULE::TEXT_is_VALUE );
 
     m_3D_Drawings.clear();
-    
+
     m_ZoneDescriptorList.clear();
 }
 
@@ -142,14 +142,14 @@ MODULE::MODULE( const MODULE& aModule ) :
 
     m_arflag = 0;
 
-	// Copy zones
-	m_ZoneDescriptorList.clear();
-	for( int ii = 0; ii < aModule.GetAreaCount(); ii++ )
-	{
-		ZONE_CONTAINER* zone = aModule.GetArea( ii );
-		ZONE_CONTAINER* zone_clone = new ZONE_CONTAINER(*zone);
-		Add(static_cast<BOARD_ITEM*>(zone_clone), ADD_APPEND );
-	}
+    // Copy zones
+    m_ZoneDescriptorList.clear();
+    for( int ii = 0; ii < aModule.GetAreaCount(); ii++ )
+    {
+        ZONE_CONTAINER* zone = aModule.GetArea( ii );
+        ZONE_CONTAINER* zone_clone = new ZONE_CONTAINER( *zone );
+        Add( static_cast<BOARD_ITEM*>( zone_clone ), ADD_APPEND );
+    }
 
     // Ensure auxiliary data is up to date
     CalculateBoundingBox();
@@ -161,7 +161,7 @@ MODULE::MODULE( const MODULE& aModule ) :
 
 MODULE::~MODULE()
 {
-	while( m_ZoneDescriptorList.size() )
+    while( m_ZoneDescriptorList.size() )
     {
         ZONE_CONTAINER* area_to_remove = m_ZoneDescriptorList[0];
         Delete( area_to_remove );
@@ -235,14 +235,14 @@ MODULE& MODULE::operator=( const MODULE& aOther )
     m_Doc         = aOther.m_Doc;
     m_KeyWord     = aOther.m_KeyWord;
 
-	// Copy zones
-	m_ZoneDescriptorList.clear();
-	for( int ii = 0; ii < aOther.GetAreaCount(); ii++ )
-	{
-		ZONE_CONTAINER* zone = aOther.GetArea( ii );
-		ZONE_CONTAINER* zone_clone = new ZONE_CONTAINER(*zone);
-		Add(static_cast<BOARD_ITEM*>(zone_clone), ADD_APPEND );
-	}
+    // Copy zones
+    m_ZoneDescriptorList.clear();
+    for( int ii = 0; ii < aOther.GetAreaCount(); ii++ )
+    {
+        ZONE_CONTAINER* zone = aOther.GetArea( ii );
+        ZONE_CONTAINER* zone_clone = new ZONE_CONTAINER(*zone);
+        Add(static_cast<BOARD_ITEM*>(zone_clone), ADD_APPEND );
+    }
 
     // Ensure auxiliary data is up to date
     CalculateBoundingBox();
@@ -312,7 +312,7 @@ void MODULE::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode )
 
     // this one uses a vector 
     case PCB_ZONE_AREA_T:
-			m_ZoneDescriptorList.push_back( (ZONE_CONTAINER*) aBoardItem );
+            m_ZoneDescriptorList.push_back( (ZONE_CONTAINER*) aBoardItem );
         break;
         
     default:
@@ -343,9 +343,9 @@ void MODULE::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode )
         static_cast<D_PAD*>( aBoardItem )->SetLocalCoord();
         break;
 
-	case PCB_ZONE_AREA_T:
-		//static_cast<ZONE_CONTAINER*>( aBoardItem )->SetLocalCoord();
-		// TODO : create setlocalcoord function
+    case PCB_ZONE_AREA_T:
+        //static_cast<ZONE_CONTAINER*>( aBoardItem )->SetLocalCoord();
+        // TODO : create setlocalcoord function
         break;
     
     default:
@@ -987,14 +987,14 @@ void MODULE::RunOnChildren( const std::function<void (BOARD_ITEM*)>& aFunction )
         for( BOARD_ITEM* drawing = m_Drawings; drawing; drawing = drawing->Next() )
             aFunction( drawing );
 
-    	// for each module, its zones
-		for( int ii = 0; ii < m_ZoneDescriptorList.size(); ii++ )
-		{
-			ZONE_CONTAINER* zone = this->GetArea( ii );
+        // for each module, its zones
+        for( int ii = 0; ii < m_ZoneDescriptorList.size(); ii++ )
+        {
+            ZONE_CONTAINER* zone = this->GetArea( ii );
 
-		
-			aFunction( static_cast<BOARD_ITEM*>( zone ) );
-		}
+        
+            aFunction( static_cast<BOARD_ITEM*>( zone ) );
+        }
 
         aFunction( static_cast<BOARD_ITEM*>( m_Reference ) );
         aFunction( static_cast<BOARD_ITEM*>( m_Value ) );
@@ -1182,12 +1182,12 @@ void MODULE::Flip( const wxPoint& aCentre )
         }
     }
     
-	for( int ii = 0; ii < m_ZoneDescriptorList.size(); ii++ )
-	{
-		ZONE_CONTAINER* zone = this->GetArea( ii );
+    for( int ii = 0; ii < m_ZoneDescriptorList.size(); ii++ )
+    {
+        ZONE_CONTAINER* zone = this->GetArea( ii );
 
-		zone->Flip( m_Pos );	
-	}
+        zone->Flip( m_Pos );    
+    }
 
     CalculateBoundingBox();
 }
@@ -1231,12 +1231,12 @@ void MODULE::SetPosition( const wxPoint& newpos )
         }
     }
     
-	for( int ii = 0; ii < m_ZoneDescriptorList.size(); ii++ )
-	{
-		ZONE_CONTAINER* zone = this->GetArea( ii );
+    for( int ii = 0; ii < m_ZoneDescriptorList.size(); ii++ )
+    {
+        ZONE_CONTAINER* zone = this->GetArea( ii );
 
-		zone->Move( delta );
-	}
+        zone->Move( delta );
+    }
 
 
     CalculateBoundingBox();
@@ -1346,12 +1346,12 @@ void MODULE::SetOrientation( double newangle )
         }
     }
 
-	for( int ii = 0; ii < m_ZoneDescriptorList.size(); ii++ )
-	{
-		ZONE_CONTAINER* zone = this->GetArea( ii );
+    for( int ii = 0; ii < m_ZoneDescriptorList.size(); ii++ )
+    {
+        ZONE_CONTAINER* zone = this->GetArea( ii );
 
-		zone->Rotate( GetPosition(), angleChange );		
-	}
+        zone->Rotate( GetPosition(), angleChange );        
+    }
     
     CalculateBoundingBox();
 }
diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h
index d705b6d..64dab20 100644
--- a/pcbnew/class_module.h
+++ b/pcbnew/class_module.h
@@ -50,7 +50,6 @@
 
 #include <class_zone.h>
 
-
 class LINE_READER;
 class EDA_3D_CANVAS;
 class EDA_DRAW_PANEL;
@@ -105,7 +104,7 @@ class MODULE_3D_SETTINGS
         wxString m_Filename;    ///< The 3D shape filename in 3D library
 };
 
-DECL_VEC_FOR_SWIG(ZONE_CONTAINERS, ZONE_CONTAINER*)
+DECL_VEC_FOR_SWIG( ZONE_CONTAINERS, ZONE_CONTAINER* )
 
 class MODULE : public BOARD_ITEM_CONTAINER
 {
@@ -715,7 +714,7 @@ public:
      */
     bool BuildPolyCourtyard();
 
-	void DeleteZONEOutlines();
+    void DeleteZONEOutlines();
 
     virtual void SwapData( BOARD_ITEM* aImage ) override;
 
diff --git a/pcbnew/drc.cpp b/pcbnew/drc.cpp
index 0aa9a4b..dc05e5c 100644
--- a/pcbnew/drc.cpp
+++ b/pcbnew/drc.cpp
@@ -192,7 +192,7 @@ int DRC::TestZoneToZoneOutline( ZONE_CONTAINER* aZone, bool aCreateMarkers )
     // iterate through all areas
     for( int ia = 0; ia < board->GetAreaCountIncludingModules(); ia++ )
     {
-		ZONE_CONTAINER* zoneRef = board->GetAreaIncludingModules( ia );
+        ZONE_CONTAINER* zoneRef = board->GetAreaIncludingModules( ia );
         SHAPE_POLY_SET refSmoothedPoly;
 
         zoneRef->BuildSmoothedPoly( refSmoothedPoly );
@@ -764,7 +764,7 @@ void DRC::testZones()
     // if it differs from the net name from net code, there is a DRC issue
     for( int ii = 0; ii < m_pcb->GetAreaCountIncludingModules(); ii++ )
     {
-		ZONE_CONTAINER* test_area = m_pcb->GetAreaIncludingModules( ii );
+        ZONE_CONTAINER* test_area = m_pcb->GetAreaIncludingModules( ii );
 
         if( !test_area->IsOnCopperLayer() )
             continue;
@@ -795,7 +795,7 @@ void DRC::testKeepoutAreas()
     // Test keepout areas for vias, tracks and pads inside keepout areas, including modules'
     for( int ii = 0; ii < m_pcb->GetAreaCountIncludingModules(); ii++ )
     {
-		ZONE_CONTAINER* area = m_pcb->GetAreaIncludingModules( ii );
+        ZONE_CONTAINER* area = m_pcb->GetAreaIncludingModules( ii );
 
         if( !area->GetIsKeepout() )
         {
@@ -973,7 +973,7 @@ bool DRC::doTrackKeepoutDrc( TRACK* aRefSeg )
     // Test keepout areas for vias, tracks and pads inside keepout areas, including modules'
     for( int ii = 0; ii < m_pcb->GetAreaCountIncludingModules(); ii++ )
     {
-		ZONE_CONTAINER* area = m_pcb->GetAreaIncludingModules( ii );
+        ZONE_CONTAINER* area = m_pcb->GetAreaIncludingModules( ii );
 
         if( !area->GetIsKeepout() )
             continue;
diff --git a/pcbnew/footprint_editor_onclick.cpp b/pcbnew/footprint_editor_onclick.cpp
index 3518052..ae61e5e 100644
--- a/pcbnew/footprint_editor_onclick.cpp
+++ b/pcbnew/footprint_editor_onclick.cpp
@@ -558,88 +558,88 @@ void FOOTPRINT_EDIT_FRAME::OnEditItemRequest( wxDC* aDC, BOARD_ITEM* aItem )
         m_canvas->Refresh();
         break;
 
-	case PCB_ZONE_AREA_T:
-		{
-			ZONE_EDIT_T     edited;
-			ZONE_SETTINGS   zoneInfo = GetZoneSettings();
-
-			BOARD_COMMIT commit( this );
-			m_canvas->SetIgnoreMouseEvents( true );
-
-			ZONE_CONTAINER* aZone = static_cast<ZONE_CONTAINER*> ( aItem );
-			wxDC* DC = aDC;
-			
-			MODULE* parentModule = static_cast<MODULE*> ( aZone->GetParent() );
-			
-			if( !parentModule ) {
-				return;
-			}
-			
-			// 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
-			s_AuxiliaryList.ClearListAndDeleteItems();
-			s_PickedList.ClearListAndDeleteItems();
-			SaveCopyOfZones( s_PickedList, parentModule, -1, UNDEFINED_LAYER );
-
-			if( aZone->GetIsKeepout() )
-			{
-				// edit a keepout area on a copper layer
-				zoneInfo << *aZone;
-				edited = InvokeKeepoutAreaEditor( this, &zoneInfo );
-			}
-			else if( IsCopperLayer( aZone->GetLayer() ) )
-			{
-				// edit a zone on a copper layer
-
-				zoneInfo << *aZone;
-
-				edited = InvokeCopperZonesEditor( this, &zoneInfo );
-			}
-			else
-			{
-				edited = InvokeNonCopperZonesEditor( this, aZone, &zoneInfo );
-			}
-
-			m_canvas->MoveCursorToCrossHair();
-			m_canvas->SetIgnoreMouseEvents( false );
-
-			if( edited == ZONE_ABORT )
-			{
-				s_AuxiliaryList.ClearListAndDeleteItems();
-				s_PickedList.ClearListAndDeleteItems();
-				return;
-			}
-
-			if( edited == ZONE_EXPORT_VALUES )
-			{
-				UpdateCopyOfZonesList( s_PickedList, s_AuxiliaryList, parentModule );
-				commit.Stage( s_PickedList );
-				commit.Push( _( "Modify zone properties" ) );
-				s_PickedList.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items
-				return;
-			}
-
-			wxBusyCursor dummy;
-
-			// Undraw old zone outlines
-			for( int ii = 0; ii < parentModule->GetAreaCount(); ii++ )
-			{
-				ZONE_CONTAINER* edge_zone = parentModule->GetArea( ii );
-				edge_zone->Draw( m_canvas, DC, GR_XOR );
-
-				if( IsGalCanvasActive() )
-				{
-					GetGalCanvas()->GetView()->Update( edge_zone );
-				}
-			}
-
-			zoneInfo.ExportSetting( *aZone );
-
-			commit.Stage( s_PickedList );
-			commit.Push( _( "Modify zone properties" ) );
-
-			s_PickedList.ClearItemsList();  // s_ItemsListPicker is no longer owner of picked items
-		}
+    case PCB_ZONE_AREA_T:
+        {
+            ZONE_EDIT_T     edited;
+            ZONE_SETTINGS   zoneInfo = GetZoneSettings();
+
+            BOARD_COMMIT commit( this );
+            m_canvas->SetIgnoreMouseEvents( true );
+
+            ZONE_CONTAINER* aZone = static_cast<ZONE_CONTAINER*> ( aItem );
+            wxDC* DC = aDC;
+            
+            MODULE* parentModule = static_cast<MODULE*> ( aZone->GetParent() );
+            
+            if( !parentModule ) {
+                return;
+            }
+            
+            // 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
+            s_AuxiliaryList.ClearListAndDeleteItems();
+            s_PickedList.ClearListAndDeleteItems();
+            SaveCopyOfZones( s_PickedList, parentModule, -1, UNDEFINED_LAYER );
+
+            if( aZone->GetIsKeepout() )
+            {
+                // edit a keepout area on a copper layer
+                zoneInfo << *aZone;
+                edited = InvokeKeepoutAreaEditor( this, &zoneInfo );
+            }
+            else if( IsCopperLayer( aZone->GetLayer() ) )
+            {
+                // edit a zone on a copper layer
+
+                zoneInfo << *aZone;
+
+                edited = InvokeCopperZonesEditor( this, &zoneInfo );
+            }
+            else
+            {
+                edited = InvokeNonCopperZonesEditor( this, aZone, &zoneInfo );
+            }
+
+            m_canvas->MoveCursorToCrossHair();
+            m_canvas->SetIgnoreMouseEvents( false );
+
+            if( edited == ZONE_ABORT )
+            {
+                s_AuxiliaryList.ClearListAndDeleteItems();
+                s_PickedList.ClearListAndDeleteItems();
+                return;
+            }
+
+            if( edited == ZONE_EXPORT_VALUES )
+            {
+                UpdateCopyOfZonesList( s_PickedList, s_AuxiliaryList, parentModule );
+                commit.Stage( s_PickedList );
+                commit.Push( _( "Modify zone properties" ) );
+                s_PickedList.ClearItemsList(); // s_ItemsListPicker is no more owner of picked items
+                return;
+            }
+
+            wxBusyCursor dummy;
+
+            // Undraw old zone outlines
+            for( int ii = 0; ii < parentModule->GetAreaCount(); ii++ )
+            {
+                ZONE_CONTAINER* edge_zone = parentModule->GetArea( ii );
+                edge_zone->Draw( m_canvas, DC, GR_XOR );
+
+                if( IsGalCanvasActive() )
+                {
+                    GetGalCanvas()->GetView()->Update( edge_zone );
+                }
+            }
+
+            zoneInfo.ExportSetting( *aZone );
+
+            commit.Stage( s_PickedList );
+            commit.Push( _( "Modify zone properties" ) );
+
+            s_PickedList.ClearItemsList();  // s_ItemsListPicker is no longer owner of picked items
+        }
         break;
 
     default:
diff --git a/pcbnew/kicad_clipboard.cpp b/pcbnew/kicad_clipboard.cpp
index 19d2da6..98beb54 100644
--- a/pcbnew/kicad_clipboard.cpp
+++ b/pcbnew/kicad_clipboard.cpp
@@ -82,9 +82,9 @@ void CLIPBOARD_IO::SaveSelection( const SELECTION& aSelected )
         if( ( i->Type() != PCB_MODULE_EDGE_T ) &&
                 ( i->Type() != PCB_MODULE_TEXT_T ) &&
                 ( i->Type() != PCB_PAD_T ) &&
-                !( (i->Type() == PCB_ZONE_AREA_T ) && 
-					(i->GetParent()) && 
-					(i->GetParent()->Type() == PCB_MODULE_T) ) )
+                !( ( i->Type() == PCB_ZONE_AREA_T ) && 
+                    ( i->GetParent() ) && 
+                    ( i->GetParent()->Type() == PCB_MODULE_T ) ) )
         {
             onlyModuleParts = false;
             continue;
diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp
index c83d1a9..629a117 100644
--- a/pcbnew/kicad_plugin.cpp
+++ b/pcbnew/kicad_plugin.cpp
@@ -1163,12 +1163,12 @@ void PCB_IO::format( MODULE* aModule, int aNestLevel ) const
     }
     
     // save zones
-	for( int ii = 0; ii < aModule->GetAreaCount(); ii++ )
-	{
-		ZONE_CONTAINER* zone = aModule->GetArea( ii );
-		format( zone, aNestLevel+1 );
-	};
-		
+    for( int ii = 0; ii < aModule->GetAreaCount(); ii++ )
+    {
+        ZONE_CONTAINER* zone = aModule->GetArea( ii );
+        format( zone, aNestLevel+1 );
+    };
+        
     m_out->Print( aNestLevel, ")\n" );
 }
 
@@ -1190,11 +1190,11 @@ void PCB_IO::formatLayers( LSET aLayerMask, int aNestLevel ) const
     static const LSET mask(  2, B_Mask,     F_Mask );
     static const LSET crt_yd(2, B_CrtYd,    F_CrtYd );
     static const LSET fab(   2, B_Fab,      F_Fab );
-    static const LSET inner(   30,
-		In1_Cu, In2_Cu, In3_Cu, In4_Cu, In5_Cu, In6_Cu, In7_Cu, In8_Cu, In9_Cu, In10_Cu,
-		In11_Cu, In12_Cu, In13_Cu, In14_Cu, In15_Cu, In16_Cu, In17_Cu, In18_Cu, In19_Cu, In20_Cu,
-		In21_Cu, In22_Cu, In23_Cu, In24_Cu, In25_Cu, In26_Cu, In27_Cu, In28_Cu, In29_Cu, In30_Cu
-	);
+    static const LSET inner( 30,
+        In1_Cu, In2_Cu, In3_Cu, In4_Cu, In5_Cu, In6_Cu, In7_Cu, In8_Cu, In9_Cu, In10_Cu,
+        In11_Cu, In12_Cu, In13_Cu, In14_Cu, In15_Cu, In16_Cu, In17_Cu, In18_Cu, In19_Cu, In20_Cu,
+        In21_Cu, In22_Cu, In23_Cu, In24_Cu, In25_Cu, In26_Cu, In27_Cu, In28_Cu, In29_Cu, In30_Cu
+    );
 
     LSET cu_mask = cu_all;
 
diff --git a/pcbnew/menubar_footprint_editor.cpp b/pcbnew/menubar_footprint_editor.cpp
index 1ae64a5..77019f4 100644
--- a/pcbnew/menubar_footprint_editor.cpp
+++ b/pcbnew/menubar_footprint_editor.cpp
@@ -360,9 +360,10 @@ void FOOTPRINT_EDIT_FRAME::ReCreateMenuBar()
 
     placeMenu->AppendSeparator();
 
-	// Keepout Area
+    // Keepout Area
     AddMenuItem( placeMenu, ID_MODEDIT_KEEPOUT_AREA_TOOL,
-                 _( "&Keepout Area" ), _( "Add keepout areas" ), KiBitmap( add_keepout_area_xpm ) );
+                 _( "&Keepout Area" ), _( "Add keepout areas" ),
+                 KiBitmap( add_keepout_area_xpm ) );
 
     placeMenu->AppendSeparator();
 
diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp
index 1aade08..f0fcf6a 100644
--- a/pcbnew/pcb_parser.cpp
+++ b/pcbnew/pcb_parser.cpp
@@ -79,11 +79,11 @@ void PCB_PARSER::init()
     m_layerMasks[ "*.SilkS" ]   = LSET( 2, B_SilkS, F_SilkS );
     m_layerMasks[ "*.Fab" ]     = LSET( 2, B_Fab,   F_Fab );
     m_layerMasks[ "*.CrtYd" ]   = LSET( 2, B_CrtYd, F_CrtYd );
-    m_layerMasks[ "In*.Cu" ]   = LSET( 30,
-		In1_Cu, In2_Cu, In3_Cu, In4_Cu, In5_Cu, In6_Cu, In7_Cu, In8_Cu, In9_Cu, In10_Cu,
-		In11_Cu, In12_Cu, In13_Cu, In14_Cu, In15_Cu, In16_Cu, In17_Cu, In18_Cu, In19_Cu, In20_Cu,
-		In21_Cu, In22_Cu, In23_Cu, In24_Cu, In25_Cu, In26_Cu, In27_Cu, In28_Cu, In29_Cu, In30_Cu
-	);
+    m_layerMasks[ "In*.Cu" ]    = LSET( 30,
+        In1_Cu,  In2_Cu,  In3_Cu,  In4_Cu,  In5_Cu,  In6_Cu,  In7_Cu,  In8_Cu,  In9_Cu,  In10_Cu,
+        In11_Cu, In12_Cu, In13_Cu, In14_Cu, In15_Cu, In16_Cu, In17_Cu, In18_Cu, In19_Cu, In20_Cu,
+        In21_Cu, In22_Cu, In23_Cu, In24_Cu, In25_Cu, In26_Cu, In27_Cu, In28_Cu, In29_Cu, In30_Cu
+    );
 
     // This is for the first pretty & *.kicad_pcb formats, which had
     // Inner1_Cu - Inner14_Cu with the numbering sequence
@@ -345,9 +345,9 @@ void PCB_PARSER::parseEDA_TEXT( EDA_TEXT* aText )
     // 60mils is 1.524mm
     if( !foundTextSize )
     {
-    	const float defaultTextSize = 1.524f * IU_PER_MM;
+        const float defaultTextSize = 1.524f * IU_PER_MM;
 
-    	aText->SetTextSize( wxSize( defaultTextSize, defaultTextSize ) );
+        aText->SetTextSize( wxSize( defaultTextSize, defaultTextSize ) );
     }
 }
 
@@ -2015,7 +2015,7 @@ MODULE* PCB_PARSER::parseMODULE_unchecked( wxArrayString* aInitialComments )
             break;
 
         case T_zone:
-			module->Add( parseZONE_CONTAINER(), ADD_APPEND );
+            module->Add( parseZONE_CONTAINER(), ADD_APPEND );
             break;
 
         default:
@@ -2843,19 +2843,16 @@ ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER()
     // bigger scope since each filled_polygon is concatenated in here
     SHAPE_POLY_SET pts;
 
-	std::unique_ptr< ZONE_CONTAINER > zone;
-	if(m_board != nullptr)
-	{
-		zone = std::unique_ptr< ZONE_CONTAINER > ( new ZONE_CONTAINER( m_board ) );
-	}else {
-		std::unique_ptr<BOARD> aBoard( new BOARD( ) );
-		//zone = std::unique_ptr< ZONE_CONTAINER > ( new ZONE_CONTAINER( nullptr ) );
-		//aBoard.get()->GetZoneSettings().ExportSetting( *(zone.get()) );
-		//aBoard->GetZoneSettings().ExportSetting( *zone );
-		
-		zone = std::unique_ptr< ZONE_CONTAINER > ( new ZONE_CONTAINER( aBoard.get() ) );
-		zone->SetParent( nullptr );
-	}
+    std::unique_ptr< ZONE_CONTAINER > zone;
+    if( m_board != nullptr )
+    {
+        zone = std::unique_ptr< ZONE_CONTAINER > ( new ZONE_CONTAINER( m_board ) );
+    }else {
+        std::unique_ptr<BOARD> aBoard( new BOARD( ) );
+        
+        zone = std::unique_ptr< ZONE_CONTAINER > ( new ZONE_CONTAINER( aBoard.get() ) );
+        zone->SetParent( nullptr );
+    }
 
     zone->SetPriority( 0 );
 
diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp
index 55fadc8..553f322 100644
--- a/pcbnew/tools/drawing_tool.cpp
+++ b/pcbnew/tools/drawing_tool.cpp
@@ -644,13 +644,13 @@ int DRAWING_TOOL::DrawZoneKeepout( const TOOL_EVENT& aEvent )
 {
     SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::KEEPOUT );
 
-	if( m_editModules )
-	{
-		m_frame->SetToolID( ID_MODEDIT_KEEPOUT_AREA_TOOL, wxCURSOR_PENCIL, _( "Add keepout" ) );
-	} else
-	{
-		m_frame->SetToolID( ID_PCB_KEEPOUT_AREA_BUTT, wxCURSOR_PENCIL, _( "Add keepout" ) );
-	}
+    if( m_editModules )
+    {
+        m_frame->SetToolID( ID_MODEDIT_KEEPOUT_AREA_TOOL, wxCURSOR_PENCIL, _( "Add keepout" ) );
+    } else
+    {
+        m_frame->SetToolID( ID_PCB_KEEPOUT_AREA_BUTT, wxCURSOR_PENCIL, _( "Add keepout" ) );
+    }
 
     return drawZone( true, ZONE_MODE::ADD );
 }
diff --git a/pcbnew/tools/pcbnew_control.cpp b/pcbnew/tools/pcbnew_control.cpp
index 320094d..5137d45 100644
--- a/pcbnew/tools/pcbnew_control.cpp
+++ b/pcbnew/tools/pcbnew_control.cpp
@@ -865,7 +865,7 @@ int PCBNEW_CONTROL::PasteItemsFromClipboard( const TOOL_EVENT& aEvent )
                 return 0;
             }
 
-		    placeBoardItems( static_cast<BOARD*>( clipItem ) );
+            placeBoardItems( static_cast<BOARD*>( clipItem ) );
             break;
         }
 
@@ -890,10 +890,10 @@ int PCBNEW_CONTROL::PasteItemsFromClipboard( const TOOL_EVENT& aEvent )
                     items.push_back( item );
                 }
                 for( auto zone : mod->Zones() )
-				{
-					zone->SetParent ( board()->m_Modules.GetFirst() );
-					items.push_back( zone );
-				}
+                {
+                    zone->SetParent ( board()->m_Modules.GetFirst() );
+                    items.push_back( zone );
+                }
             }
             else
             {
diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp
index 83575f3..e0ad53d 100644
--- a/pcbnew/tools/selection_tool.cpp
+++ b/pcbnew/tools/selection_tool.cpp
@@ -1535,17 +1535,17 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const
         {
             auto* zone = static_cast<const ZONE_CONTAINER*>( aItem );
 
-			//check if zone has a parent of type module
-			if( zone && zone->GetParent() && (zone->GetParent()->Type() == PCB_MODULE_T) )
-			{
-				// only if not editing module
-				if(m_frame->IsType(FRAME_PCB_MODULE_EDITOR) == false)
-				{
-					return false;
-				}	
-				
-			}
-			
+            //check if zone has a parent of type module
+            if( zone && zone->GetParent() && ( zone->GetParent()->Type() == PCB_MODULE_T ) )
+            {
+                // only if not editing module
+                if( m_frame->IsType(FRAME_PCB_MODULE_EDITOR ) == false )
+                {
+                    return false;
+                }    
+                
+            }
+            
             if( zone && zone->GetIsKeepout() )
             {
                 auto zoneLayers = zone->GetLayerSet().Seq();
diff --git a/pcbnew/tools/zone_create_helper.cpp b/pcbnew/tools/zone_create_helper.cpp
index b1e3f02..512d4d5 100644
--- a/pcbnew/tools/zone_create_helper.cpp
+++ b/pcbnew/tools/zone_create_helper.cpp
@@ -93,14 +93,13 @@ std::unique_ptr<ZONE_CONTAINER> ZONE_CREATE_HELPER::createNewZone( bool aKeepout
     // Apply the selected settings
     zoneInfo.ExportSetting( *newZone );
     
-    if(frame.IsType(FRAME_PCB_MODULE_EDITOR)) {
-		for( auto module : board.Modules() )
-		{
-			newZone->SetParent(module);
-			break;
-		}
-		
-	}
+    if( frame.IsType( FRAME_PCB_MODULE_EDITOR ) ) {
+        for( auto module : board.Modules() )
+        {
+            newZone->SetParent( module );
+            break;
+        }
+    }
 
     return newZone;
 }
diff --git a/pcbnew/zones_functions_for_undo_redo.cpp b/pcbnew/zones_functions_for_undo_redo.cpp
index 9322f96..0a606a4 100644
--- a/pcbnew/zones_functions_for_undo_redo.cpp
+++ b/pcbnew/zones_functions_for_undo_redo.cpp
@@ -178,12 +178,12 @@ int SaveCopyOfZones( PICKED_ITEMS_LIST& aPickList, MODULE* aModule, int aNetCode
 {
     int copyCount = 0;
 
-	MODULE* moduleDup = new MODULE( *aModule );
-	moduleDup->SetParent ( aModule->GetParent () );
-	ITEM_PICKER picker( aModule, UR_CHANGED );
-	picker.SetLink( moduleDup );
-	aPickList.PushItem( picker );
-	copyCount++;	
+    MODULE* moduleDup = new MODULE( *aModule );
+    moduleDup->SetParent ( aModule->GetParent() );
+    ITEM_PICKER picker( aModule, UR_CHANGED );
+    picker.SetLink( moduleDup );
+    aPickList.PushItem( picker );
+    copyCount++;    
 
     return copyCount;
 }
-- 
2.7.4


Follow ups

References