summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gerbonara/cad/protoboard.py4
-rw-r--r--gerbonara/cad/protoserve.py30
-rw-r--r--gerbonara/cad/protoserve_data/protoserve.html24
3 files changed, 46 insertions, 12 deletions
diff --git a/gerbonara/cad/protoboard.py b/gerbonara/cad/protoboard.py
index a3d616f..b61a0ed 100644
--- a/gerbonara/cad/protoboard.py
+++ b/gerbonara/cad/protoboard.py
@@ -116,6 +116,10 @@ class PropLayout:
return [ unit(leftover * (value or 1.0) / sum_props if not isinstance(value, str) else calculated, MM)
for value, calculated in zip(self.proportions, out) ]
+ @property
+ def single_sided(self):
+ return all(elem.single_sided for elem in self.content)
+
def __str__(self):
children = ', '.join( f'{elem}:{width}' for elem, width in zip(self.content, self.proportions))
return f'PropLayout[{self.direction.upper()}]({children})'
diff --git a/gerbonara/cad/protoserve.py b/gerbonara/cad/protoserve.py
index b594196..a210e91 100644
--- a/gerbonara/cad/protoserve.py
+++ b/gerbonara/cad/protoserve.py
@@ -41,12 +41,21 @@ def deserialize(obj, unit):
pitch_y = float(obj.get('pitch_y', 1.27))
clearance = float(obj.get('clearance', 0.2))
+ mil = lambda x: x/1000 if unit == Inch else x
+
match obj['type']:
case 'layout':
+ if not obj.get('children'):
+ return pb.EmptyProtoArea()
+
proportions = [float(child['layout_prop']) for child in obj['children']]
content = [deserialize(child, unit) for child in obj['children']]
return pb.PropLayout(content, obj['direction'], proportions)
+ case 'twoside':
+ top, bottom = obj['children']
+ return pb.TwoSideLayout(deserialize(top, unit), deserialize(bottom, unit))
+
case 'placeholder':
return pb.EmptyProtoArea()
@@ -59,7 +68,7 @@ def deserialize(obj, unit):
return pb.PatternProtoArea(pitch_x, pitch_y, obj=pad, unit=unit)
case 'tht':
- hole_dia = float(obj['hole_dia'])
+ hole_dia = mil(float(obj['hole_dia']))
match obj['plating']:
case 'plated':
oneside, plated = False, True
@@ -85,16 +94,16 @@ def deserialize(obj, unit):
return pb.PatternProtoArea(pitch_x, pitch_y, obj=pb.ManhattanPads(pitch_x, pitch_y, clearance, unit=unit), unit=unit)
case 'powered':
- pitch = float(obj.get('pitch', 2.54))
- hole_dia = float(obj['hole_dia'])
- via_drill = float(obj['via_hole_dia'])
- trace_width = float(obj['trace_width'])
+ pitch = mil(float(obj.get('pitch', 2.54)))
+ hole_dia = mil(float(obj['hole_dia']))
+ via_drill = mil(float(obj['via_hole_dia']))
+ trace_width = mil(float(obj['trace_width']))
return pb.PatternProtoArea(pitch, pitch, pb.PoweredProto(pitch, hole_dia, clearance, via_size=via_drill, trace_width=trace_width, unit=unit), unit=unit)
case 'flower':
- pitch = float(obj.get('pitch', 2.54))
- hole_dia = float(obj['hole_dia'])
- pattern_dia = float(obj['pattern_dia'])
+ pitch = mil(float(obj.get('pitch', 2.54)))
+ hole_dia = mil(float(obj['hole_dia']))
+ pattern_dia = mil(float(obj['pattern_dia']))
return pb.PatternProtoArea(2*pitch, 2*pitch, pb.THTFlowerProto(pitch, hole_dia, pattern_dia, unit=unit), unit=unit)
case 'rf':
@@ -113,7 +122,10 @@ def to_board(obj):
mounting_hole_dia = float(holes.get('diameter', unit(3.2, MM)))
mounting_hole_offset = float(holes.get('offset', unit(5, MM)))
- content = deserialize(obj['children'][0], unit)
+ if obj.get('children'):
+ content = deserialize(obj['children'][0], unit)
+ else:
+ content = [pb.EmptyProtoArea()]
return pb.ProtoBoard(w, h, content,
corner_radius=corner_radius,
diff --git a/gerbonara/cad/protoserve_data/protoserve.html b/gerbonara/cad/protoserve_data/protoserve.html
index 7bc9a30..3afeb5c 100644
--- a/gerbonara/cad/protoserve_data/protoserve.html
+++ b/gerbonara/cad/protoserve_data/protoserve.html
@@ -15,6 +15,7 @@ html, body {
margin: 0;
width: 100%;
height: 100%;
+ font-family: Helvetica, Segoe UI, Sans-Serif;
}
body {
@@ -161,6 +162,7 @@ input {
#preview {
grid-area: main;
+ padding: 20px;
}
#preview-image {
@@ -171,6 +173,18 @@ input {
#links {
grid-area: links;
+ display: flex;
+ justify-content: center;
+ padding: 5px;
+}
+
+#link-gerbers {
+ background-color: #0d6efd;
+ color: white;
+ font-weight: bold;
+ box-shadow: 0px 0px 1px 1px hsl(0, 0%, 0% / 20%);
+ border-radius: .5em;
+ padding: 1em 2em 1em 2em;
}
.layout-area {
@@ -203,6 +217,10 @@ input {
color: hsl(0 0% 60%);
}
+.narrow-only {
+ display: none;
+}
+
</style>
</head>
<body>
@@ -266,8 +284,8 @@ input {
<img id="preview-image" alt="Automatically generated preview image"/>
</div>
<div id="links">
- <a href="#controls">Settings</a>
- <a href="#preview">Preview</a>
+ <a class="narrow-only" href="#controls">Settings</a>
+ <a class="narrow-only" href="#preview">Preview</a>
<a id="link-gerbers" href='#'>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="1em">
<title>Download</title>
@@ -313,7 +331,7 @@ input {
</template>
<template id="tpl-g-twoside">
- <div class="group split-sides">
+ <div data-type='twoside' class="group split-sides">
<h4>Split front and back</h4>
<span class="content area-controls">(<a href="#" class="area-remove">Remove</a><a href="#" class="area-move">Move</a>)</span>
<label class="proportion">Proportion