Skip to content

Commit 043feca

Browse files
authored
Merge pull request #3 from sparkfun/release_candidate
v1.1.0
2 parents 54a2f7d + eb28631 commit 043feca

File tree

8 files changed

+1140
-814
lines changed

8 files changed

+1140
-814
lines changed

SparkFunKiCadPanelizer/dialog/dialog.py

Lines changed: 151 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ def get_version(rel_path: str) -> str:
3131

3232
_APP_VERSION = get_version("_version.py")
3333

34+
def get_btn_bitmap(bitmap):
35+
path = resource_path(bitmap)
36+
png = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)
37+
return wx.BitmapBundle(png)
38+
3439
def ParseFloat(InputString, DefaultValue=0.0):
3540
value = DefaultValue
3641
if InputString != "":
@@ -40,9 +45,35 @@ def ParseFloat(InputString, DefaultValue=0.0):
4045
print("Value not valid")
4146
return value
4247

43-
class Dialog(dialog_text_base.DIALOG_TEXT_BASE):
48+
class Dialog(dialog_text_base.DialogPanelBase):
49+
def __init__(self, parent, config, layertable, ordering, panelizer, func):
50+
51+
dialog_text_base.DialogPanelBase.__init__(self, None)
52+
53+
self.panel = DialogPanel(self, config, layertable, ordering, panelizer, func)
54+
55+
best_size = self.BestSize
56+
# hack for some gtk themes that incorrectly calculate best size
57+
best_size.IncBy(dx=0, dy=30)
58+
self.SetClientSize(best_size)
59+
60+
self.SetTitle(_APP_NAME + " - " + _APP_VERSION)
61+
62+
# hack for new wxFormBuilder generating code incompatible with old wxPython
63+
# noinspection PyMethodOverriding
64+
def SetSizeHints(self, sz1, sz2):
65+
try:
66+
# wxPython 4
67+
super(Dialog, self).SetSizeHints(sz1, sz2)
68+
except TypeError:
69+
# wxPython 3
70+
self.SetSizeHintsSz(sz1, sz2)
4471

72+
class DialogPanel(dialog_text_base.DialogPanel):
4573
# The names of the config items need to match the names in dialog_text_base minus the m_
74+
# - except for vScoreLayer
75+
vscore_layer = 'vScoreLayer'
76+
default_vscore_layer = 'User.Comments'
4677
config_defaults = {
4778
'dimensionsInchesBtn': 'true',
4879
'dimensionsMmBtn': 'false',
@@ -55,19 +86,18 @@ class Dialog(dialog_text_base.DIALOG_TEXT_BASE):
5586
'removeRightVerticalCheck': 'false',
5687
'productionBordersCheck': 'false',
5788
'productionFiducialsCheck': 'false',
58-
'productionExposeCheck': 'false'
89+
'productionExposeCheck': 'false',
90+
vscore_layer: default_vscore_layer
5991
}
6092

61-
def __init__(self, parent, config, ordering, panelizer, func):
62-
dialog_text_base.DIALOG_TEXT_BASE.__init__(self, parent)
63-
64-
# hack for some gtk themes that incorrectly calculate best size
65-
#best_size = self.BestSize
66-
#best_size.IncBy(dx=0, dy=30)
67-
#self.SetClientSize(best_size)
93+
def __init__(self, parent, config, layertable, ordering, panelizer, func):
6894

95+
dialog_text_base.DialogPanel.__init__(self, parent)
96+
6997
self.config_file = config
7098

99+
self.layertable = layertable
100+
71101
self.ordering_instructions = ordering
72102

73103
self.panelizer = panelizer
@@ -76,8 +106,25 @@ def __init__(self, parent, config, ordering, panelizer, func):
76106

77107
self.error = None
78108

79-
self.SetTitle(_APP_NAME + " - " + _APP_VERSION)
80-
109+
self.general = GeneralPanel(self.notebook)
110+
self.vscore = VScorePanel(self.notebook)
111+
self.notebook.AddPage(self.general, "General")
112+
self.notebook.AddPage(self.vscore, "V-Score")
113+
114+
# Delete any existing rows in LayersGrid
115+
if self.vscore.LayersGrid.NumberRows:
116+
self.vscore.LayersGrid.DeleteRows(0, self.vscore.LayersGrid.NumberRows)
117+
# Append empty rows based on layertable
118+
self.vscore.LayersGrid.AppendRows(len(self.layertable))
119+
# Initialize them
120+
row = 0
121+
for layer in self.layertable.keys():
122+
self.vscore.LayersGrid.SetCellValue(row, 0, "0") # JSON style
123+
self.vscore.LayersGrid.SetCellRenderer(row, 0, wx.grid.GridCellBoolRenderer())
124+
self.vscore.LayersGrid.SetCellValue(row, 1, layer)
125+
self.vscore.LayersGrid.SetReadOnly(row, 1)
126+
row += 1
127+
81128
self.loadConfig()
82129

83130
def loadConfig(self):
@@ -108,34 +155,110 @@ def LoadSettings(self, params):
108155
if value is None:
109156
continue
110157

111-
try:
112-
obj = getattr(self, "m_{}".format(key))
113-
if hasattr(obj, "SetValue"):
114-
obj.SetValue(value)
115-
elif hasattr(obj, "SetStringSelection"):
116-
obj.SetStringSelection(value)
117-
else:
118-
raise Exception("Invalid item")
119-
except Exception as e:
120-
pass
158+
if self.vscore_layer in key:
159+
defaultLayerFound = False
160+
for row in range(self.vscore.LayersGrid.GetNumberRows()):
161+
if value in self.vscore.LayersGrid.GetCellValue(row, 1):
162+
b = "1"
163+
defaultLayerFound = True
164+
else:
165+
b = "0"
166+
self.vscore.LayersGrid.SetCellValue(row, 0, b)
167+
if not defaultLayerFound:
168+
self.vscore.LayersGrid.SetCellValue(0, 0, "1") # Default to the first layer
169+
else:
170+
try:
171+
obj = getattr(self.general, "m_{}".format(key))
172+
if hasattr(obj, "SetValue"):
173+
obj.SetValue(value)
174+
elif hasattr(obj, "SetStringSelection"):
175+
obj.SetStringSelection(value)
176+
else:
177+
raise Exception("Invalid item")
178+
except Exception as e:
179+
pass
180+
121181
return params
122182

123183
def CurrentSettings(self):
124184
params = {}
125185

126186
for item in self.config_defaults.keys():
127-
obj = getattr(self, "m_{}".format(item))
128-
if hasattr(obj, "GetValue"):
129-
params.update({item: obj.GetValue()})
130-
elif hasattr(obj, "GetStringSelection"):
131-
params.update({item: obj.GetStringSelection()})
187+
if self.vscore_layer in item:
188+
for row in range(self.vscore.LayersGrid.GetNumberRows()):
189+
if self.vscore.LayersGrid.GetCellValue(row, 0) == "1":
190+
params.update({self.vscore_layer: self.vscore.LayersGrid.GetCellValue(row, 1)})
132191
else:
133-
raise Exception("Invalid item")
192+
obj = getattr(self.general, "m_{}".format(item))
193+
if hasattr(obj, "GetValue"):
194+
params.update({item: obj.GetValue()})
195+
elif hasattr(obj, "GetStringSelection"):
196+
params.update({item: obj.GetStringSelection()})
197+
else:
198+
raise Exception("Invalid item")
199+
134200
return params
135201

136202
def OnPanelizeClick(self, e):
137203
self.saveConfig()
138204
self.func(self, self.panelizer)
139205

140206
def OnCancelClick(self, e):
141-
self.EndModal(wx.ID_CANCEL)
207+
self.GetParent().EndModal(wx.ID_CANCEL)
208+
209+
class GeneralPanel(dialog_text_base.GeneralPanelBase):
210+
211+
def __init__(self, parent):
212+
dialog_text_base.GeneralPanelBase.__init__(self, parent)
213+
214+
self.m_buttonFiducialsHelp.SetLabelText("")
215+
# Icon by Icons8 https://icons8.com : https://icons8.com/icon/63308/info
216+
self.m_buttonFiducialsHelp.SetBitmap(get_btn_bitmap("info-15.png"))
217+
218+
self.m_buttonEdgeHelp.SetLabelText("")
219+
# Icon by Icons8 https://icons8.com : https://icons8.com/icon/63308/info
220+
self.m_buttonEdgeHelp.SetBitmap(get_btn_bitmap("info-15.png"))
221+
222+
def ClickFiducialsHelp( self, event ):
223+
wx.MessageBox("\
224+
By default, the panel fiducials are placed in\n\
225+
the top and bottom edges. Normally we\n\
226+
recommend leaving them there.\n\
227+
\n\
228+
Selecting this option moves them to the left\n\
229+
and right edges.\n\
230+
\n\
231+
This can be useful when using horizontal gaps\n\
232+
and vertical v-scores. It avoids the panel\n\
233+
having to be scrapped if an edge has been\n\
234+
snapped off and the fiducials are missing.\
235+
", 'Info', wx.OK | wx.ICON_INFORMATION)
236+
237+
def ClickEdgeHelp( self, event ):
238+
wx.MessageBox("\
239+
Select this option if you are panelizing\n\
240+
a MicroMod Processor or Function Board.\n\
241+
\n\
242+
The bottom and top edges will be exposed\n\
243+
so the fingers and chamfered edge can be\n\
244+
manufactured. The top row of PCBs is\n\
245+
rotated automatically.\
246+
", 'Info', wx.OK | wx.ICON_INFORMATION)
247+
248+
class VScorePanel(dialog_text_base.VScorePanelBase):
249+
250+
def __init__(self, parent):
251+
dialog_text_base.VScorePanelBase.__init__(self, parent)
252+
253+
self.Layout()
254+
self.LayersGrid.SetColSize(0, 50)
255+
self.LayersGrid.SetColSize(1, self.GetParent().GetClientSize().x - 80)
256+
257+
def OnLayersGridCellClicked(self, event):
258+
self.LayersGrid.ClearSelection()
259+
#self.LayersGrid.SelectRow(event.Row)
260+
if event.Col == 0:
261+
for row in range(self.LayersGrid.GetNumberRows()):
262+
val = "1" if (row == event.Row) else "0" # JSON style
263+
self.LayersGrid.SetCellValue(row, 0, val)
264+

0 commit comments

Comments
 (0)