Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds encoder type with a circle (50% border radius) drawing style #64

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions KEYMAP_SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ This field provides information about the physical layout of the keyboard, i.e.,

1. **QMK `info.json` `layout` specification**:
This is the [official QMK format](https://docs.qmk.fm/#/reference_info_json?id=layout-format) for physical key descriptions
that every `info.json` file in the QMK firmware repository uses. `keymap-drawer` only uses the `x`, `y`, `r`, `rx` and `ry` fields.
that every `info.json` file in the QMK firmware repository uses.
`keymap-drawer` only uses the `x`, `y`, `w`, `h`, `r`, `rx` and `ry` fields.
The `x, y, w, h` specifies the key location and size (width, height) in `1u` units,
with `r` indicating the key rotation in degrees, centered at `rx, ry`.
Note that `keymap-editor` utilizes [the same format](https://github.com/nickcoutsos/keymap-editor/wiki/Defining-keyboard-layouts) for `info.json`.

QMK spec also lets you specify multiple "layouts" per keyboard corresponding to different layout macros to support physical variations.
Expand All @@ -37,10 +40,22 @@ This field provides information about the physical layout of the keyboard, i.e.,
visualize a given JSON definition, re-order keys using the "Re-order" tool and generate one from scratch from various formats such as KLE or Kicad
PCBs using the "Import" tool.

Alternatively you can write QMK layout inline with the `qmk_info` parameter
according to the official schema or a simple of key specs. For example:

```yaml
layout:
qmk_info: [
{x: 1, y: 0}, {x: 2, y: 0}, {x: 3, y: 0},
{x: 0, y: 1}, {x: 1, y: 1}, {x: 2, y: 1}, {x: 3, y: 1, h: 2},
...
]
```

Note that the behavior of the layout helper and `keymap-drawer` differs for rotated keys when omitting `rx`, `ry` parameters --
`keymap-drawer` assumes rotation around the key center and layout helper assumes rotation around the top left of the key.
For this reason it is recommended to explicitly specify `rx`, `ry` fields if `r` is specified. You might also want to omit the fields
besides `x`, `y`, `r`, `rx` and `ry` in your final JSON since they won't be used by `keymap-drawer`.
besides `x`, `y`, `w`, `h`, `r`, `rx` and `ry` in your final JSON since they won't be used by `keymap-drawer`.

2. **Parametrized ortholinear layouts**:
This lets you specify parameters to automatically generate a split or non-split ortholinear layout.
Expand Down Expand Up @@ -98,7 +113,7 @@ A `LayoutKey` can be defined with either a string value or with a mapping with t
| `tap (t)` | `str` | `""` | the tap action of a key, drawn on the center of the key; spaces will be converted to line breaks[^2] |
| `hold (h)` | `str` | `""` | the hold action of a key, drawn on the bottom of the key |
| `shifted (s)` | `str` | `""` | the "shifted" action of a key, drawn on the top of the key |
| `type` | `str` | `""` | the styling of the key that corresponds to the [SVG class](CONFIGURATION.md#svg_style)[^3]. predefined types are `held` (a red shading to denote held down keys), `ghost` (dashed outline to denote optional keys in a layout), `trans` (lighter text for transparent keys) |
| `type` | `str` | `""` | the styling of the key that corresponds to the [SVG class](CONFIGURATION.md#svg_style)[^3]. predefined types are `held` (a red shading to denote held down keys), `ghost` (dashed outline to denote optional keys in a layout), `trans` (lighter text for transparent keys), and `encoder` (circled outline) |

[^2]: You can prevent line breaks by using double spaces `" "` to denote a single non-breaking space.
[^3]: Text styling can be overridden in the SVG config using the `"tap"`, `"hold"` and `"shifted"` classes if desired.
Expand Down
16 changes: 16 additions & 0 deletions examples/tidbit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
layout:
qmk_info: [
{x: 1, y: 0}, {x: 2, y: 0}, {x: 3, y: 0},
{x: 0, y: 1}, {x: 1, y: 1}, {x: 2, y: 1}, {x: 3, y: 1, h: 2},
{x: 0, y: 2}, {x: 1, y: 2}, {x: 2, y: 2}, # ^^ double height
{x: 0, y: 3}, {x: 1, y: 3}, {x: 2, y: 3}, {x: 3, y: 3, h: 2},
{x: 0, y: 4, w: 2}, {x: 2, y: 4} # ^^ double height
]

layers:
default:
- [ {tap: Esc, type: encoder}, '*', '-']
- ['7', '8', '9', '+']
- ['4', '5', '6']
- ['1', '2', '3', Enter]
- ['0', '.']
5 changes: 5 additions & 0 deletions keymap_drawer/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ class KeySidePars(BaseModel):
stroke-width: 2;
}

rect.encoder {
rx: 50%;
ry: 50%;
}

text {
text-anchor: middle;
dominant-baseline: middle;
Expand Down
11 changes: 6 additions & 5 deletions keymap_drawer/physical_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,26 +162,27 @@ def __rmul__(self, other: int | float) -> "PhysicalLayout":
return PhysicalLayout(keys=[other * k for k in self.keys])


def layout_factory(
def layout_factory( # pylint: disable=too-many-arguments
config: DrawConfig,
qmk_keyboard: str | None = None,
qmk_info_json: Path | None = None,
qmk_info: dict | None = None,
qmk_layout: str | None = None,
ortho_layout: dict | None = None,
) -> PhysicalLayout:
"""Create and return a physical layout, as determined by the combination of arguments passed."""
if len([arg for arg in (qmk_keyboard, qmk_info_json, ortho_layout) if arg is not None]) != 1:
if len([arg for arg in (qmk_keyboard, qmk_info_json, qmk_info, ortho_layout) if arg is not None]) != 1:
raise ValueError(
'Please provide exactly one of "qmk_keyboard", "qmk_info_json" or "ortho_layout" specs for physical layout'
)

if qmk_keyboard or qmk_info_json:
if qmk_keyboard or qmk_info_json or qmk_info:
if qmk_keyboard:
qmk_info = _get_qmk_info(qmk_keyboard, config.use_local_cache)
else: # qmk_info_json
assert qmk_info_json is not None
elif qmk_info_json:
with open(qmk_info_json, "rb") as f:
qmk_info = json.load(f)
assert qmk_info is not None

if isinstance(qmk_info, list):
assert qmk_layout is None, "Cannot use qmk_layout with a list-format QMK spec"
Expand Down