kicad/pcbnew/scripting/plugins/HelpfulFootprintWizardPlugi...

251 lines
7.8 KiB
Python

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
#
import pcbnew
import FootprintWizardDrawingAids
class FootprintWizardParameterManager:
"""
Functions for helpfully managing parameters to a KiCAD Footprint
Wizard.
Abstracts away from whatever structure is used by pcbnew's footprint
wizard class
"""
def __init__(self):
self.parameters = {}
self.GenerateParameterList()
def GenerateParameterList(self):
"""
Construct parameters here, or leave out to have no parameters
"""
pass
def CheckParameters(self):
"""
Implement this to make checks on parameter values, filling
parameter_errors (or using the checker routines)
Subclasses can implment their own and override the parent
defaults and add new ones
"""
pass
uMM = 1
uMils = 2
uNatural = 3
uBool = 4
def AddParam(self, section, param, unit, default, hint = ''):
"""
Add a parameter with some properties.
TODO: Hints are not supported, as there is as yet nowhere to
put them in the KiCAD interface
"""
val = None
if unit == self.uMM:
val = pcbnew.FromMM(default)
elif unit == self.uMils:
val = pcbnew.FromMils(default)
elif unit == self.uNatural:
val = default
elif unit == self.uBool:
val = "True" if default else "False" #ugly stringing
else:
print "Warning: Unknown unit type: %s" % unit
return
if unit in [self.uNatural, self.uBool]:
param = "*%s" % param #star prefix for natural
if section not in self.parameters:
self.parameters[section] = {}
self.parameters[section][param] = val
def _PrintParameterTable(self):
"""
Pretty-print the parameters we have
"""
for name, section in self.parameters.iteritems():
print " %s:" % name
for key, value in section.iteritems():
unit = ""
if (type(value) is int or type(value) is float) and not "*" in key:
unit = "mm"
if "*" in key:
key = key[1:]
else:
value = pcbnew.ToMM(value)
print " %s: %s%s" % (key, value, unit)
def _ParametersHaveErrors(self):
"""
Return true if we discovered errors suring parameter processing
"""
for name, section in self.parameter_errors.iteritems():
for k, v in section.iteritems():
if v:
return True
return False
def _PrintParameterErrors(self):
"""
Pretty-print parameters with errors
"""
for name, section in self.parameter_errors.iteritems():
printed_section = False
for key, value in section.iteritems():
if value:
if not printed_section:
print " %s:" % name
print " %s: %s (have %s)" % (key, value,
self.parameters[name][key])
def ProcessParameters(self):
"""
Make sure the parameters we have meet whatever expectations the
footprint wizard has of them
"""
self.ClearErrors()
self.CheckParameters();
if self._ParametersHaveErrors():
print "Cannot build footprint: Parameters have errors:"
self._PrintParameterErrors()
return False
print "Building new %s footprint with the following parameters:" % self.name
self._PrintParameterTable()
return True
#################################################################
# PARAMETER CHECKERS
#################################################################
def CheckParamPositiveInt(self, section, param, min_value = 1,
max_value = None, is_multiple_of = 1):
"""
Make sure a parameter can be made into an int, and enforce
limits if required
"""
try:
self.parameters[section][param] = int(self.parameters[section][param])
except ValueError:
self.parameter_errors[section][param] = "Must be a valid integer"
return
if min_value is not None and (self.parameters[section][param] < min_value):
self.parameter_errors[section][param] = "Must be greater than or equal to %d" % (min_value)
return
if max_value is not None and (self.parameters[section][param] > min_value):
self.parameter_errors[section][param] = "Must be less than or equal to %d" % (max_value)
return
if is_multiple_of > 1 and (self.parameters[section][param] % is_multiple_of) > 0:
self.parameter_errors[section][param] = "Must be a multiple of %d" % is_multiple_of
return
return
def CheckParamBool(self, section, param):
"""
Make sure a parameter looks like a boolean, convert to native
boolean type if so
"""
if str(self.parameters[section][param]).lower() in ["true", "t", "y", "yes", "on", "1", "1.0"]:
self.parameters[section][param] = True;
return
elif str(self.parameters[section][param]).lower() in ["false", "f", "n", "no", "off", "0", "0.0"]:
self.parameters[section][param] = False;
return
self.parameter_errors[section][param] = "Must be boolean (true/false)"
return
class HelpfulFootprintWizardPlugin(pcbnew.FootprintWizardPlugin,
FootprintWizardParameterManager):
"""
A class to simplify many aspects of footprint creation, leaving only
the foot-print specific routines to the wizards themselves
Generally, you need to implement:
GetReference()
GetValue()
GenerateParameterList()
CheckParameters()
BuildThisFootprint()
GetName()
GetDescription()
"""
def __init__(self):
pcbnew.FootprintWizardPlugin.__init__(self)
FootprintWizardParameterManager.__init__(self)
self.name = self.GetName()
self.decription = self.GetDescription()
self.image = self.GetImage()
def GetReference(self):
raise NotImplementedError
def GetValuePrefix(self):
return "U" # footprints needing wizards of often ICs
def GetImage(self):
return ""
def BuildThisFootprint(self):
raise NotImplementedError
def BuildFootprint(self):
"""
Actually make the footprint. We defer all but the setup to
the implmenting class
"""
if not self.ProcessParameters():
return
self.module = pcbnew.MODULE(None) # create a new module
self.draw = FootprintWizardDrawingAids.FootprintWizardDrawingAids(self.module)
self.module.SetReference(self.GetReference())
self.module.SetValue("%s**" % self.GetValuePrefix())
fpid = pcbnew.FPID(self.module.GetReference()) #the name in library
self.module.SetFPID( fpid )
self.BuildThisFootprint() # implementer's build function