Commit 5a202e16 authored by Garth Corral's avatar Garth Corral

Merge trunk @ 5315

parents 0cf91f46 58f2d2e8
......@@ -148,6 +148,34 @@ void DSNLEXER::SetSpecctraMode( bool aMode )
}
}
bool DSNLEXER::SyncLineReaderWith( DSNLEXER& aLexer )
{
// Synchronize the pointers handling the data read by the LINE_READER
// only if aLexer shares the same LINE_READER, because only in this case
// the char buffer can be common
if( reader != aLexer.reader )
return false;
// Be sure the char buffer is common
if( reader->Line() != aLexer.reader->Line() )
return false;
// We can synchronize the pointers which handle the data currently read
start = aLexer.start;
next = aLexer.next;
limit = aLexer.limit;
// Sync these parameters is not mandatory, but could help
// for instance in debug
curText = aLexer.curText;
curOffset = aLexer.curOffset;
return true;
}
void DSNLEXER::PushReader( LINE_READER* aLineReader )
{
readerStack.push_back( aLineReader );
......
......@@ -275,6 +275,9 @@ bool FOOTPRINT_LIST::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* a
FOOTPRINT_INFO* FOOTPRINT_LIST::GetModuleInfo( const wxString& aFootprintName )
{
if( aFootprintName.IsEmpty() )
return NULL;
BOOST_FOREACH( FOOTPRINT_INFO& fp, m_list )
{
FPID fpid;
......
......@@ -69,7 +69,6 @@ public:
private:
void parsePlugin() throw( IO_ERROR, PARSE_ERROR );
};
// PCB_PLOT_PARAMS_PARSER
......@@ -162,7 +161,7 @@ private:
// the first is the title
// the second is the command line
wxArrayString m_plugins;
wxConfigBase* m_config; // to store the "plugins"
wxConfigBase* m_config; // to store the "plugins"
public:
// Constructor and destructor
......@@ -175,7 +174,6 @@ private:
void OnCancelClick( wxCommandEvent& event );
void OnHelp( wxCommandEvent& event );
void OnAddPlugin( wxCommandEvent& event );
void OnChoosePlugin( wxCommandEvent& event );
void OnRemovePlugin( wxCommandEvent& event );
void OnEditPlugin( wxCommandEvent& event );
void OnCommandLineEdited( wxCommandEvent& event );
......@@ -183,6 +181,25 @@ private:
void pluginInit();
void installPluginsList();
/**
* @return the Plugin filename from a command line
* @param aCommand = the command line
*/
wxString getPluginFileName( const wxString& aCommand );
/**
* display (when exists) the text found between the keyword "@package"
* (compatible with doxygen comments)
* and the end of comment block (""" in python", --> in xml)
*/
void displayPluginInfo( FILE * aFile, const wxString& aFilename );
/**
* Browse plugin files, and set m_CommandStringCtrl field
* @return a command line ro run the plugin
*/
wxString choosePlugin();
};
// Create and show DIALOG_BOM.
......@@ -215,12 +232,14 @@ DIALOG_BOM::~DIALOG_BOM()
STRING_FORMATTER writer;
writer.Print( 0, "(plugins" );
for( unsigned ii = 0; ii < m_plugins.GetCount(); ii += 2 )
{
writer.Print( 1, "(plugin %s (cmd %s))",
writer.Quotew( m_plugins[ii] ).c_str(),
writer.Quotew( m_plugins[ii+1] ).c_str() );
}
writer.Print( 0, ")" );
wxString list( FROM_UTF8( writer.GetString().c_str() ) );
......@@ -272,6 +291,7 @@ void DIALOG_BOM::OnPluginSelected( wxCommandEvent& event )
pluginInit();
}
#include <wx/ffile.h>
void DIALOG_BOM::pluginInit()
{
int ii = m_lbPlugins->GetSelection();
......@@ -285,9 +305,71 @@ void DIALOG_BOM::pluginInit()
m_textCtrlName->SetValue( m_plugins[2 * ii] );
m_textCtrlCommand->SetValue( m_plugins[(2 * ii)+1] );
wxString pluginName = getPluginFileName( m_textCtrlCommand->GetValue() );
if( pluginName.IsEmpty() )
return;
FILE* pluginFile = wxFopen( pluginName, "rt" );
if( pluginFile == NULL )
{
wxString msg;
msg.Printf( _( "Failed to open file '%s'" ), GetChars( pluginName ) );
DisplayError( this, msg );
return;
}
displayPluginInfo( pluginFile, pluginName );
}
void DIALOG_BOM::displayPluginInfo( FILE * aFile, const wxString& aFilename )
{
m_Messages->Clear();
// display (when exists) the text found between the keyword "@package"
// (compatible with doxygen comments)
// and the end of comment block (""" in python", --> in xml)
wxString data;
wxFFile fdata( aFile ); // dtor will close the file
if( !fdata.ReadAll( &data ) )
return;
wxString header( wxT( "@package" ) );
wxString endsection( wxT( "-->" ) ); // For xml
wxFileName fn( aFilename );
if( fn.GetExt().IsSameAs( wxT("py"), false ) )
endsection = wxT( "\"\"\"" );
else if( !fn.GetExt().IsSameAs( wxT("xsl"), false ) )
// If this is not a python file, we know nothing about file
// and the info cannot be found
return;
// Extract substring between @package and """
int strstart = data.Find( header );
if( strstart == wxNOT_FOUND )
return;
strstart += header.Length();
int strend = data.find( endsection, strstart );
if( strend == wxNOT_FOUND)
return;
// Remove emty line if any
while( data[strstart] < ' ' )
strstart++;
m_Messages->SetValue( data.SubString( strstart, strend-1 ) );
}
/**
* Function RunPlugin
* run the plugin command line
......@@ -350,8 +432,17 @@ void DIALOG_BOM::OnRemovePlugin( wxCommandEvent& event )
*/
void DIALOG_BOM::OnAddPlugin( wxCommandEvent& event )
{
wxString cmdLine = choosePlugin();
if( cmdLine.IsEmpty() )
return;
// Creates a new plugin entry
wxString name = wxGetTextFromUser( _("Plugin") );
wxFileName fn( getPluginFileName( cmdLine ) );
wxString defaultName = fn.GetName();
wxString name = wxGetTextFromUser( _("Plugin name in plugin list") ,
_("Plugin name"), defaultName );
if( name.IsEmpty() )
return;
......@@ -361,22 +452,26 @@ void DIALOG_BOM::OnAddPlugin( wxCommandEvent& event )
{
if( name == m_plugins[ii] )
{
wxMessageBox( _("This plugin already exists. Abort") );
wxMessageBox( _("This name already exists. Abort") );
return;
}
}
// Eppend the new plugin
m_plugins.Add( name );
m_plugins.Add( wxEmptyString );
m_lbPlugins->SetSelection( m_lbPlugins->GetCount() - 1 );
m_lbPlugins->Append( name );
m_lbPlugins->SetSelection( m_lbPlugins->GetCount() - 1 );
m_textCtrlCommand->SetValue( cmdLine );
pluginInit();
}
/*
* Browse plugin files, and set m_CommandStringCtrl field
*/
void DIALOG_BOM::OnChoosePlugin( wxCommandEvent& event )
wxString DIALOG_BOM::choosePlugin()
{
wxString mask = wxT( "*" );
#ifndef __WXMAC__
......@@ -395,7 +490,7 @@ void DIALOG_BOM::OnChoosePlugin( wxCommandEvent& event )
true
);
if( fullFileName.IsEmpty() )
return;
return wxEmptyString;
// Creates a default command line,
// suitable to run the external tool xslproc or python
......@@ -414,44 +509,65 @@ void DIALOG_BOM::OnChoosePlugin( wxCommandEvent& event )
else
cmdLine.Printf(wxT("\"%s\""), GetChars( fullFileName ) );
m_textCtrlCommand->SetValue( cmdLine );
return cmdLine;
}
void DIALOG_BOM::OnEditPlugin( wxCommandEvent& event )
wxString DIALOG_BOM::getPluginFileName( const wxString& aCommand )
{
wxString pluginName, cmdline;
wxString pluginName;
// Try to find the plugin name.
// This is possible if the name ends by .py or .xsl
cmdline = m_textCtrlCommand->GetValue();
int pos = -1;
if( (pos = cmdline.Find( wxT(".py") )) != wxNOT_FOUND )
if( (pos = aCommand.Find( wxT(".py") )) != wxNOT_FOUND )
pos += 2;
else if( (pos = cmdline.Find( wxT(".xsl") )) != wxNOT_FOUND )
else if( (pos = aCommand.Find( wxT(".xsl") )) != wxNOT_FOUND )
pos += 3;
// the end of plugin name is at position pos.
if( pos > 0 )
{
// Be sure this is the end of the name: the next char is " or space
int eos = cmdline[pos+1];
int eos = aCommand[pos+1];
if( eos == ' '|| eos == '\"' )
{
// search for the starting point of the name
int jj = pos-1;
while( jj >= 0 )
if( cmdline[jj] != eos )
if( aCommand[jj] != eos )
jj--;
else
break;
// extract the name
if( jj >= 0 )
pluginName = cmdline.SubString( jj, pos );
{
eos = aCommand[jj];
if( eos == ' '|| eos == '\"' ) // do not include delimiters
jj++;
pluginName = aCommand.SubString( jj, pos );
}
}
}
return pluginName;
}
void DIALOG_BOM::OnEditPlugin( wxCommandEvent& event )
{
wxString pluginName = getPluginFileName( m_textCtrlCommand->GetValue() );
if( pluginName.Length() <= 2 ) // if name != ""
{
wxMessageBox( _("Plugin file name not found. Cannot edit plugin file") );
return;
}
AddDelimiterString( pluginName );
wxString editorname = Pgm().GetEditorName();
......
......@@ -16,7 +16,6 @@ BEGIN_EVENT_TABLE( DIALOG_BOM_BASE, DIALOG_SHIM )
EVT_BUTTON( wxID_CANCEL, DIALOG_BOM_BASE::_wxFB_OnCancelClick )
EVT_BUTTON( ID_HELP, DIALOG_BOM_BASE::_wxFB_OnHelp )
EVT_BUTTON( ID_ADD_PLUGIN, DIALOG_BOM_BASE::_wxFB_OnAddPlugin )
EVT_BUTTON( wxID_BROWSE_PLUGINS, DIALOG_BOM_BASE::_wxFB_OnChoosePlugin )
EVT_BUTTON( ID_REMOVEL_PLUGIN, DIALOG_BOM_BASE::_wxFB_OnRemovePlugin )
EVT_BUTTON( wxID_ANY, DIALOG_BOM_BASE::_wxFB_OnEditPlugin )
EVT_TEXT( ID_CMDLINE, DIALOG_BOM_BASE::_wxFB_OnCommandLineEdited )
......@@ -72,9 +71,6 @@ DIALOG_BOM_BASE::DIALOG_BOM_BASE( wxWindow* parent, wxWindowID id, const wxStrin
m_buttonAddPlugin = new wxButton( this, ID_ADD_PLUGIN, _("Add Plugin"), wxDefaultPosition, wxDefaultSize, 0 );
bRightSizer->Add( m_buttonAddPlugin, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
m_buttonBrowsePlugin = new wxButton( this, wxID_BROWSE_PLUGINS, _("Set Plugin Cmd"), wxDefaultPosition, wxDefaultSize, 0 );
bRightSizer->Add( m_buttonBrowsePlugin, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
m_buttonDelPlugin = new wxButton( this, ID_REMOVEL_PLUGIN, _("Remove Plugin"), wxDefaultPosition, wxDefaultSize, 0 );
bRightSizer->Add( m_buttonDelPlugin, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
......@@ -103,6 +99,13 @@ DIALOG_BOM_BASE::DIALOG_BOM_BASE( wxWindow* parent, wxWindowID id, const wxStrin
bMainSizer->Add( bbottomSizer, 0, wxEXPAND, 5 );
m_staticTextInfo = new wxStaticText( this, wxID_ANY, _("Plugin Info:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextInfo->Wrap( -1 );
bMainSizer->Add( m_staticTextInfo, 0, wxRIGHT|wxLEFT, 5 );
m_Messages = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY );
bMainSizer->Add( m_Messages, 1, wxALL|wxEXPAND, 5 );
this->SetSizer( bMainSizer );
this->Layout();
......
This diff is collapsed.
......@@ -44,7 +44,6 @@ class DIALOG_BOM_BASE : public DIALOG_SHIM
void _wxFB_OnCancelClick( wxCommandEvent& event ){ OnCancelClick( event ); }
void _wxFB_OnHelp( wxCommandEvent& event ){ OnHelp( event ); }
void _wxFB_OnAddPlugin( wxCommandEvent& event ){ OnAddPlugin( event ); }
void _wxFB_OnChoosePlugin( wxCommandEvent& event ){ OnChoosePlugin( event ); }
void _wxFB_OnRemovePlugin( wxCommandEvent& event ){ OnRemovePlugin( event ); }
void _wxFB_OnEditPlugin( wxCommandEvent& event ){ OnEditPlugin( event ); }
void _wxFB_OnCommandLineEdited( wxCommandEvent& event ){ OnCommandLineEdited( event ); }
......@@ -57,7 +56,6 @@ class DIALOG_BOM_BASE : public DIALOG_SHIM
ID_CREATE_BOM,
ID_HELP,
ID_ADD_PLUGIN,
wxID_BROWSE_PLUGINS,
ID_REMOVEL_PLUGIN,
ID_CMDLINE
};
......@@ -71,11 +69,12 @@ class DIALOG_BOM_BASE : public DIALOG_SHIM
wxButton* m_buttonHelp;
wxStaticLine* m_staticline2;
wxButton* m_buttonAddPlugin;
wxButton* m_buttonBrowsePlugin;
wxButton* m_buttonDelPlugin;
wxButton* m_buttonEdit;
wxStaticText* m_staticTextCmd;
wxTextCtrl* m_textCtrlCommand;
wxStaticText* m_staticTextInfo;
wxTextCtrl* m_Messages;
// Virtual event handlers, overide them in your derived class
virtual void OnPluginSelected( wxCommandEvent& event ) { event.Skip(); }
......@@ -84,7 +83,6 @@ class DIALOG_BOM_BASE : public DIALOG_SHIM
virtual void OnCancelClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnHelp( wxCommandEvent& event ) { event.Skip(); }
virtual void OnAddPlugin( wxCommandEvent& event ) { event.Skip(); }
virtual void OnChoosePlugin( wxCommandEvent& event ) { event.Skip(); }
virtual void OnRemovePlugin( wxCommandEvent& event ) { event.Skip(); }
virtual void OnEditPlugin( wxCommandEvent& event ) { event.Skip(); }
virtual void OnCommandLineEdited( wxCommandEvent& event ) { event.Skip(); }
......@@ -92,7 +90,7 @@ class DIALOG_BOM_BASE : public DIALOG_SHIM
public:
DIALOG_BOM_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Bill of Material"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 404,315 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
DIALOG_BOM_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Bill of Material"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 409,393 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~DIALOG_BOM_BASE();
};
......
This diff is collapsed.
......@@ -381,7 +381,7 @@ bool SCH_EDIT_FRAME::WriteNetListFile( NETLIST_OBJECT_LIST * aConnectedItemsList
NETLIST_EXPORT_TOOL helper( aConnectedItemsList, Prj().SchLibs() );
bool open_file = aFormat < NET_TYPE_CUSTOM1;
bool open_file = (aFormat < NET_TYPE_CUSTOM1) && (aFormat >= 0);
if( (aFormat == NET_TYPE_PCBNEW) && (aNetlistOptions & NET_PCBNEW_USE_NEW_FORMAT ) )
open_file = false;
......@@ -390,7 +390,7 @@ bool SCH_EDIT_FRAME::WriteNetListFile( NETLIST_OBJECT_LIST * aConnectedItemsList
if( ( f = wxFopen( aFullFileName, wxT( "wt" ) ) ) == NULL )
{
wxString msg;
msg.Printf( _( "Failed to create file <%s>" ),
msg.Printf( _( "Failed to create file '%s'" ),
GetChars( aFullFileName ) );
DisplayError( this, msg );
return false;
......
......@@ -19,6 +19,14 @@
in the filename.
-->
<!--
@package
Generate a Tab delimited list (csv file type).
One component per line
Fields are
Ref,Value, Footprint, Datasheet, Field5, Field4, price
-->
<!DOCTYPE xsl:stylesheet [
<!ENTITY nl "&#xd;&#xa;"> <!--new line CR, LF, or LF, your choice -->
]>
......
......@@ -7,6 +7,14 @@
How to use:
Eeschema.pdf: chapter 14
-->
<!--
@package
Generate a comma separated value BOM list (csv file type).
Components are sorted by value
One component per line
Fields are
Quantity, 'Part name', Description, lib
-->
<!DOCTYPE xsl:stylesheet [
<!ENTITY nl "&#xd;&#xa;"> <!--new line CR, LF -->
......@@ -18,20 +26,18 @@
<!-- for each component -->
<xsl:template match="libpart">
<!--
<xsl:value-of select="count(//comp/libsource/@part[@part])"/><xsl:text>,</xsl:text>
-->
<xsl:value-of select="@part"/><xsl:text>,</xsl:text>
<xsl:value-of select="description"/><xsl:text>,</xsl:text>
<!-- -->
<xsl:value-of select="count(//comp/libsource/@part[@part])"/><xsl:text>,"</xsl:text>
<xsl:value-of select="@part"/><xsl:text>","</xsl:text>
<xsl:value-of select="description"/><xsl:text>","</xsl:text>
<xsl:value-of select="@lib"/>
<xsl:text>&nl;</xsl:text>
<xsl:text>"&nl;</xsl:text>
</xsl:template>
<xsl:template match="/export">
<xsl:text>qty,partname,description,lib&nl;</xsl:text>
<xsl:text>Qty,partname,description,lib&nl;</xsl:text>
<xsl:apply-templates select="libparts/libpart"/>
</xsl:template>
......
......@@ -90,9 +90,6 @@ BEGIN_EVENT_TABLE( GERBVIEW_FRAME, EDA_DRAW_FRAME )
EVT_MENU( wxID_HELP, EDA_DRAW_FRAME::GetKicadHelp )
EVT_MENU( wxID_ABOUT, EDA_DRAW_FRAME::GetKicadAbout )
EVT_TOOL( wxID_CUT, GERBVIEW_FRAME::Process_Special_Functions )
EVT_TOOL( wxID_COPY, GERBVIEW_FRAME::Process_Special_Functions )
EVT_TOOL( wxID_PASTE, GERBVIEW_FRAME::Process_Special_Functions )
EVT_TOOL( wxID_UNDO, GERBVIEW_FRAME::Process_Special_Functions )
EVT_TOOL( wxID_PRINT, GERBVIEW_FRAME::ToPrinter )
EVT_COMBOBOX( ID_TOOLBARH_GERBVIEW_SELECT_ACTIVE_LAYER,
......@@ -145,9 +142,6 @@ void GERBVIEW_FRAME::Process_Special_Functions( wxCommandEvent& event )
switch( id )
{
case wxID_CUT:
case wxID_COPY:
case ID_POPUP_DELETE_BLOCK:
case ID_POPUP_PLACE_BLOCK:
case ID_POPUP_ZOOM_BLOCK:
break;
......@@ -219,12 +213,6 @@ void GERBVIEW_FRAME::Process_Special_Functions( wxCommandEvent& event )
HandleBlockEnd( &dc );
break;
case ID_POPUP_DELETE_BLOCK:
GetScreen()->m_BlockLocate.SetCommand( BLOCK_DELETE );
GetScreen()->m_BlockLocate.SetMessageBlock( this );
HandleBlockEnd( &dc );
break;
default:
wxFAIL_MSG( wxT( "GERBVIEW_FRAME::Process_Special_Functions error" ) );
break;
......
......@@ -80,7 +80,7 @@ void GERBVIEW_FRAME::Files_io( wxCommandEvent& event )
break;
case ID_GERBVIEW_ERASE_ALL:
Clear_DrawLayers( true );
Clear_DrawLayers( false );
Zoom_Automatique( false );
m_canvas->Refresh();
ClearMsgPanel();
......
......@@ -24,7 +24,6 @@
#include <fctsys.h>
#include <class_drawpanel.h>
#include <confirm.h>
#include <id.h>
#include <gerbview.h>
......@@ -75,8 +74,6 @@ bool GERBVIEW_FRAME::OnRightClick( const wxPoint& aPosition, wxMenu* PopMenu )
PopMenu->AppendSeparator();
AddMenuItem( PopMenu, ID_POPUP_PLACE_BLOCK,
_( "Place Block" ), KiBitmap( checked_ok_xpm ) );
AddMenuItem( PopMenu, ID_POPUP_DELETE_BLOCK,
_( "Delete Block (ctrl + drag mouse)" ), KiBitmap( delete_xpm ) );
}
else
{
......
......@@ -71,7 +71,7 @@ enum DSN_SYNTAX_T {
/**
* Class DLEXER
* Class DSNLEXER
* implements a lexical analyzer for the SPECCTRA DSN file format. It
* reads lexical tokens from the current LINE_READER through the NextTok()
* function.
......@@ -215,6 +215,16 @@ public:
virtual ~DSNLEXER();
/**
* Useable only for DSN lexers which share the same LINE_READER
* Synchronizes the pointers handling the data read by the LINE_READER
* Allows 2 DNSLEXER to share the same current line, when switching from a
* DNSLEXER to an other DNSLEXER
* @param aLexer = the model
* @return true if the sync can be made ( at least the same line reader )
*/
bool SyncLineReaderWith( DSNLEXER& aLexer );
/**
* Function SetSpecctraMode
* changes the behavior of this lexer into or out of "specctra mode". If
......
......@@ -580,7 +580,10 @@ void D_PAD:: TransformShapeWithClearanceToPolygon( CPOLYGONS_LIST& aCornerBuffer
ClipperLib::Paths shapeWithClearance;
for( int ii = 0; ii < 4; ii++ )
{
corners[ii] += PadShapePos;
outline << ClipperLib::IntPoint( corners[ii].x, corners[ii].y );
}
ClipperLib::ClipperOffset offset_engine;
// Prepare an offset (inflate) transform, with edges connected by arcs
......@@ -600,19 +603,7 @@ void D_PAD:: TransformShapeWithClearanceToPolygon( CPOLYGONS_LIST& aCornerBuffer
offset_engine.Execute( shapeWithClearance, rounding_radius );
// get new outline (only one polygon is expected)
// For info, ClipperLib uses long long to handle integer coordinates
ClipperLib::Path& polygon = shapeWithClearance[0];
for( unsigned jj = 0; jj < polygon.size(); jj++ )
{
corner_position.x = int( polygon[jj].X );
corner_position.y = int( polygon[jj].Y );
corner_position += PadShapePos;
CPolyPt polypoint( corner_position.x, corner_position.y );
aCornerBuffer.Append( polypoint );
}
aCornerBuffer.CloseLastContour();
aCornerBuffer.ImportFrom( shapeWithClearance );
}
break;
}
......@@ -1008,7 +999,6 @@ void CreateThermalReliefPadPolygon( CPOLYGONS_LIST& aCornerBuffer,
double angle = aPad.GetOrientation();
int rounding_radius = KiROUND( aThermalGap * aCorrectionFactor ); // Corner rounding radius
double angle_pg; // Polygon increment angle
for( int i = 0; i < aCircleToSegmentsCount / 4 + 1; i++ )
{
......@@ -1016,7 +1006,7 @@ void CreateThermalReliefPadPolygon( CPOLYGONS_LIST& aCornerBuffer,
// Start at half increment offset
RotatePoint( &corner_position, 1800.0 / aCircleToSegmentsCount );
angle_pg = i * delta;
double angle_pg = i * delta;
RotatePoint( &corner_position, angle_pg ); // Rounding vector rotation
corner_position -= aPad.GetSize() / 2; // Rounding vector + Pad corner offset
......
......@@ -898,3 +898,14 @@ wxString ZONE_CONTAINER::GetSelectMenuText() const
return msg;
}
/* Copy polygons stored in aKiPolyList to m_FilledPolysList
* The previous m_FilledPolysList contents is replaced.
*/
void ZONE_CONTAINER::CopyPolygonsFromClipperPathsToFilledPolysList(
ClipperLib::Paths& aClipperPolyList )
{
m_FilledPolysList.RemoveAllContours();
m_FilledPolysList.ImportFrom( aClipperPolyList );
}
......@@ -305,6 +305,14 @@ public:
*/
void CopyPolygonsFromKiPolygonListToFilledPolysList( KI_POLYGON_SET& aKiPolyList );
/**
* Function CopyPolygonsFromClipperPathsToFilledPolysList
* Copy polygons stored in aKiPolyList to m_FilledPolysList
* The previous m_FilledPolysList contents is replaced.
* @param aClipperPolyList = a ClipperLib::Paths containing polygons.
*/
void CopyPolygonsFromClipperPathsToFilledPolysList( ClipperLib::Paths& aClipperPolyList );
/**
* Function CopyPolygonsFromFilledPolysListToKiPolygonList
* Copy polygons from m_FilledPolysList to aKiPolyList
......
......@@ -1938,14 +1938,39 @@ void EAGLE_PLUGIN::packageWire( MODULE* aModule, CPTREE& aTree ) const
wxPoint end( kicad_x( w.x2 ), kicad_y( w.y2 ) );
int width = kicad( w.width );
EDGE_MODULE* dwg = new EDGE_MODULE( aModule, S_SEGMENT );
aModule->GraphicalItems().PushBack( dwg );
EDGE_MODULE* dwg;
if( !w.curve )
{
dwg = new EDGE_MODULE( aModule, S_SEGMENT );
dwg->SetStart0( start );
dwg->SetEnd0( end );
dwg->SetStart0( start );
dwg->SetEnd0( end );
}
else
{
dwg = new EDGE_MODULE( aModule, S_ARC );
// Eagle give us start and end.
// S_ARC wants start to give the centre, and end to give the start
double dx = end.x - start.x, dy = end.y - start.y;
wxPoint mid = (start + end) / 2;
double dlen = sqrt( dx*dx + dy*dy );
double dist = dlen / ( 2 * tan( DEG2RAD( *w.curve ) / 2 ) );
wxPoint centre(
mid.x + dist * ( dy / dlen ),
mid.y - dist * ( dx / dlen )
);
dwg->SetStart0( centre );
dwg->SetEnd0( start );
dwg->SetAngle( *w.curve * -10.0 ); // KiCad rotates the other way
}
dwg->SetLayer( layer );
dwg->SetWidth( width );
aModule->GraphicalItems().PushBack( dwg );
}
}
......
......@@ -541,6 +541,9 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
break;
case ID_POPUP_PCB_DELETE_ZONE_CONTAINER:
// Force the main contour selection, to remove the entire zone:
((ZONE_CONTAINER*) GetCurItem())->SetSelectedCorner( 0 );
// Fall through
case ID_POPUP_PCB_DELETE_ZONE_CUTOUT:
m_canvas->MoveCursorToCrossHair();
{
......
......@@ -41,9 +41,7 @@
#include <class_module.h>
/**
* Function Tracks_and_Vias_Size_Event
* Event handler for tracks and vias size selection (and some options)
/* Event handler for tracks and vias size selection (and some options)
* relative to toolbars and popup events
*/
void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event )
......@@ -51,11 +49,11 @@ void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event )
int ii;
int id = event.GetId();
/* Note: none of these events require aborting the current command (if any)
* (like move, edit or block command)
* so we do not test for a current command in progress and call
* m_canvas->m_endMouseCaptureCallback( m_canvas, &dc );
*/
/* Note: none of these events require aborting the current command (if any)
* (like move, edit or block command)
* so we do not test for a current command in progress and call
* m_canvas->m_endMouseCaptureCallback( m_canvas, &dc );
*/
switch( id )
{
case ID_AUX_TOOLBAR_PCB_SELECT_AUTO_WIDTH:
......@@ -142,5 +140,7 @@ void PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event( wxCommandEvent& event )
}*/
//+hp
//Refresh canvas, that we can see changes instantly. I use this because it dont,t throw mouse up-left corner.
m_canvas->Refresh();
if( m_canvas->IsMouseCaptured() )
m_canvas->Refresh();
}
......@@ -126,6 +126,10 @@ static EDA_HOTKEY HkCanvasOpenGL( wxT( "Switch to OpenGL Canvas" ),
static EDA_HOTKEY HkCanvasCairo( wxT( "Switch to Cairo Canvas" ),
HK_CANVAS_CAIRO, WXK_F12 );
static EDA_HOTKEY HkZoneFillOrRefill( wxT( "Fill or Refill All Zones" ),
HK_ZONE_FILL_OR_REFILL, 'B' );
static EDA_HOTKEY HkZoneRemoveFilled( wxT( "Remove Filled Areas in All Zones" ),
HK_ZONE_REMOVE_FILLED, 'N' );
/* Fit on Screen */
#if !defined( __WXMAC__ )
static EDA_HOTKEY HkZoomAuto( wxT( "Zoom Auto" ), HK_ZOOM_AUTO, WXK_HOME );
......@@ -289,6 +293,7 @@ EDA_HOTKEY* board_edit_Hotkey_List[] =
&HkRecordMacros8, &HkCallMacros8, &HkRecordMacros9, &HkCallMacros9,
&HkSwitchHighContrastMode,
&HkCanvasDefault, &HkCanvasCairo, &HkCanvasOpenGL,
&HkZoneFillOrRefill, &HkZoneRemoveFilled,
NULL
};
......
......@@ -114,7 +114,9 @@ enum hotkey_id_commnand {
HK_CANVAS_OPENGL,
HK_CANVAS_CAIRO,
HK_LEFT_CLICK,
HK_LEFT_DCLICK
HK_LEFT_DCLICK,
HK_ZONE_FILL_OR_REFILL,
HK_ZONE_REMOVE_FILLED
};
// Full list of hotkey descriptors for board editor and footprint editor
......
......@@ -41,6 +41,7 @@
#include <pcbnew.h>
#include <pcbnew_id.h>
#include <hotkeys.h>
#include <class_zone.h>
/* How to add a new hotkey:
* see hotkeys.cpp
......@@ -566,6 +567,13 @@ bool PCB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotkeyCode, const wxPoint& aPosit
case HK_CANVAS_DEFAULT:
evt_type = ID_MENU_CANVAS_DEFAULT;
break;
case HK_ZONE_FILL_OR_REFILL:
evt_type = ID_POPUP_PCB_FILL_ALL_ZONES;
break;
case HK_ZONE_REMOVE_FILLED:
evt_type = ID_POPUP_PCB_REMOVE_FILLED_AREAS_IN_ALL_ZONES;
break;
}
if( evt_type != 0 )
......
......@@ -319,10 +319,14 @@ bool PCB_EDIT_FRAME::OnRightClick( const wxPoint& aMousePos, wxMenu* aPopMenu )
if( GetBoard()->m_ZoneDescriptorList.size() > 0 )
{
aPopMenu->AppendSeparator();
msg = AddHotkeyName( _( "Fill or Refill All Zones" ),
g_Board_Editor_Hokeys_Descr, HK_ZONE_FILL_OR_REFILL );
AddMenuItem( aPopMenu, ID_POPUP_PCB_FILL_ALL_ZONES,
_( "Fill or Refill All Zones" ), KiBitmap( fill_zone_xpm ) );
msg, KiBitmap( fill_zone_xpm ) );
msg = AddHotkeyName( _( "Remove Filled Areas in All Zones" ),
g_Board_Editor_Hokeys_Descr, HK_ZONE_REMOVE_FILLED );
AddMenuItem( aPopMenu, ID_POPUP_PCB_REMOVE_FILLED_AREAS_IN_ALL_ZONES,
_( "Remove Filled Areas in All Zones" ), KiBitmap( zone_unfill_xpm ) );
msg, KiBitmap( zone_unfill_xpm ) );
aPopMenu->AppendSeparator();
}
......
......@@ -1135,12 +1135,14 @@ void PCB_PARSER::parseSetup() throw( IO_ERROR, PARSE_ERROR )
{
PCB_PLOT_PARAMS plotParams;
PCB_PLOT_PARAMS_PARSER parser( reader );
// parser must share the same current line as our current PCB parser
// synchronize it.
parser.SyncLineReaderWith( *this );
plotParams.Parse( &parser );
m_board->SetPlotOptions( plotParams );
SyncLineReaderWith( parser );
// I don't know why but this seems to fix a problem in PCB_PLOT_PARAMS::Parse().
NextTok();
m_board->SetPlotOptions( plotParams );
}
break;
......
......@@ -22,7 +22,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <wx/wx.h>
//#include <wx/wx.h>
#include <pcb_plot_params_parser.h>
#include <pcb_plot_params.h>
#include <layers_id_colors_and_visibility.h>
......
......@@ -773,12 +773,25 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
zone->TransformOutlinesShapeWithClearanceToPolygon( bufferPolys,
inflate, true );
zone->TransformOutlinesShapeWithClearanceToPolygon( initialPolys,
0, true );
}
// To avoid a lot of code, use a ZONE_CONTAINER
// to handle and plot polygons, because our polygons look exactly like
// filled areas in zones
// Note, also this code is not optimized: it creates a lot of copy/duplicate data
// However it is not complex, and fast enough for plot purposes (copy/convert data
// is only a very small calculation time for these calculations)
ZONE_CONTAINER zone( aBoard );
zone.SetArcSegmentCount( 32 );
zone.SetMinThickness( 0 ); // trace polygons only
zone.SetLayer ( layer );
// Now:
// 1 - merge areas which are intersecting, i.e. remove gaps
// 1 - merge polygons which are intersecting, i.e. remove gaps
// having a thickness < aMinThickness
// 2 - deflate resulting areas by aMinThickness/2
// 2 - deflate resulting polygons by aMinThickness/2
KI_POLYGON_SET areasToMerge;
bufferPolys.ExportTo( areasToMerge );
KI_POLYGON_SET initialAreas;
......@@ -788,29 +801,44 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
// = aMinThickness/2, shapes too close ( dist < aMinThickness )
// will be merged, because they are overlapping
KI_POLYGON_SET areas;
areas |= areasToMerge;
areas |= areasToMerge; // Populates with merged polygons
// Deflate: remove the extra margin, to create the actual shapes
// Here I am using polygon:resize, because this function creates better shapes
// than deflate algo.
// Use here deflate with arc creation and 18 segments per circle to create arcs
// In boost polygon (at least v 1.54 and previous) in very rare cases resize crashes
// with 16 segments (perhaps related to 45 degrees pads). So using 18 segments
// is a workaround to try to avoid these crashes
areas = resize( areas, -inflate , true, 18 );
// Resize slightly changes shapes. So *ensure* initial shapes are kept
// Use here deflate made by Clipper, because:
// Clipper is (by far) faster and better, event using arcs to deflate shapes
// boost::polygon < 1.56 polygon resize function sometimes crashes when deflating using arcs
// boost::polygon >=1.56 polygon resize function just does not work
// Note also we combine polygons using boost::polygon, which works better than Clipper,
// especially with zones using holes linked to main outlines by overlapping segments
CPOLYGONS_LIST tmp;
tmp.ImportFrom( areas );
// Deflate area using Clipper, better than boost::polygon
ClipperLib::Paths areasDeflate;
tmp.ExportTo( areasDeflate );
// Deflate areas: they will have the right size after deflate
ClipperLib::ClipperOffset offset_engine;
circleToSegmentsCount = 16;
offset_engine.ArcTolerance = (double)inflate / 3.14 / circleToSegmentsCount;
offset_engine.AddPaths( areasDeflate, ClipperLib::jtRound, ClipperLib::etClosedPolygon );
offset_engine.Execute( areasDeflate, -inflate );
// Combine the current areas to initial areas. This is mandatory because
// inflate/deflate transform is not perfect, and we want the initial areas perfectly kept
tmp.RemoveAllContours();
tmp.ImportFrom( areasDeflate );
areas.clear();
tmp.ExportTo( areas );
// Resize slightly changes shapes (the transform is not perfect).
// So *ensure* initial shapes are kept
areas |= initialAreas;
// To avoid a lot of code, use a ZONE_CONTAINER
// to plot polygons, because they are exactly like
// filled areas in zones
ZONE_CONTAINER zone( aBoard );
zone.SetArcSegmentCount( 32 );
zone.SetMinThickness( 0 ); // trace polygons only
zone.SetLayer ( layer );
zone.CopyPolygonsFromKiPolygonListToFilledPolysList( areas );
itemplotter.PlotFilledAreas( &zone );
}
......
......@@ -29,7 +29,6 @@
*/
#include <fctsys.h>
//#include <pgm_base.h>
#include <kiface_i.h>
#include <class_drawpanel.h>
#include <confirm.h>
......
......@@ -13,7 +13,7 @@ from sys import argv,exit
if len(argv)<2:
print "usage:"
print " fixswigimports.py file.py"
print " fix_swig_imports.py file.py"
print ""
print " will fix the swig import code for working inside KiCad"
print " where it happended that the external _pcbnew.so/dll was"
......@@ -52,7 +52,7 @@ if doneOk:
print "swig_import_helper fixed for",filename
else:
print "Error: the swig import helper was not fixed, check",filename
print " and fix this script: fixswigimports.py"
print " and fix this script: fix_swig_imports.py"
exit(2)
......
bom_?.py are some python scripts which read a generic xml netlist from eeschema,
and create a bom.
All examples use ky_generic_netlist_reader.py, which is a python utility to read
All examples use ky_netlist_reader.py, which is a python utility to read
and parse this generic xml netlist and create the corresponding data
used to build the bom.
......@@ -12,3 +12,27 @@ python bom_example?.py <netlist name> <bom list netname>
See Eeschema doc, chapter 14 for info about the generic xml netlist format,
and how to run a script from Eeschema to create a customized netlist or BOM.
If the python comment
"""
@package
some comments
"""
is added to the begining of the python script, the comment will be displayed
in Eescheam, in the BOM dialog
For instance:
"""
@package
Generate a HTML BOM list.
Components are sorted and grouped by value
Fields are (if exist)
Ref, Quantity, Value, Part, Datasheet, Description, Vendor
"""
displays:
Generate a HTML BOM list.
Components are sorted and grouped by value
Fields are (if exist)
Ref, Quantity, Value, Part, Datasheet, Description, Vendor
in BOM dialog
......@@ -4,6 +4,15 @@
# Example: Sorted and Grouped HTML BOM with more advanced grouping
#
"""
@package
Generate a HTML BOM list.
Components are sorted and grouped by value
Fields are (if exist)
Ref, Quantity, Value, Part, Datasheet, Description, Vendor
"""
from __future__ import print_function
# Import the KiCad python helper module and the csv formatter
......@@ -74,8 +83,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1])
try:
f = open(sys.argv[2], 'w')
except IOError:
e = "Can't open output file for writing: " + sys.argv[2]
print(__file__, ":", e, file=sys.stderr)
f = stdout
f = sys.stdout
# Output a set of rows for a header providing general information
html = html.replace('<!--SOURCE-->', net.getSource())
......
#
# Example python script to generate a BOM from a KiCad generic netlist
#
# Example: Tab delimited list (The same as std output) Ungrouped
#
"""
@package
Generate a csv list file.
Components are sorted by ref and grouped by value
One component per line
Fields are (if exist)
Ref, Quantity, value, Part, footprint, 'Description', 'Vendor'
"""
from __future__ import print_function
......@@ -20,8 +26,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1])
try:
f = open(sys.argv[2], 'w')
except IOError:
print(__file__, ":", e, file=sys.stderr)
f = stdout
e = "Can't open output file for writing: " + sys.argv[2]
print(__file__, ":", e, sys.stderr)
f = sys.stdout
# Create a new csv writer object to use as the output formatter, although we
# are created a tab delimited list instead!
......
......@@ -4,6 +4,15 @@
# Example: Ungrouped (One component per row) CSV output
#
"""
@package
Generate a csv list file.
Components are sorted by ref and grouped by value
One component per line
Fields are (if exist)
Ref, value, Part, footprint, Datasheet, Manufacturer, Vendor
"""
from __future__ import print_function
# Import the KiCad python helper module
......@@ -20,8 +29,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1])
try:
f = open(sys.argv[2], 'w')
except IOError:
print(__file__, ":", e, file=sys.stderr)
f = stdout
e = "Can't open output file for writing: " + sys.argv[2]
print( __file__, ":", e, sys.stderr )
f = sys.stdout
# Create a new csv writer object to use as the output formatter
out = csv.writer(f, lineterminator='\n', delimiter=',', quotechar="\"", quoting=csv.QUOTE_ALL)
......
......@@ -27,7 +27,7 @@ try:
f = open(sys.argv[2], 'w')
except IOError:
e = "Can't open output file for writing: " + sys.argv[2]
print(__file__, ":", e, file=sys.stderr)
print( __file__, ":", e, sys.stderr )
f = sys.stdout
# subset the components to those wanted in the BOM, controlled
......@@ -46,7 +46,7 @@ columnset = compfields | partfields # union
columns = ['Item', 'Qty', 'Reference(s)', 'Value', 'LibPart', 'Footprint', 'Datasheet'] + sorted(list(columnset))
# Create a new csv writer object to use as the output formatter
out = csv.writer(f, lineterminator='\n', delimiter=',', quotechar='\"', quoting=csv.QUOTE_MINIMAL)
out = csv.writer( f, lineterminator='\n', delimiter=',', quotechar='\"', quoting=csv.QUOTE_MINIMAL )
# override csv.writer's writerow() to support utf8 encoding:
def writerow( acsvwriter, columns ):
......
#
# Example python script to generate a BOM from a KiCad generic netlist
#
# Example: Sorted and Grouped CSV BOM
#
"""
@package
Generate a Tab delimited list (csv file type).
Components are sorted by ref and grouped by value
Fields are (if exist)
'Ref', 'Qnty', 'Value', 'Sch lib name', 'footprint', 'Description', 'Vendor'
"""
# Import the KiCad python helper module and the csv formatter
import kicad_netlist_reader
import csv
import sys
# Generate an instance of a generic netlist, and load the netlist tree from
# the command line option. If the file doesn't exist, execution will stop
net = kicad_netlist_reader.netlist(sys.argv[1])
# Open a file to write to, if the file cannot be opened output to stdout
# instead
try:
f = open(sys.argv[2], 'w')
except IOError:
e = "Can't open output file for writing: " + sys.argv[2]
print(__file__, ":", e, sys.stderr)
f = sys.stdout
# Create a new csv writer object to use as the output formatter
out = csv.writer(f, lineterminator='\n', delimiter=',', quotechar='\"', quoting=csv.QUOTE_ALL)
# Output a set of rows for a header providing general information
out.writerow(['Source:', net.getSource()])
out.writerow(['Date:', net.getDate()])
out.writerow(['Tool:', net.getTool()])
out.writerow(['Component Count:', len(net.components)])
out.writerow(['Ref', 'Qnty', 'Value', 'Sch lib name', 'footprint', 'Description', 'Vendor'])
# Get all of the components in groups of matching parts + values
# (see ky_generic_netlist_reader.py)
grouped = net.groupComponents()
# Output all of the component information
for group in grouped:
refs = ""
# Add the reference of every component in the group and keep a reference
# to the component so that the other data can be filled in once per group
for component in group:
refs += component.getRef() + ", "
c = component
# Fill in the component groups common data
out.writerow([refs, len(group), c.getValue(), c.getLibName() + "/" + c.getPartName(), c.getFootprint(),
c.getDescription(), c.getField("Vendor")])
......@@ -4,6 +4,15 @@
# Example: Sorted and Grouped HTML BOM with more advanced grouping
#
"""
@package
Generate a HTML BOM list.
Components are sorted and grouped by ref
Fields are (if exist)
Ref, Quantity, Value, Part, Datasheet, Description, Vendor
"""
from __future__ import print_function
# Import the KiCad python helper module and the csv formatter
......@@ -74,8 +83,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1])
try:
f = open(sys.argv[2], 'w')
except IOError:
print(__file__, ":", e, file=sys.stderr)
f = stdout
e = "Can't open output file for writing: " + sys.argv[2]
print( __file__, ":", e, sys.stderr )
f = sys.stdout
components = net.getInterestingComponents()
......
......@@ -3,6 +3,13 @@
#
# Example: Sorted and Grouped HTML BOM
#
"""
@package
Generate a HTML BOM list.
Components are sorted by ref and grouped by value
Fields are (if exist)
Ref, Quantity, Value, Part, Datasheet, Description, Vendor
"""
from __future__ import print_function
......@@ -39,8 +46,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1])
try:
f = open(sys.argv[2], 'w')
except IOError:
e = "Can't open output file for writing: " + sys.argv[2]
print(__file__, ":", e, file=sys.stderr)
f = stdout
f = sys.stdout
components = net.getInterestingComponents()
......@@ -51,7 +59,8 @@ html = html.replace('<!--TOOL-->', net.getTool())
html = html.replace('<!--COMPCOUNT-->', "<b>Component Count:</b>" + \
str(len(components)))
row = "<tr><th style='width:640px'>Ref</th>" + "<th>Qnty</th>"
row = "<tr><th style='width:640px'>Ref</th>"
row += "<th>Qnty</th>"
row += "<th>Value</th>" + "<th>Part</th>" + "<th>Datasheet</th>"
row += "<th>Description</th>" + "<th>Vendor</th></tr>"
......@@ -74,10 +83,11 @@ for group in grouped:
c = component
row = "<tr><td>" + refs +"</td><td>" + str(len(group))
row += "</td><td>" + c.getValue() + "</td><td>" + c.getLibName() + ":"
row += c.getPartName() + "</td><td>" + c.getDatasheet() + "</td><td>"
row += c.getDescription() + "</td><td>" + c.getField("Vendor")
row += "</td></tr>"
row += "</td><td>" + c.getValue()
row += "</td><td>" + c.getLibName() + ":" + c.getPartName()
row += "</td><td>" + c.getDatasheet()
row += "</td><td>" + c.getDescription()
row += "</td><td>" + c.getField("Vendor")+ "</td></tr>"
html = html.replace('<!--TABLEROW-->', row + "<!--TABLEROW-->")
......
......@@ -7,6 +7,15 @@
# is due to be deprecated in 3.0+ soon
#
"""
@package
Generate a HTML BOM list.
Components are sorted and grouped by value
Fields are (if exist)
Ref, Quantity, Value, Part, Datasheet, Description, Vendor
"""
from __future__ import print_function
import sys
import xml.sax as sax
......
......@@ -21,7 +21,8 @@ net = kicad_netlist_reader.netlist(sys.argv[1])
try:
f = open(sys.argv[2], 'w')
except IOError:
print( __file__, ":", e, file=sys.stderr)
f = stdout
e = "Can't open output file for writing: " + sys.argv[2]
print( __file__, ":", e, sys.stderr)
f = sys.stdout
print(net.formatXML(), file=f)
......@@ -64,8 +64,9 @@ net = kicad_netlist_reader.netlist(sys.argv[1])
try:
f = open(sys.argv[2], 'w')
except IOError:
e = "Can't open output file for writing: " + sys.argv[2]
print(__file__, ":", e, file=sys.stderr)
f = stdout
f = sys.stdout
for c in net.components:
c.checkvalue()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment