Action plugins: handle undo/redo feature when running an action plugin.
This commit is contained in:
parent
431abcff0c
commit
13395d34dd
|
@ -0,0 +1,157 @@
|
|||
|
||||
from pcbnew import *
|
||||
import random
|
||||
import pprint
|
||||
|
||||
|
||||
class testundoredo0(ActionPlugin):
|
||||
|
||||
def defaults(self):
|
||||
self.name = "Test Undo/Redo: Remove footprints"
|
||||
self.category = "Test Undo/Redo"
|
||||
self.description = ""
|
||||
|
||||
def Run(self):
|
||||
pcb = GetBoard()
|
||||
|
||||
for module in pcb.GetModules():
|
||||
pcb.RemoveNative(module)
|
||||
|
||||
|
||||
class testundoredo1(ActionPlugin):
|
||||
|
||||
def defaults(self):
|
||||
self.name = "Test Undo/Redo: Remove all board items"
|
||||
self.category = "Test Undo/Redo"
|
||||
self.description = ""
|
||||
|
||||
def Run(self):
|
||||
pcb = GetBoard()
|
||||
|
||||
while pcb.GetAreaCount() > 0:
|
||||
area = pcb.GetArea(0)
|
||||
pcb.RemoveNative(area)
|
||||
|
||||
for module in pcb.GetModules():
|
||||
pcb.RemoveNative(module)
|
||||
|
||||
for track in pcb.GetTracks():
|
||||
pcb.RemoveNative(track)
|
||||
|
||||
for draw in pcb.m_Drawings:
|
||||
pcb.RemoveNative(draw)
|
||||
|
||||
|
||||
class testundoredo2(ActionPlugin):
|
||||
|
||||
def defaults(self):
|
||||
self.name = "Test Undo/Redo: Generate random content"
|
||||
self.category = "Test Undo/Redo"
|
||||
self.description = ""
|
||||
|
||||
def createFPCXModule(self,pads):
|
||||
size_025_160mm = wxSizeMM(0.25,1.6)
|
||||
size_150_200mm = wxSizeMM(1.50,2.0)
|
||||
# create a new module, it's parent is our previously created pcb
|
||||
module = MODULE(self.pcb)
|
||||
module.SetReference("FPC"+str(pads)) # give it a reference name
|
||||
module.Reference().SetPosition(wxPointMM(-1,-1))
|
||||
self.pcb.Add(module) # add it to our pcb
|
||||
m_pos = wxPointMM(0,0)#random.randint(10,200),random.randint(10,200))
|
||||
module.SetPosition(m_pos)
|
||||
|
||||
# create a pad array and add it to the module
|
||||
|
||||
|
||||
def smdRectPad(module,size,pos,name):
|
||||
pad = D_PAD(module)
|
||||
pad.SetSize(size)
|
||||
pad.SetShape(PAD_SHAPE_RECT)
|
||||
pad.SetAttribute(PAD_ATTRIB_SMD)
|
||||
pad.SetLayerSet(pad.SMDMask())
|
||||
pad.SetPosition(pos)
|
||||
pad.SetPadName(name)
|
||||
return pad
|
||||
|
||||
for n in range (0,pads):
|
||||
pad = smdRectPad(module,size_025_160mm,wxPointMM(0.5*n,0),str(n+1))
|
||||
module.Add(pad)
|
||||
|
||||
|
||||
pad_s0 = smdRectPad(module,size_150_200mm,wxPointMM(-1.6,1.3),"0")
|
||||
pad_s1 = smdRectPad(module,size_150_200mm,wxPointMM((pads-1)*0.5+1.6,1.3),"0")
|
||||
module.Add(pad_s0)
|
||||
module.Add(pad_s1)
|
||||
|
||||
e = EDGE_MODULE(module)
|
||||
e.SetStart0(wxPointMM(-1,0))
|
||||
e.SetEnd0(wxPointMM(0,0))
|
||||
e.SetWidth(FromMM(0.2))
|
||||
e.SetLayer(F_SilkS)
|
||||
e.SetShape(S_SEGMENT)
|
||||
module.Add(e)
|
||||
module.SetPosition(wxPointMM(random.randint(20,200),random.randint(20,150)))
|
||||
return module
|
||||
|
||||
|
||||
|
||||
def Run(self):
|
||||
self.pcb = GetBoard()
|
||||
random.seed()
|
||||
|
||||
for i in range(10):
|
||||
seg = DRAWSEGMENT()
|
||||
seg.SetLayer( random.choice([Edge_Cuts,Cmts_User,Eco1_User,Eco2_User]) )
|
||||
seg.SetStart( wxPointMM( random.randint(10,100),
|
||||
random.randint(10,100) ) )
|
||||
seg.SetEnd( wxPointMM( random.randint(10,100),
|
||||
random.randint(10,100) ) )
|
||||
self.pcb.Add( seg )
|
||||
|
||||
if i%2 == 0:
|
||||
t = TRACK(None)
|
||||
else:
|
||||
t = VIA(None)
|
||||
#t.SetLayerPair(segments['layerPair'][0],segments['layerPair'][1])
|
||||
t.SetViaType(VIA_THROUGH)
|
||||
t.SetDrill(FromMM(random.randint(1,20)/10.0))
|
||||
t.SetStart(wxPointMM(random.randint(100,150),random.randint(100,150)))
|
||||
t.SetEnd(wxPointMM(random.randint(100,150),random.randint(100,150)))
|
||||
t.SetWidth(FromMM(random.randint(1,15)/10.0))
|
||||
t.SetLayer(random.choice([F_Cu,B_Cu]))
|
||||
self.pcb.Add(t)
|
||||
|
||||
self.createFPCXModule(random.randint(2,40))
|
||||
|
||||
|
||||
class testundoredo3(ActionPlugin):
|
||||
|
||||
def defaults(self):
|
||||
self.name = "Test Undo/Redo: Move elements randomly"
|
||||
self.category = "Test Undo/Redo"
|
||||
self.description = ""
|
||||
|
||||
def Run(self):
|
||||
pcb = GetBoard()
|
||||
|
||||
for i in range(0,pcb.GetAreaCount()):
|
||||
area = pcb.GetArea(i)
|
||||
area.Move(wxPointMM(random.randint(-20,20),random.randint(-20,20)))
|
||||
|
||||
for module in pcb.GetModules():
|
||||
module.Move(wxPointMM(random.randint(-20,20),random.randint(-20,20)))
|
||||
if random.randint(0,10) > 5:
|
||||
module.Flip(module.GetPosition())
|
||||
|
||||
for track in pcb.GetTracks():
|
||||
track.Move(wxPointMM(random.randint(-20,20),random.randint(-20,20)))
|
||||
|
||||
for draw in pcb.m_Drawings:
|
||||
draw.Move(wxPointMM(random.randint(-20,20),random.randint(-20,20)))
|
||||
|
||||
|
||||
|
||||
testundoredo0().register()
|
||||
testundoredo1().register()
|
||||
testundoredo2().register()
|
||||
testundoredo3().register()
|
|
@ -36,6 +36,8 @@
|
|||
#include <class_board.h>
|
||||
#include <class_module.h>
|
||||
#include <class_track.h>
|
||||
#include <class_drawsegment.h>
|
||||
#include <class_zone.h>
|
||||
#include <board_commit.h>
|
||||
#include <kicad_device_context.h>
|
||||
|
||||
|
@ -176,14 +178,190 @@ void PCB_EDIT_FRAME::OnActionPlugin( wxCommandEvent& aEvent )
|
|||
|
||||
if( actionPlugin )
|
||||
{
|
||||
// TODO: Adding recovery point for jobs
|
||||
// BOARD_COMMIT commit( this );
|
||||
// commit.Push( _( "External plugin" ) );
|
||||
PICKED_ITEMS_LIST itemsList;
|
||||
BOARD* currentPcb = GetBoard();
|
||||
bool fromEmpty = false;
|
||||
|
||||
actionPlugin->Run();
|
||||
itemsList.m_Status = UR_CHANGED;
|
||||
|
||||
OnModify();
|
||||
|
||||
// Append tracks:
|
||||
for( BOARD_ITEM* item = currentPcb->m_Track; item != NULL; item = item->Next() )
|
||||
{
|
||||
ITEM_PICKER picker( item, UR_CHANGED );
|
||||
itemsList.PushItem( picker );
|
||||
}
|
||||
|
||||
// Append modules:
|
||||
for( BOARD_ITEM* item = currentPcb->m_Modules; item != NULL; item = item->Next() )
|
||||
{
|
||||
ITEM_PICKER picker( item, UR_CHANGED );
|
||||
itemsList.PushItem( picker );
|
||||
}
|
||||
|
||||
// Append drawings
|
||||
for( BOARD_ITEM* item = currentPcb->m_Drawings; item != NULL; item = item->Next() )
|
||||
{
|
||||
ITEM_PICKER picker( item, UR_CHANGED );
|
||||
itemsList.PushItem( picker );
|
||||
}
|
||||
|
||||
// Append zones outlines
|
||||
for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ )
|
||||
{
|
||||
ITEM_PICKER picker( (EDA_ITEM*) currentPcb->GetArea(
|
||||
ii ), UR_CHANGED );
|
||||
itemsList.PushItem( picker );
|
||||
}
|
||||
|
||||
// Append zones segm:
|
||||
for( BOARD_ITEM* item = currentPcb->m_Zone; item != NULL; item = item->Next() )
|
||||
{
|
||||
ITEM_PICKER picker( item, UR_CHANGED );
|
||||
itemsList.PushItem( picker );
|
||||
}
|
||||
|
||||
if( itemsList.GetCount() > 0 )
|
||||
SaveCopyInUndoList( itemsList, UR_CHANGED, wxPoint( 0.0, 0.0 ) );
|
||||
else
|
||||
fromEmpty = true;
|
||||
|
||||
itemsList.ClearItemsList();
|
||||
|
||||
// Execute plugin himself...
|
||||
actionPlugin->Run();
|
||||
|
||||
currentPcb->m_Status_Pcb = 0;
|
||||
|
||||
// Get back the undo buffer to fix some modifications
|
||||
PICKED_ITEMS_LIST* oldBuffer = NULL;
|
||||
|
||||
if( fromEmpty )
|
||||
{
|
||||
oldBuffer = new PICKED_ITEMS_LIST();
|
||||
oldBuffer->m_Status = UR_NEW;
|
||||
}
|
||||
else
|
||||
{
|
||||
oldBuffer = GetScreen()->PopCommandFromUndoList();
|
||||
wxASSERT( oldBuffer );
|
||||
}
|
||||
|
||||
// Try do discover what was modified
|
||||
|
||||
PICKED_ITEMS_LIST deletedItemsList;
|
||||
|
||||
// Found deleted modules
|
||||
for( unsigned int i = 0; i < oldBuffer->GetCount(); i++ )
|
||||
{
|
||||
BOARD_ITEM* item = (BOARD_ITEM*) oldBuffer->GetPickedItem( i );
|
||||
ITEM_PICKER picker( item, UR_DELETED );
|
||||
|
||||
wxASSERT( item );
|
||||
|
||||
switch( item->Type() )
|
||||
{
|
||||
case PCB_NETINFO_T:
|
||||
case PCB_MARKER_T:
|
||||
case PCB_MODULE_T:
|
||||
case PCB_TRACE_T:
|
||||
case PCB_VIA_T:
|
||||
case PCB_LINE_T:
|
||||
case PCB_TEXT_T:
|
||||
case PCB_DIMENSION_T:
|
||||
case PCB_TARGET_T:
|
||||
case PCB_ZONE_T:
|
||||
|
||||
// If item has a list it's mean that the element is on the board
|
||||
if( item->GetList() == NULL )
|
||||
{
|
||||
deletedItemsList.PushItem( picker );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PCB_ZONE_AREA_T:
|
||||
{
|
||||
bool zoneFound = false;
|
||||
|
||||
for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ )
|
||||
zoneFound |= currentPcb->GetArea( ii ) == item;
|
||||
|
||||
if( !zoneFound )
|
||||
{
|
||||
deletedItemsList.PushItem( picker );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
wxString msg;
|
||||
msg.Printf( wxT( "(PCB_EDIT_FRAME::OnActionPlugin) needs work: "
|
||||
"BOARD_ITEM type (%d) not handled" ),
|
||||
item->Type() );
|
||||
wxFAIL_MSG( msg );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Mark deleted elements in undolist
|
||||
for( unsigned int i = 0; i < deletedItemsList.GetCount(); i++ )
|
||||
{
|
||||
oldBuffer->PushItem( deletedItemsList.GetItemWrapper( i ) );
|
||||
}
|
||||
|
||||
// Find new modules
|
||||
for( BOARD_ITEM* item = currentPcb->m_Modules; item != NULL; item = item->Next() )
|
||||
{
|
||||
if( !oldBuffer->ContainsItem( item ) )
|
||||
{
|
||||
ITEM_PICKER picker( item, UR_NEW );
|
||||
oldBuffer->PushItem( picker );
|
||||
}
|
||||
}
|
||||
|
||||
for( BOARD_ITEM* item = currentPcb->m_Track; item != NULL; item = item->Next() )
|
||||
{
|
||||
if( !oldBuffer->ContainsItem( item ) )
|
||||
{
|
||||
ITEM_PICKER picker( item, UR_NEW );
|
||||
oldBuffer->PushItem( picker );
|
||||
}
|
||||
}
|
||||
|
||||
for( BOARD_ITEM* item = currentPcb->m_Drawings; item != NULL; item = item->Next() )
|
||||
{
|
||||
if( !oldBuffer->ContainsItem( item ) )
|
||||
{
|
||||
ITEM_PICKER picker( item, UR_NEW );
|
||||
oldBuffer->PushItem( picker );
|
||||
}
|
||||
}
|
||||
|
||||
for( BOARD_ITEM* item = currentPcb->m_Zone; item != NULL; item = item->Next() )
|
||||
{
|
||||
if( !oldBuffer->ContainsItem( item ) )
|
||||
{
|
||||
ITEM_PICKER picker( item, UR_NEW );
|
||||
oldBuffer->PushItem( picker );
|
||||
}
|
||||
}
|
||||
|
||||
for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ )
|
||||
{
|
||||
if( !oldBuffer->ContainsItem( (EDA_ITEM*) currentPcb->GetArea( ii ) ) )
|
||||
{
|
||||
ITEM_PICKER picker( (EDA_ITEM*) currentPcb->GetArea(
|
||||
ii ), UR_NEW );
|
||||
oldBuffer->PushItem( picker );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GetScreen()->PushCommandToUndoList( oldBuffer );
|
||||
|
||||
if( IsGalCanvasActive() )
|
||||
{
|
||||
UseGalCanvas( GetGalCanvas() );
|
||||
|
@ -235,7 +413,7 @@ void PCB_EDIT_FRAME::RebuildActionPluginMenus()
|
|||
{
|
||||
wxMenuItem* item;
|
||||
|
||||
if( ii < (int)available_menus.size() )
|
||||
if( ii < (int) available_menus.size() )
|
||||
{
|
||||
item = available_menus[ii];
|
||||
item->SetItemLabel( ACTION_PLUGINS::GetAction( ii )->GetName() );
|
||||
|
|
Loading…
Reference in New Issue