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_board.h>
|
||||||
#include <class_module.h>
|
#include <class_module.h>
|
||||||
#include <class_track.h>
|
#include <class_track.h>
|
||||||
|
#include <class_drawsegment.h>
|
||||||
|
#include <class_zone.h>
|
||||||
#include <board_commit.h>
|
#include <board_commit.h>
|
||||||
#include <kicad_device_context.h>
|
#include <kicad_device_context.h>
|
||||||
|
|
||||||
|
@ -176,14 +178,190 @@ void PCB_EDIT_FRAME::OnActionPlugin( wxCommandEvent& aEvent )
|
||||||
|
|
||||||
if( actionPlugin )
|
if( actionPlugin )
|
||||||
{
|
{
|
||||||
// TODO: Adding recovery point for jobs
|
PICKED_ITEMS_LIST itemsList;
|
||||||
// BOARD_COMMIT commit( this );
|
BOARD* currentPcb = GetBoard();
|
||||||
// commit.Push( _( "External plugin" ) );
|
bool fromEmpty = false;
|
||||||
|
|
||||||
actionPlugin->Run();
|
itemsList.m_Status = UR_CHANGED;
|
||||||
|
|
||||||
OnModify();
|
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() )
|
if( IsGalCanvasActive() )
|
||||||
{
|
{
|
||||||
UseGalCanvas( GetGalCanvas() );
|
UseGalCanvas( GetGalCanvas() );
|
||||||
|
@ -201,7 +379,7 @@ void PCB_EDIT_FRAME::RebuildActionPluginMenus()
|
||||||
{
|
{
|
||||||
wxMenu* actionMenu = GetMenuBar()->FindItem( ID_TOOLBARH_PCB_ACTION_PLUGIN )->GetSubMenu();
|
wxMenu* actionMenu = GetMenuBar()->FindItem( ID_TOOLBARH_PCB_ACTION_PLUGIN )->GetSubMenu();
|
||||||
|
|
||||||
if( !actionMenu ) // Should not occur.
|
if( !actionMenu ) // Should not occur.
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// First, remove existing submenus, if they are too many
|
// First, remove existing submenus, if they are too many
|
||||||
|
@ -235,7 +413,7 @@ void PCB_EDIT_FRAME::RebuildActionPluginMenus()
|
||||||
{
|
{
|
||||||
wxMenuItem* item;
|
wxMenuItem* item;
|
||||||
|
|
||||||
if( ii < (int)available_menus.size() )
|
if( ii < (int) available_menus.size() )
|
||||||
{
|
{
|
||||||
item = available_menus[ii];
|
item = available_menus[ii];
|
||||||
item->SetItemLabel( ACTION_PLUGINS::GetAction( ii )->GetName() );
|
item->SetItemLabel( ACTION_PLUGINS::GetAction( ii )->GetName() );
|
||||||
|
@ -248,9 +426,9 @@ void PCB_EDIT_FRAME::RebuildActionPluginMenus()
|
||||||
ACTION_PLUGINS::GetAction( ii )->GetDescription(),
|
ACTION_PLUGINS::GetAction( ii )->GetDescription(),
|
||||||
KiBitmap( hammer_xpm ) );
|
KiBitmap( hammer_xpm ) );
|
||||||
|
|
||||||
Connect( item->GetId(), wxEVT_COMMAND_MENU_SELECTED,
|
Connect( item->GetId(), wxEVT_COMMAND_MENU_SELECTED,
|
||||||
(wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) &
|
(wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) &
|
||||||
PCB_EDIT_FRAME::OnActionPlugin );
|
PCB_EDIT_FRAME::OnActionPlugin );
|
||||||
}
|
}
|
||||||
|
|
||||||
ACTION_PLUGINS::SetActionMenu( ii, item->GetId() );
|
ACTION_PLUGINS::SetActionMenu( ii, item->GetId() );
|
||||||
|
|
Loading…
Reference in New Issue