boxespy/boxes/generators/keypad.py

137 lines
4.9 KiB
Python

"""Generator for keypads with mechanical switches."""
from copy import deepcopy
from boxes import Boxes, boolarg
from boxes.edges import FingerJointSettings
from .keyboard import Keyboard
class Keypad(Boxes, Keyboard):
"""Generator for keypads with mechanical switches."""
ui_group = 'Box'
btn_size = 15.6
space_between_btn = 4
box_padding = 10
triangle = 25.0
def __init__(self):
super().__init__()
self.argparser.add_argument(
'--h', action='store', type=int, default=30,
help='height of the box'
)
self.argparser.add_argument(
'--top1_thickness', action='store', type=float, default=1.5,
help=('thickness of the button hold layer, cherry like switches '
'need 1.5mm or smaller to snap in')
)
self.argparser.add_argument(
'--top2_enable', action='store', type=boolarg, default=False,
help=('enables another top layer that can hold CPG151101S11 '
'hotswap sockets')
)
self.argparser.add_argument(
'--top2_thickness', action='store', type=float, default=1.5,
help=('thickness of the hotplug layer, CPG151101S11 hotswap '
'sockets need 1.2mm to 1.5mm')
)
# Add parameter common with other keyboard projects
self.add_common_keyboard_parameters(
# Hotswap already depends on top2_enable setting, a second parameter
# for it would be useless
add_hotswap_parameter=False,
# By default, 3 columns of 4 rows
default_columns_definition="4x3"
)
self.addSettingsArgs(FingerJointSettings, surroundingspaces=1)
def _get_x_y(self):
"""Gets the keypad's size based on the number of buttons."""
spacing = self.btn_size + self.space_between_btn
border = 2*self.box_padding - self.space_between_btn
x = len(self.columns_definition) * spacing + border
y = max(offset + keys * spacing for (offset, keys) in self.columns_definition) + border
return x, y
def render(self):
"""Renders the keypad."""
# deeper edge for top to add multiple layers
deep_edge = deepcopy(self.edges['f'].settings)
deep_edge.thickness = self.thickness + self.top1_thickness
if self.top2_enable:
deep_edge.thickness += self.top2_thickness
deep_edge.edgeObjects(self, 'gGH', True)
d1, d2 = 2., 3.
x, y = self._get_x_y()
h = self.h
# box sides
self.rectangularWall(x, h, "GFEF", callback=[self.wallx_cb], move="right")
self.rectangularWall(y, h, "GfEf", callback=[self.wally_cb], move="up")
self.rectangularWall(y, h, "GfEf", callback=[self.wally_cb])
self.rectangularWall(x, h, "GFEF", callback=[self.wallx_cb], move="left up")
# keypad lids
self.rectangularWall(x, y, "ffff", callback=self.to_grid_callback(self.support_hole), move="right")
self.rectangularWall(x, y, "ffff", callback=self.to_grid_callback(self.key_hole), move="up")
if self.top2_enable:
self.rectangularWall(x, y, "ffff", callback=self.to_grid_callback(self.hotplug))
# screwable
tr = self.triangle
trh = tr / 3
self.rectangularWall(
x, y,
callback=[lambda: self.hole(trh, trh, d=d2)] * 4,
move='left up'
)
self.rectangularTriangle(
tr, tr, "ffe", num=4,
callback=[None, lambda: self.hole(trh, trh, d=d1)]
)
def to_grid_callback(self, inner_callback):
def callback():
# move to first key center
key_margin = self.box_padding + self.btn_size / 2
self.moveTo(key_margin, key_margin)
self.apply_callback_on_columns(
inner_callback, self.columns_definition, self.btn_size + self.space_between_btn
)
return [callback]
def hotplug(self):
"""Callback for the key stabelizers."""
self.pcb_holes(
with_pcb_mount=self.pcb_mount_enable,
with_diode=self.diode_enable,
with_led=self.led_enable,
)
def support_hole(self):
self.configured_plate_cutout(support=True)
def key_hole(self):
self.configured_plate_cutout()
# stolen form electronics-box
def wallx_cb(self):
"""Callback for triangle holes on x-side."""
x, _ = self._get_x_y()
t = self.thickness
self.fingerHolesAt(0, self.h - 1.5 * t, self.triangle, 0)
self.fingerHolesAt(x, self.h - 1.5 * t, self.triangle, 180)
# stolen form electronics-box
def wally_cb(self):
"""Callback for triangle holes on y-side."""
_, y = self._get_x_y()
t = self.thickness
self.fingerHolesAt(0, self.h - 1.5 * t, self.triangle, 0)
self.fingerHolesAt(y, self.h - 1.5 * t, self.triangle, 180)