Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
0e9a35ec4e | |||
f463d67b9d |
.envrcflake.lockflake.nix
.gitea/workflows
Cargo.lockCargo.nixCargo.tomlTaskfile.ymlauthdb
bike-lights
bike/src
case
bike-light-enclosure.scadclasp.scadcommon.scadcontrol_panel.scadcontrol_panel_case.scadcontrol_panel_lid.scadcontrol_panel_slider.scad
core/src
simulator
config/src
coordinates/src
crate-hashes.jsoncyber-slides
cyberpunk-splash
cyberpunk
dashboard/src
emseries
file-service
fitnesstrax
app
core
fluent-ergonomics/src
gm-control-panel/src
gm-dash/server/src
hex-grid/src
ifc
l10n-db
memorycache/src
nom-training/src
otg
core/src
gtk/src
pwa
pico-dotstar-pulsation
pico-st7789
@ -1,31 +0,0 @@
|
|||||||
name: Monorepo build
|
|
||||||
run-name: ${{ gitea.actor }} is testing out Gitea Actions
|
|
||||||
on: [push]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
# Explore-Gitea-Actions:
|
|
||||||
# runs-on: native
|
|
||||||
# steps:
|
|
||||||
# - run: echo "The job was automatically triggered by a ${{ gitea.event_name }} event."
|
|
||||||
# - run: echo "This job is now running on ${{ runner.os }} server hosted by Gitea!"
|
|
||||||
# - run: echo "The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
|
|
||||||
# - name: Check out repository code
|
|
||||||
# uses: actions/checkout@v4
|
|
||||||
# - run: echo "The ${{ gitea.repository }} repository has been cloned to the runner."
|
|
||||||
# - run: echo "The workflow is now ready to test your code on the runner."
|
|
||||||
# - name: List files in the repository
|
|
||||||
# run: |
|
|
||||||
# ls ${{ gitea.workspace }}
|
|
||||||
# - run: echo "This job's status is ${{ job.status }}."
|
|
||||||
|
|
||||||
build-flake:
|
|
||||||
runs-on: nixos
|
|
||||||
defaults.run.working-directory: ${{ gitea.workspace }}
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Build the apps
|
|
||||||
run: /run/current-system/sw/bin/nix --extra-experimental-features "nix-command flakes" build .#all
|
|
||||||
- name: Check the end of the build
|
|
||||||
run: ls ${{ gitea.workspace }}/result/bin
|
|
||||||
|
|
4691
Cargo.lock
generated
4691
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
96
Cargo.toml
96
Cargo.toml
@ -1,74 +1,34 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
members = [
|
members = [
|
||||||
# "authdb",
|
"authdb",
|
||||||
# "bike-lights/core",
|
"bike-lights/bike",
|
||||||
# "bike-lights/simulator",
|
"bike-lights/core",
|
||||||
# "changeset",
|
"bike-lights/simulator",
|
||||||
# "config",
|
"changeset",
|
||||||
# "config-derive",
|
"config",
|
||||||
# "coordinates",
|
"config-derive",
|
||||||
# "cyber-slides",
|
"coordinates",
|
||||||
"cyberpunk",
|
|
||||||
"cyberpunk-splash",
|
"cyberpunk-splash",
|
||||||
# "dashboard",
|
"dashboard",
|
||||||
# "emseries",
|
"emseries",
|
||||||
# "file-service",
|
"file-service",
|
||||||
|
"fitnesstrax/core",
|
||||||
"fitnesstrax/app",
|
"fitnesstrax/app",
|
||||||
# "fitnesstrax/core",
|
"fluent-ergonomics",
|
||||||
# "fluent-ergonomics",
|
"geo-types",
|
||||||
# "geo-types",
|
"gm-control-panel",
|
||||||
# "gm-control-panel",
|
"hex-grid",
|
||||||
# "gm-dash/server",
|
"icon-test",
|
||||||
# "hex-grid",
|
"ifc",
|
||||||
# "icon-test",
|
"memorycache",
|
||||||
"l10n-db",
|
"nom-training",
|
||||||
# "memorycache",
|
"otg/core",
|
||||||
# "nom-training",
|
"otg/gtk",
|
||||||
# "otg/core",
|
"result-extended",
|
||||||
# "otg/gtk",
|
"screenplay",
|
||||||
# "pico-st7789",
|
"sgf",
|
||||||
# "result-extended",
|
"timezone-testing",
|
||||||
# "screenplay",
|
"tree",
|
||||||
# "sgf",
|
"visions/server", "gm-dash/server",
|
||||||
# "timezone-testing",
|
|
||||||
# "tree",
|
|
||||||
"visions/server",
|
|
||||||
# "visions/types",
|
|
||||||
"visions/ui",
|
|
||||||
# "bike-lights/bike",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.dependencies]
|
|
||||||
adw = { version = "0.5", package = "libadwaita", features = [ "v1_4" ] }
|
|
||||||
async-channel = { version = "2.1" }
|
|
||||||
async-std = { version = "1.13" }
|
|
||||||
async-trait = { version = "0.1" }
|
|
||||||
axum = { version = "0.8", features = ["macros"] }
|
|
||||||
cairo-rs = { version = "0.18" }
|
|
||||||
chrono = { version = "0.4" }
|
|
||||||
chrono-tz = { version = "0.8" }
|
|
||||||
dimensioned = { version = "0.8", features = [ "serde" ] }
|
|
||||||
gdk = { version = "0.7", package = "gdk4" }
|
|
||||||
gio = { version = "0.18" }
|
|
||||||
glib = { version = "0.18" }
|
|
||||||
gloo-console = { version = "0.3.0" }
|
|
||||||
gloo-net = { version = "0.6.0" }
|
|
||||||
gtk = { version = "0.7", package = "gtk4", features = [ "v4_10" ] }
|
|
||||||
serde = { version = "1.0", features = ["derive", "serde_derive"] }
|
|
||||||
serde-wasm-bindgen = { version = "0.6.5" }
|
|
||||||
serde_json = { version = "1.0.138" }
|
|
||||||
thiserror = { version = "2.0" }
|
|
||||||
tokio = { version = "1.43", features = ["full", "rt"] }
|
|
||||||
tower-http = { version = "0.6", features = ["cors"] }
|
|
||||||
uuid = { version = "1.13", features = ["v4"] }
|
|
||||||
wasm-bindgen = { version = "0.2.100" }
|
|
||||||
wasm-bindgen-futures = { version = "0.4.50" }
|
|
||||||
web-sys = { version = "0.3.77" }
|
|
||||||
yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] }
|
|
||||||
|
|
||||||
# cairo-rs = { version = "0.18" }
|
|
||||||
# gio = { version = "0.18" }
|
|
||||||
# glib = { version = "0.18" }
|
|
||||||
# gtk = { version = "0.7", package = "gtk4" }
|
|
||||||
|
|
||||||
|
20
Taskfile.yml
20
Taskfile.yml
@ -1,20 +0,0 @@
|
|||||||
version: '3'
|
|
||||||
|
|
||||||
tasks:
|
|
||||||
build:
|
|
||||||
cmds:
|
|
||||||
- cargo build --release
|
|
||||||
|
|
||||||
update:
|
|
||||||
cmds:
|
|
||||||
- task build
|
|
||||||
- crate2nix generate
|
|
||||||
- nix build
|
|
||||||
|
|
||||||
lint:
|
|
||||||
cmds:
|
|
||||||
- cargo clippy
|
|
||||||
|
|
||||||
test:
|
|
||||||
cmds:
|
|
||||||
- cargo test
|
|
@ -18,7 +18,7 @@ base64ct = { version = "1", features = [ "alloc" ] }
|
|||||||
clap = { version = "4", features = [ "derive" ] }
|
clap = { version = "4", features = [ "derive" ] }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
sha2 = { version = "0.10" }
|
sha2 = { version = "0.10" }
|
||||||
sqlx = { version = "0.8", features = [ "runtime-tokio", "sqlite" ] }
|
sqlx = { version = "0.7", features = [ "runtime-tokio", "sqlite" ] }
|
||||||
thiserror = { version = "1" }
|
thiserror = { version = "1" }
|
||||||
tokio = { version = "1", features = [ "full" ] }
|
tokio = { version = "1", features = [ "full" ] }
|
||||||
uuid = { version = "0.4", features = [ "serde", "v4" ] }
|
uuid = { version = "0.4", features = [ "serde", "v4" ] }
|
||||||
|
@ -119,7 +119,6 @@ impl<
|
|||||||
> UI for BikeUI<D, P, LeftId, RightId, PreviousId, NextId, BrakeId>
|
> UI for BikeUI<D, P, LeftId, RightId, PreviousId, NextId, BrakeId>
|
||||||
{
|
{
|
||||||
fn check_event(&mut self, current_time: Instant) -> Option<Event> {
|
fn check_event(&mut self, current_time: Instant) -> Option<Event> {
|
||||||
/*
|
|
||||||
if self.brake_sensor.is_high().unwrap_or(true) && !self.brake_enabled {
|
if self.brake_sensor.is_high().unwrap_or(true) && !self.brake_enabled {
|
||||||
self.brake_enabled = true;
|
self.brake_enabled = true;
|
||||||
Some(Event::Brake)
|
Some(Event::Brake)
|
||||||
@ -127,8 +126,6 @@ impl<
|
|||||||
self.brake_enabled = false;
|
self.brake_enabled = false;
|
||||||
Some(Event::BrakeRelease)
|
Some(Event::BrakeRelease)
|
||||||
} else if self.left_blinker_button.is_low(current_time) {
|
} else if self.left_blinker_button.is_low(current_time) {
|
||||||
*/
|
|
||||||
if self.left_blinker_button.is_low(current_time) {
|
|
||||||
self.left_blinker_button.set_debounce(current_time);
|
self.left_blinker_button.set_debounce(current_time);
|
||||||
Some(Event::LeftBlinker)
|
Some(Event::LeftBlinker)
|
||||||
} else if self.right_blinker_button.is_low(current_time) {
|
} else if self.right_blinker_button.is_low(current_time) {
|
||||||
|
@ -1,174 +0,0 @@
|
|||||||
width = 65;
|
|
||||||
length = 75;
|
|
||||||
height = 16;
|
|
||||||
wall_thickness = 2;
|
|
||||||
guide_thickness = 1;
|
|
||||||
power_width = 21;
|
|
||||||
output_width = 37.5;
|
|
||||||
half_wall_thickness = wall_thickness / 2;
|
|
||||||
standoff_thickness = 10;
|
|
||||||
hole_diameter = 3;
|
|
||||||
// The radius of a nut in mm. However, based on my measurements, I'm not actually sure I have this right. The short height of a nut is 7.86mm. Derive from there.
|
|
||||||
nut_radius = 8.5 * cos(30) / 2;
|
|
||||||
nut_height = 2.69; // mm
|
|
||||||
screw_radius = 2;
|
|
||||||
handlebar_radius = 15;
|
|
||||||
clasp_thickness = 4;
|
|
||||||
clasp_width = 35;
|
|
||||||
circular_face_count = 48;
|
|
||||||
|
|
||||||
module hexagon(r, h) {
|
|
||||||
pi = 3.1415926;
|
|
||||||
polyhedron(
|
|
||||||
points=[
|
|
||||||
[r, 0, 0],
|
|
||||||
[r * cos(60), r * sin(60), 0],
|
|
||||||
[r * cos(120), r * sin(120), 0],
|
|
||||||
[r * cos(180), r * sin(180), 0],
|
|
||||||
[r * cos(240), r * sin(240), 0],
|
|
||||||
[r * cos(300), r * sin(300), 0],
|
|
||||||
|
|
||||||
[r, 0, h],
|
|
||||||
[r * cos(60), r * sin(60), h],
|
|
||||||
[r * cos(120), r * sin(120), h],
|
|
||||||
[r * cos(180), r * sin(180), h],
|
|
||||||
[r * cos(240), r * sin(240), h],
|
|
||||||
[r * cos(300), r * sin(300), h],
|
|
||||||
],
|
|
||||||
faces=[
|
|
||||||
[0, 1, 2, 3, 4, 5],
|
|
||||||
[11, 10, 9, 8, 7, 6],
|
|
||||||
[6, 7, 1, 0],
|
|
||||||
[7, 8, 2, 1],
|
|
||||||
[8, 9, 3, 2],
|
|
||||||
[9, 10, 4, 3],
|
|
||||||
[10, 11, 5, 4],
|
|
||||||
[11, 6, 0, 5],
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nut holders are blocks that have a hole drilled through them and a hexagonal-shaped cavity. The idea is to
|
|
||||||
module nut_holder() {
|
|
||||||
difference() {
|
|
||||||
translate([-4.5, -4.5, -2]) cube([9, 9, 4]);
|
|
||||||
union() {
|
|
||||||
translate([0, 0, -1]) hexagon(nut_radius, 2);
|
|
||||||
cylinder(h = 6, r = screw_radius, center = true, $fn = 24);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module screw_hole() {
|
|
||||||
union() {
|
|
||||||
translate([0, 0, 4]) cylinder(h = 2.1, r = screw_radius * 2, center = true, $fn = 24);
|
|
||||||
cylinder(h = 6, r = screw_radius, center = true, $fn = 24);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module base() {
|
|
||||||
cube([width, length, wall_thickness]);
|
|
||||||
}
|
|
||||||
|
|
||||||
module face() {
|
|
||||||
union() {
|
|
||||||
cube([width, length, wall_thickness / 2]);
|
|
||||||
translate([wall_thickness, wall_thickness, wall_thickness / 2]) cube([width-wall_thickness*2, length-wall_thickness*2, wall_thickness / 2]);
|
|
||||||
translate([4.5 + wall_thickness, 4.5 + wall_thickness, 4]) nut_holder();
|
|
||||||
translate([width - 4.5 - wall_thickness, 4.5 + wall_thickness, 4]) nut_holder();
|
|
||||||
translate([width - 4.5 - wall_thickness, length - 4.5 - wall_thickness, 4]) nut_holder();
|
|
||||||
translate([4.5 + wall_thickness, length - 4.5 - wall_thickness, 4]) nut_holder();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module wall(length) {
|
|
||||||
cube([length, height, wall_thickness]);
|
|
||||||
}
|
|
||||||
|
|
||||||
module power_wall() {
|
|
||||||
difference() {
|
|
||||||
wall(65);
|
|
||||||
translate([9, 2, -.5]) cube([power_width, height, wall_thickness + 1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module output_wall() {
|
|
||||||
difference() {
|
|
||||||
wall(65);
|
|
||||||
translate([9, 2, -.5]) cube([output_width, height, wall_thickness + 1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use hexagons as cutouts into which I can install a hex nut. This isn't quite right yet, but close.
|
|
||||||
// hexagon(nut_radius, 1);
|
|
||||||
|
|
||||||
// cube([standoff_thickness, standoff_thickness, 2]);
|
|
||||||
|
|
||||||
/*
|
|
||||||
difference() {
|
|
||||||
union() {
|
|
||||||
base();
|
|
||||||
rotate([90, 0, 90]) wall(75);
|
|
||||||
// translate([width - wall_thickness, 0, 0]) rotate([90, 0, 90]) wall(length);
|
|
||||||
// rotate([90, 0, 0]) power_wall();
|
|
||||||
// translate([0, length, 0]) rotate([90, 0, 0]) output_wall();
|
|
||||||
// translate([wall_thickness,
|
|
||||||
// wall_thickness,
|
|
||||||
// wall_thickness]) standoff();
|
|
||||||
// translate([width - wall_thickness - standoff_thickness,
|
|
||||||
// wall_thickness,
|
|
||||||
// wall_thickness]) standoff();
|
|
||||||
// translate([wall_thickness,
|
|
||||||
// length - wall_thickness - standoff_thickness,
|
|
||||||
// wall_thickness]) standoff();
|
|
||||||
// translate([width - wall_thickness - standoff_thickness,
|
|
||||||
// length - wall_thickness - standoff_thickness,
|
|
||||||
// wall_thickness]) standoff();
|
|
||||||
}
|
|
||||||
// translate([-half_wall_thickness, -wall_thickness - half_wall_thickness, height - half_wall_thickness]) cube([wall_thickness, length + wall_thickness * 2, wall_thickness]);
|
|
||||||
// translate([width - half_wall_thickness, -wall_thickness - half_wall_thickness, height - half_wall_thickness]) cube([wall_thickness, length + wall_thickness * 2, wall_thickness]);
|
|
||||||
// translate([-half_wall_thickness, -half_wall_thickness, height - half_wall_thickness]) rotate([0, 0, 270]) cube([wall_thickness, width + wall_thickness * 2, wall_thickness]);
|
|
||||||
// translate([-half_wall_thickness, length + half_wall_thickness, height - half_wall_thickness]) rotate([0, 0, 270]) cube([wall_thickness, width + wall_thickness * 2, wall_thickness]);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
module box() {
|
|
||||||
difference() {
|
|
||||||
union() {
|
|
||||||
cube([width, length, wall_thickness * 2]);
|
|
||||||
translate([0, 0, wall_thickness]) rotate([90, 0, 90]) wall(length);
|
|
||||||
translate([width - wall_thickness, 0, wall_thickness]) rotate([90, 0, 90]) wall(length);
|
|
||||||
translate([0, wall_thickness, wall_thickness]) rotate([90, 0, 0]) wall(width);
|
|
||||||
translate([0, length, wall_thickness]) rotate([90, 0, 0]) wall(width);
|
|
||||||
}
|
|
||||||
translate([4.5 + wall_thickness, 4.5 + wall_thickness, 4]) rotate([180, 0, 0]) screw_hole();
|
|
||||||
translate([width - 4.5 - wall_thickness, 4.5 + wall_thickness, 4]) rotate([180, 0, 0]) screw_hole();
|
|
||||||
translate([width - 4.5 - wall_thickness, length - 4.5 - wall_thickness, 4]) rotate([180, 0, 0]) screw_hole();
|
|
||||||
translate([4.5 + wall_thickness, length - 4.5 - wall_thickness, 4]) rotate([180, 0, 0]) screw_hole();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module top_clasp() {
|
|
||||||
difference() {
|
|
||||||
union() {
|
|
||||||
cylinder(h = clasp_width, r = handlebar_radius + clasp_thickness, center = true, $fn = circular_face_count);
|
|
||||||
translate([0, 0, -clasp_width / 2]) cylinder(h = 1, r = handlebar_radius + clasp_thickness + 1, center = true, $fn = circular_face_count);
|
|
||||||
translate([0, 0, -clasp_width / 2 + 4]) cylinder(h = 1, r = handlebar_radius + clasp_thickness + 1, center = true, $fn = circular_face_count);
|
|
||||||
translate([0, 0, clasp_width / 2]) cylinder(h = 1, r = handlebar_radius + clasp_thickness + 1, center = true, $fn = circular_face_count);
|
|
||||||
translate([0, 0, clasp_width / 2 - 4]) cylinder(h = 1, r = handlebar_radius + clasp_thickness + 1, center = true, $fn = circular_face_count);
|
|
||||||
translate([-handlebar_radius-5, -10, -clasp_width / 2 + 6]) cube([6, 20, clasp_width - 12]);
|
|
||||||
}
|
|
||||||
translate([-0.5, 0, 0]) cylinder(h = clasp_width+2, r = handlebar_radius + 1, center = true, $fn = circular_face_count);
|
|
||||||
translate([-0.5, -handlebar_radius - 10, -clasp_width / 2 - 1]) cube([handlebar_radius + 10, handlebar_radius * 2 + 20, clasp_width + 2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module body() {
|
|
||||||
union() {
|
|
||||||
box();
|
|
||||||
translate([width / 2, length / 2, -5 - handlebar_radius]) rotate([0, 90, 90]) top_clasp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body();
|
|
||||||
translate([width + 10, 0, 0]) face();
|
|
@ -1,21 +0,0 @@
|
|||||||
handlebar_radius = 15;
|
|
||||||
clasp_thickness = 4;
|
|
||||||
circular_face_count = 48;
|
|
||||||
clasp_width = 35;
|
|
||||||
|
|
||||||
module top_clasp() {
|
|
||||||
difference() {
|
|
||||||
union() {
|
|
||||||
cylinder(h = clasp_width, r = handlebar_radius + clasp_thickness, center = true, $fn = circular_face_count);
|
|
||||||
translate([0, 0, -clasp_width / 2]) cylinder(h = 1, r = handlebar_radius + clasp_thickness + 1, center = true, $fn = circular_face_count);
|
|
||||||
translate([0, 0, -clasp_width / 2 + 4]) cylinder(h = 1, r = handlebar_radius + clasp_thickness + 1, center = true, $fn = circular_face_count);
|
|
||||||
translate([0, 0, clasp_width / 2]) cylinder(h = 1, r = handlebar_radius + clasp_thickness + 1, center = true, $fn = circular_face_count);
|
|
||||||
translate([0, 0, clasp_width / 2 - 4]) cylinder(h = 1, r = handlebar_radius + clasp_thickness + 1, center = true, $fn = circular_face_count);
|
|
||||||
translate([-handlebar_radius-5, -10, -clasp_width / 2 + 6]) cube([6, 20, clasp_width - 12]);
|
|
||||||
}
|
|
||||||
translate([-0.5, 0, 0]) cylinder(h = clasp_width+2, r = handlebar_radius + 1, center = true, $fn = circular_face_count);
|
|
||||||
translate([-0.5, -handlebar_radius - 10, -clasp_width / 2 - 1]) cube([handlebar_radius + 10, handlebar_radius * 2 + 20, clasp_width + 2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
top_clasp();
|
|
@ -1,8 +1,3 @@
|
|||||||
|
|
||||||
module hexagon(r, h) {
|
|
||||||
cylinder(r = r, h = h, center = 2, $fn = 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
module pill(length, bevel) {
|
module pill(length, bevel) {
|
||||||
hull() {
|
hull() {
|
||||||
translate([0, 0, (-length / 2) + bevel]) sphere(r = bevel);
|
translate([0, 0, (-length / 2) + bevel]) sphere(r = bevel);
|
||||||
@ -10,27 +5,6 @@ module pill(length, bevel) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module rounded_cube(dimensions, bevel = 0) {
|
|
||||||
x = dimensions[0];
|
|
||||||
y = dimensions[1];
|
|
||||||
z = dimensions[2];
|
|
||||||
|
|
||||||
if (bevel > 0) {
|
|
||||||
hull() {
|
|
||||||
translate([-x / 2 + bevel, -y / 2 + bevel, -z / 2 + bevel]) sphere(r = bevel);
|
|
||||||
translate([ x / 2 - bevel, -y / 2 + bevel, -z / 2 + bevel]) sphere(r = bevel);
|
|
||||||
translate([ x / 2 - bevel, y / 2 - bevel, -z / 2 + bevel]) sphere(r = bevel);
|
|
||||||
translate([-x / 2 + bevel, y / 2 - bevel, -z / 2 + bevel]) sphere(r = bevel);
|
|
||||||
translate([-x / 2 + bevel, -y / 2 + bevel, z / 2 - bevel]) sphere(r = bevel);
|
|
||||||
translate([ x / 2 - bevel, -y / 2 + bevel, z / 2 - bevel]) sphere(r = bevel);
|
|
||||||
translate([ x / 2 - bevel, y / 2 - bevel, z / 2 - bevel]) sphere(r = bevel);
|
|
||||||
translate([-x / 2 + bevel, y / 2 - bevel, z / 2 - bevel]) sphere(r = bevel);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cube(dimensions, center = true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module box_face(dimensions, bevel = 0) {
|
module box_face(dimensions, bevel = 0) {
|
||||||
x = dimensions[0];
|
x = dimensions[0];
|
||||||
y = dimensions[1];
|
y = dimensions[1];
|
||||||
@ -74,7 +48,6 @@ module box(length, width, height, bevel = 0) {
|
|||||||
rotate([90, 0, 0])
|
rotate([90, 0, 0])
|
||||||
rotate([0, 90, 0])
|
rotate([0, 90, 0])
|
||||||
box_face([width, height, wall_thickness], bevel);
|
box_face([width, height, wall_thickness], bevel);
|
||||||
|
|
||||||
translate([length - wall_thickness + bevel, 0, bevel])
|
translate([length - wall_thickness + bevel, 0, bevel])
|
||||||
rotate([90, 0, 0])
|
rotate([90, 0, 0])
|
||||||
rotate([0, 90, 0])
|
rotate([0, 90, 0])
|
||||||
@ -82,11 +55,3 @@ module box(length, width, height, bevel = 0) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module box_side_slider(length, width, height) {
|
|
||||||
difference() {
|
|
||||||
box_face([width - wall_thickness * 2 + 4, height, wall_thickness], bevel);
|
|
||||||
translate([-1, -1, 1]) cube([4-threshold, height+2, 4-threshold]);
|
|
||||||
color("red") translate([width - wall_thickness * 2 + 1, -1, 1]) cube([4-threshold, height+2, 4-threshold]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ threshold = 0.1;
|
|||||||
board_length = 92;
|
board_length = 92;
|
||||||
board_width = 72;
|
board_width = 72;
|
||||||
board_height = 21.5;
|
board_height = 21.5;
|
||||||
wall_thickness = 4;
|
wall_thickness = 2;
|
||||||
bevel = 0.5;
|
bevel = 0.5;
|
||||||
|
|
||||||
hinge_radius = 2.5;
|
hinge_radius = 2.5;
|
||||||
@ -13,63 +13,16 @@ case_width = board_width + wall_thickness * 2;
|
|||||||
case_length = board_length + wall_thickness * 2;
|
case_length = board_length + wall_thickness * 2;
|
||||||
case_height = board_height + wall_thickness;
|
case_height = board_height + wall_thickness;
|
||||||
|
|
||||||
handlebar_radius = 15;
|
|
||||||
clasp_thickness = 4;
|
|
||||||
circular_face_count = 48;
|
|
||||||
clasp_width = 35;
|
|
||||||
|
|
||||||
include <./common.scad>;
|
include <./common.scad>;
|
||||||
|
|
||||||
module top_clasp() {
|
|
||||||
difference() {
|
|
||||||
union() {
|
|
||||||
cylinder(h = clasp_width, r = handlebar_radius + clasp_thickness, center = true, $fn = circular_face_count);
|
|
||||||
translate([0, 0, -clasp_width / 2]) cylinder(h = 1, r = handlebar_radius + clasp_thickness + 1, center = true, $fn = circular_face_count);
|
|
||||||
translate([0, 0, -clasp_width / 2 + 4]) cylinder(h = 1, r = handlebar_radius + clasp_thickness + 1, center = true, $fn = circular_face_count);
|
|
||||||
translate([0, 0, clasp_width / 2]) cylinder(h = 1, r = handlebar_radius + clasp_thickness + 1, center = true, $fn = circular_face_count);
|
|
||||||
translate([0, 0, clasp_width / 2 - 4]) cylinder(h = 1, r = handlebar_radius + clasp_thickness + 1, center = true, $fn = circular_face_count);
|
|
||||||
translate([-handlebar_radius-5, -10, -clasp_width / 2 + 6]) cube([6, 20, clasp_width - 12]);
|
|
||||||
}
|
|
||||||
translate([-0.5, 0, 0]) cylinder(h = clasp_width+2, r = handlebar_radius + 1, center = true, $fn = circular_face_count);
|
|
||||||
translate([-0.5, -handlebar_radius - 10, -clasp_width / 2 - 1]) cube([handlebar_radius + 10, handlebar_radius * 2 + 20, clasp_width + 2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module hinge(length) {
|
module hinge(length) {
|
||||||
difference() {
|
difference() {
|
||||||
union() {
|
union() {
|
||||||
cube([hinge_radius * 2, length, hinge_radius], center = true);
|
cylinder(h = length, r = hinge_radius);
|
||||||
translate([0, 0, -1.5]) rotate([90, 0, 0]) cylinder(h = length, r = hinge_radius, center = true);
|
translate([0, -hinge_radius, 0])
|
||||||
|
cube([hinge_radius, hinge_radius * 2, length]);
|
||||||
}
|
}
|
||||||
translate([0, threshold / 2, -1.5]) rotate([90, 0, 0]) cylinder(h = length + threshold * 2, r = 1, center = true);
|
translate([0, 0, -threshold / 2]) cylinder(h = length + threshold, r = 1);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module base_case(length, width, height, bevel = 0) {
|
|
||||||
difference() {
|
|
||||||
union() {
|
|
||||||
channel(length + wall_thickness / 2, width, height, bevel);
|
|
||||||
|
|
||||||
translate([-bevel, 0, bevel])
|
|
||||||
rotate([90, 0, 0])
|
|
||||||
rotate([0, 90, 0])
|
|
||||||
box_face([width, height, wall_thickness], bevel);
|
|
||||||
|
|
||||||
// These are the sleds at the bottom of the case that should hold the lower of the two boards down
|
|
||||||
color("blue") translate([0, wall_thickness - 2, wall_thickness + 4]) cube([length - 8, 4, wall_thickness / 2]);
|
|
||||||
color("blue") translate([wall_thickness - 2, wall_thickness - 4, wall_thickness + 4]) cube([4, width, wall_thickness / 2]);
|
|
||||||
color("blue") translate([length - 25, width - wall_thickness * 3 / 2, wall_thickness + 6]) cube([16, wall_thickness, wall_thickness / 2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This makes an indent at the bottom to accomodate solder joins
|
|
||||||
translate([wall_thickness + 2, wall_thickness + 2, wall_thickness / 2]) cube([length, width - wall_thickness * 2 - 4, wall_thickness / 2 + threshold]);
|
|
||||||
|
|
||||||
// This creates a cutout that lets the power plug slide in better.
|
|
||||||
translate([wall_thickness, width - wall_thickness, wall_thickness]) cube([length, 2, 6]);
|
|
||||||
|
|
||||||
// These two put in the slots that should allow the fourth wall to be slotted into place.
|
|
||||||
color("red") translate([length - 1, wall_thickness - 2, 4]) cube([2, 2, height]);
|
|
||||||
color("red") translate([length - 1, width - wall_thickness, 4]) cube([2, 2, height]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,16 +33,11 @@ module main_case() {
|
|||||||
|
|
||||||
difference() {
|
difference() {
|
||||||
union() {
|
union() {
|
||||||
base_case(case_length,
|
box(case_length,
|
||||||
case_width,
|
case_width,
|
||||||
case_height,
|
case_height,
|
||||||
bevel);
|
bevel);
|
||||||
|
|
||||||
translate([-bevel, 0, bevel])
|
|
||||||
rotate([90, 0, 0])
|
|
||||||
rotate([0, 90, 0])
|
|
||||||
box_face([case_width, case_height, wall_thickness], bevel);
|
|
||||||
|
|
||||||
translate([0, -hinge_radius - bevel + threshold, hinge_z_offset + bevel])
|
translate([0, -hinge_radius - bevel + threshold, hinge_z_offset + bevel])
|
||||||
rotate([90, 0, 0])
|
rotate([90, 0, 0])
|
||||||
rotate([0, 90, 0])
|
rotate([0, 90, 0])
|
||||||
@ -117,94 +65,31 @@ module main_case() {
|
|||||||
rotate([0, 180, 0])
|
rotate([0, 180, 0])
|
||||||
linear_extrude(1)
|
linear_extrude(1)
|
||||||
text("right", size = 3);
|
text("right", size = 3);
|
||||||
// translate([case_length / 2, case_width / 2, -20]) rotate([0, 90, 0]) top_clasp();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
translate([case_length / 2, case_width / 2, -threshold]) hexagon(4.5, 6);
|
color("green", 1) translate([8.5 + wall_thickness, case_width - wall_thickness - threshold, wall_thickness])
|
||||||
|
cube([60, wall_thickness * 2, 7]);
|
||||||
# translate([8.5 + wall_thickness, case_width - wall_thickness - threshold, wall_thickness])
|
|
||||||
# cube([60, wall_thickness * 2, 7]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module lamp() {
|
|
||||||
union() {
|
|
||||||
translate([0, 0, -0.5]) cube([12.9 + threshold, 8, 4], center = true);
|
|
||||||
translate([0, 0, .88]) cube([5 + threshold, 5 + threshold, 1.56], center = true);
|
|
||||||
/*
|
|
||||||
translate([0, 0, -1.56]) cube([12.9, 7.6, wall_thickness], center = true);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module button() {
|
|
||||||
union() {
|
|
||||||
cube([3.5 + threshold, 6.1 + threshold, 4 + threshold], center = true);
|
|
||||||
translate([0, 0, -0.5]) cube([1.2, 7, 3 + threshold], center = true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module lid() {
|
module lid() {
|
||||||
lid_width = case_width + hinge_radius * 2 + wall_thickness;
|
lid_width = case_width + hinge_radius * 2 + wall_thickness;
|
||||||
hinge_length = case_length / 4;
|
|
||||||
union() {
|
union() {
|
||||||
difference() {
|
difference() {
|
||||||
rounded_cube([case_length,
|
box_face([case_length,
|
||||||
lid_width,
|
lid_width,
|
||||||
wall_thickness],
|
wall_thickness],
|
||||||
bevel);
|
bevel);
|
||||||
translate([0, lid_width / 5, 0.4]) lamp();
|
translate([(case_length - 60) / 2, 14 + hinge_radius * 2, -threshold / 2])
|
||||||
translate([-15, lid_width / 5, 0.4]) lamp();
|
cube([60, 16, wall_thickness + threshold]);
|
||||||
translate([15, lid_width / 5, 0.4]) lamp();
|
|
||||||
translate([-30, lid_width / 5, 0]) button();
|
|
||||||
translate([30, lid_width / 5, 0]) button();
|
|
||||||
|
|
||||||
translate([0, lid_width / 5, -2]) cube([20, 7, 3], center = true);
|
|
||||||
|
|
||||||
color("black") translate([-2, lid_width / 5 - 5, -2]) rotate([0, 0, 90]) rotate([0, 90, 0]) cylinder(h=5, r = 1, center = true, $fn = circular_face_count);
|
|
||||||
color("black") translate([-17, lid_width / 5 - 5, -2]) rotate([0, 0, 90]) rotate([0, 90, 0]) cylinder(h=5, r = 1, center = true, $fn = circular_face_count);
|
|
||||||
color("black") translate([13, lid_width / 5 - 5, -2]) rotate([0, 0, 90]) rotate([0, 90, 0]) cylinder(h=5, r = 1, center = true, $fn = circular_face_count);
|
|
||||||
color("black") translate([-30, lid_width / 5 - 5, -2]) rotate([0, 0, 90]) rotate([0, 90, 0]) cylinder(h=5, r = 1, center = true, $fn = circular_face_count);
|
|
||||||
color("black") translate([30, lid_width / 5 - 5, -2]) rotate([0, 0, 90]) rotate([0, 90, 0]) cylinder(h=5, r = 1, center = true, $fn = circular_face_count);
|
|
||||||
color("black") translate([0, 10, -2]) rotate([0, 90, 0]) cylinder(h = 62, r = 1, center = true, $fn = circular_face_count);
|
|
||||||
|
|
||||||
color("red") translate([-33, 21, -2]) rotate([0, 90, 0]) cylinder(h = 5, r = 1, center = true, $fn = circular_face_count);
|
|
||||||
color("red") translate([-35, 13, -2]) rotate([0, 0, 90]) rotate([0, 90, 0]) cylinder(h = 18, r = 1, center = true, $fn = circular_face_count);
|
|
||||||
color("red") translate([33, 21, -2]) rotate([0, 90, 0]) cylinder(h = 5, r = 1, center = true, $fn = circular_face_count);
|
|
||||||
color("red") translate([35, 13, -2]) rotate([0, 0, 90]) rotate([0, 90, 0]) cylinder(h = 18, r = 1, center = true, $fn = circular_face_count);
|
|
||||||
color("red") translate([0, 5, -2]) rotate([0, 90, 0]) cylinder(h = 70, r = 1, center = true, $fn = circular_face_count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
translate([case_length / 2 - hinge_length / 2, lid_width / 2 - wall_thickness / 2 - 0.5, -wall_thickness / 2]) rotate([0, 0, 90]) hinge(hinge_length);
|
translate([case_length / 4 + 1, hinge_radius - 0.4, -hinge_radius])
|
||||||
translate([-case_length / 2 + hinge_length / 2, lid_width / 2 - wall_thickness / 2 - 0.5, -wall_thickness / 2]) rotate([0, 0, 90]) hinge(hinge_length);
|
rotate([180, 0, 0])
|
||||||
|
rotate([0, 90, 0]) hinge(case_length / 2 - 2);
|
||||||
translate([0, -lid_width / 2 + bevel, -3]) rounded_cube([20, wall_thickness / 2, 10], bevel);
|
|
||||||
color("blue") translate([-9, -lid_width / 2 + 1.5, -6]) rotate([90, 0, 0]) rotate([0, 90, 0]) linear_extrude(18) circle(1, $fn = 3);
|
|
||||||
color("blue") translate([-9, -lid_width / 2 + 1.5, -7]) rotate([90, 0, 0]) rotate([0, 90, 0]) linear_extrude(18) circle(1, $fn = 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module box_side() {
|
|
||||||
box_side_slider(case_length, case_width, case_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
module case_base() {
|
|
||||||
difference() {
|
|
||||||
rounded_cube([case_length, case_width, wall_thickness + 2], bevel = 0.5);
|
|
||||||
translate([wall_thickness, 0, 2]) rounded_cube([case_length + threshold, board_width + threshold, 2 + threshold]);
|
|
||||||
|
|
||||||
// These give a screw-hole in the center which will allow the clamp to be attached
|
|
||||||
translate([0, 0, -1]) hexagon(4.5, 2);
|
|
||||||
translate([0, 0, -wall_thickness / 2]) cylinder(r = 2, h = wall_thickness + threshold, center = true);
|
|
||||||
|
|
||||||
// and now a bit of an indentation to help the clip remain in place
|
|
||||||
translate([0, 0, -4.5]) cube([clasp_width + threshold, clasp_width + threshold, wall_thickness], center = true);
|
|
||||||
|
|
||||||
// here are some grooves along the edges that can be used to piece parts together
|
|
||||||
translate([wall_thickness / 2, case_width / 2 - wall_thickness / 2, wall_thickness / 2])
|
|
||||||
cube([board_length + wall_thickness, wall_thickness / 2, wall_thickness / 2 + threshold], center = true);
|
|
||||||
translate([wall_thickness / 2, -case_width / 2 + wall_thickness / 2, wall_thickness / 2])
|
|
||||||
cube([board_length + wall_thickness, wall_thickness / 2, wall_thickness / 2 + threshold], center = true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// main_case();
|
||||||
|
// color("red", 1) translate([0, 0, case_height + wall_thickness / 2]) lid();
|
||||||
|
// color("red", 1) translate([0, 0, 40]) lid();
|
||||||
|
@ -1,11 +1,4 @@
|
|||||||
|
|
||||||
include <./control_panel.scad>
|
include <./control_panel.scad>
|
||||||
|
|
||||||
/*
|
main_case();
|
||||||
difference() {
|
|
||||||
color("blue") rounded_cube([5, 5, 5], bevel = 0.5);
|
|
||||||
translate([0, 0, 1]) rounded_cube([4, 4, 4]);
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
case_base();
|
|
||||||
|
@ -2,5 +2,4 @@
|
|||||||
include <./control_panel.scad>
|
include <./control_panel.scad>
|
||||||
|
|
||||||
lid();
|
lid();
|
||||||
// lamp();
|
|
||||||
|
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
|
|
||||||
include <./control_panel.scad>
|
|
||||||
|
|
||||||
box_side();
|
|
@ -38,7 +38,7 @@ pub struct Instant(pub U128F0);
|
|||||||
|
|
||||||
impl Default for Instant {
|
impl Default for Instant {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self(U128F0::from(0_u8))
|
Self(U128F0::from(0 as u8))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,7 +198,7 @@ impl Blinker {
|
|||||||
direction: BlinkerDirection,
|
direction: BlinkerDirection,
|
||||||
time: Instant,
|
time: Instant,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut ending_dashboard = OFF_DASHBOARD;
|
let mut ending_dashboard = OFF_DASHBOARD.clone();
|
||||||
|
|
||||||
match direction {
|
match direction {
|
||||||
BlinkerDirection::Left => {
|
BlinkerDirection::Left => {
|
||||||
@ -213,7 +213,7 @@ impl Blinker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut ending_body = OFF_BODY;
|
let mut ending_body = OFF_BODY.clone();
|
||||||
match direction {
|
match direction {
|
||||||
BlinkerDirection::Left => {
|
BlinkerDirection::Left => {
|
||||||
for i in 0..30 {
|
for i in 0..30 {
|
||||||
@ -233,26 +233,26 @@ impl Blinker {
|
|||||||
|
|
||||||
Blinker {
|
Blinker {
|
||||||
transition: Fade::new(
|
transition: Fade::new(
|
||||||
starting_dashboard,
|
starting_dashboard.clone(),
|
||||||
starting_body,
|
starting_body.clone(),
|
||||||
ending_dashboard,
|
ending_dashboard.clone(),
|
||||||
ending_body,
|
ending_body.clone(),
|
||||||
BLINKER_FRAMES,
|
BLINKER_FRAMES,
|
||||||
time,
|
time,
|
||||||
),
|
),
|
||||||
fade_in: Fade::new(
|
fade_in: Fade::new(
|
||||||
OFF_DASHBOARD,
|
OFF_DASHBOARD.clone(),
|
||||||
OFF_BODY,
|
OFF_BODY.clone(),
|
||||||
ending_dashboard,
|
ending_dashboard.clone(),
|
||||||
ending_body,
|
ending_body.clone(),
|
||||||
BLINKER_FRAMES,
|
BLINKER_FRAMES,
|
||||||
time,
|
time,
|
||||||
),
|
),
|
||||||
fade_out: Fade::new(
|
fade_out: Fade::new(
|
||||||
ending_dashboard,
|
ending_dashboard.clone(),
|
||||||
ending_body,
|
ending_body.clone(),
|
||||||
OFF_DASHBOARD,
|
OFF_DASHBOARD.clone(),
|
||||||
OFF_BODY,
|
OFF_BODY.clone(),
|
||||||
BLINKER_FRAMES,
|
BLINKER_FRAMES,
|
||||||
time,
|
time,
|
||||||
),
|
),
|
||||||
@ -336,7 +336,7 @@ impl Pattern {
|
|||||||
|
|
||||||
fn body(&self) -> BodyPattern {
|
fn body(&self) -> BodyPattern {
|
||||||
match self {
|
match self {
|
||||||
Pattern::Water => WATER_BODY,
|
Pattern::Water => OFF_BODY,
|
||||||
Pattern::GayPride => PRIDE_BODY,
|
Pattern::GayPride => PRIDE_BODY,
|
||||||
Pattern::TransPride => TRANS_PRIDE_BODY,
|
Pattern::TransPride => TRANS_PRIDE_BODY,
|
||||||
}
|
}
|
||||||
@ -375,7 +375,7 @@ impl App {
|
|||||||
pattern.dashboard(),
|
pattern.dashboard(),
|
||||||
pattern.body(),
|
pattern.body(),
|
||||||
DEFAULT_FRAMES,
|
DEFAULT_FRAMES,
|
||||||
Instant(0_u32.into()),
|
Instant((0 as u32).into()),
|
||||||
)),
|
)),
|
||||||
dashboard_lights: OFF_DASHBOARD,
|
dashboard_lights: OFF_DASHBOARD,
|
||||||
lights: OFF_BODY,
|
lights: OFF_BODY,
|
||||||
@ -386,8 +386,8 @@ impl App {
|
|||||||
match self.state {
|
match self.state {
|
||||||
State::Pattern(ref pattern) => {
|
State::Pattern(ref pattern) => {
|
||||||
self.current_animation = Box::new(Fade::new(
|
self.current_animation = Box::new(Fade::new(
|
||||||
self.dashboard_lights,
|
self.dashboard_lights.clone(),
|
||||||
self.lights,
|
self.lights.clone(),
|
||||||
pattern.dashboard(),
|
pattern.dashboard(),
|
||||||
pattern.body(),
|
pattern.body(),
|
||||||
DEFAULT_FRAMES,
|
DEFAULT_FRAMES,
|
||||||
@ -396,8 +396,8 @@ impl App {
|
|||||||
}
|
}
|
||||||
State::Brake => {
|
State::Brake => {
|
||||||
self.current_animation = Box::new(Fade::new(
|
self.current_animation = Box::new(Fade::new(
|
||||||
self.dashboard_lights,
|
self.dashboard_lights.clone(),
|
||||||
self.lights,
|
self.lights.clone(),
|
||||||
BRAKES_DASHBOARD,
|
BRAKES_DASHBOARD,
|
||||||
BRAKES_BODY,
|
BRAKES_BODY,
|
||||||
BRAKES_FRAMES,
|
BRAKES_FRAMES,
|
||||||
@ -406,16 +406,16 @@ impl App {
|
|||||||
}
|
}
|
||||||
State::LeftBlinker => {
|
State::LeftBlinker => {
|
||||||
self.current_animation = Box::new(Blinker::new(
|
self.current_animation = Box::new(Blinker::new(
|
||||||
self.dashboard_lights,
|
self.dashboard_lights.clone(),
|
||||||
self.lights,
|
self.lights.clone(),
|
||||||
BlinkerDirection::Left,
|
BlinkerDirection::Left,
|
||||||
time,
|
time,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
State::RightBlinker => {
|
State::RightBlinker => {
|
||||||
self.current_animation = Box::new(Blinker::new(
|
self.current_animation = Box::new(Blinker::new(
|
||||||
self.dashboard_lights,
|
self.dashboard_lights.clone(),
|
||||||
self.lights,
|
self.lights.clone(),
|
||||||
BlinkerDirection::Right,
|
BlinkerDirection::Right,
|
||||||
time,
|
time,
|
||||||
));
|
));
|
||||||
@ -441,13 +441,19 @@ impl App {
|
|||||||
State::LeftBlinker => self.state = State::Pattern(self.home_pattern),
|
State::LeftBlinker => self.state = State::Pattern(self.home_pattern),
|
||||||
_ => self.state = State::LeftBlinker,
|
_ => self.state = State::LeftBlinker,
|
||||||
},
|
},
|
||||||
Event::NextPattern => if let State::Pattern(ref pattern) = self.state {
|
Event::NextPattern => match self.state {
|
||||||
self.home_pattern = pattern.next();
|
State::Pattern(ref pattern) => {
|
||||||
self.state = State::Pattern(self.home_pattern);
|
self.home_pattern = pattern.next();
|
||||||
|
self.state = State::Pattern(self.home_pattern);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
},
|
},
|
||||||
Event::PreviousPattern => if let State::Pattern(ref pattern) = self.state {
|
Event::PreviousPattern => match self.state {
|
||||||
self.home_pattern = pattern.previous();
|
State::Pattern(ref pattern) => {
|
||||||
self.state = State::Pattern(self.home_pattern);
|
self.home_pattern = pattern.previous();
|
||||||
|
self.state = State::Pattern(self.home_pattern);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
},
|
},
|
||||||
Event::RightBlinker => match self.state {
|
Event::RightBlinker => match self.state {
|
||||||
State::Brake => self.state = State::BrakeRightBlinker,
|
State::Brake => self.state = State::BrakeRightBlinker,
|
||||||
@ -459,14 +465,17 @@ impl App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn tick(&mut self, time: Instant) {
|
pub fn tick(&mut self, time: Instant) {
|
||||||
if let Some(event) = self.ui.check_event(time) {
|
match self.ui.check_event(time) {
|
||||||
self.update_state(event);
|
Some(event) => {
|
||||||
self.update_animation(time);
|
self.update_state(event);
|
||||||
|
self.update_animation(time);
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
let (dashboard, lights) = self.current_animation.tick(time);
|
let (dashboard, lights) = self.current_animation.tick(time);
|
||||||
self.dashboard_lights = dashboard;
|
self.dashboard_lights = dashboard.clone();
|
||||||
self.lights = lights;
|
self.lights = lights.clone();
|
||||||
self.ui.update_lights(dashboard, lights);
|
self.ui.update_lights(dashboard, lights);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,74 +98,7 @@ pub const DEFAULT_FRAMES: U16F0 = U16F0::lit("30");
|
|||||||
|
|
||||||
pub const WATER_DASHBOARD: DashboardPattern = [WATER_1, WATER_2, WATER_3];
|
pub const WATER_DASHBOARD: DashboardPattern = [WATER_1, WATER_2, WATER_3];
|
||||||
|
|
||||||
pub const WATER_BODY: BodyPattern = [
|
pub const WATER_BODY: BodyPattern = [RGB_OFF; 60];
|
||||||
WATER_1,
|
|
||||||
WATER_1,
|
|
||||||
WATER_1,
|
|
||||||
WATER_1,
|
|
||||||
WATER_1,
|
|
||||||
WATER_1,
|
|
||||||
WATER_1,
|
|
||||||
WATER_1,
|
|
||||||
WATER_1,
|
|
||||||
WATER_1,
|
|
||||||
|
|
||||||
WATER_2,
|
|
||||||
WATER_2,
|
|
||||||
WATER_2,
|
|
||||||
WATER_2,
|
|
||||||
WATER_2,
|
|
||||||
WATER_2,
|
|
||||||
WATER_2,
|
|
||||||
WATER_2,
|
|
||||||
WATER_2,
|
|
||||||
WATER_2,
|
|
||||||
|
|
||||||
WATER_3,
|
|
||||||
WATER_3,
|
|
||||||
WATER_3,
|
|
||||||
WATER_3,
|
|
||||||
WATER_3,
|
|
||||||
WATER_3,
|
|
||||||
WATER_3,
|
|
||||||
WATER_3,
|
|
||||||
WATER_3,
|
|
||||||
WATER_3,
|
|
||||||
|
|
||||||
|
|
||||||
WATER_3,
|
|
||||||
WATER_3,
|
|
||||||
WATER_3,
|
|
||||||
WATER_3,
|
|
||||||
WATER_3,
|
|
||||||
WATER_3,
|
|
||||||
WATER_3,
|
|
||||||
WATER_3,
|
|
||||||
WATER_3,
|
|
||||||
WATER_3,
|
|
||||||
|
|
||||||
WATER_2,
|
|
||||||
WATER_2,
|
|
||||||
WATER_2,
|
|
||||||
WATER_2,
|
|
||||||
WATER_2,
|
|
||||||
WATER_2,
|
|
||||||
WATER_2,
|
|
||||||
WATER_2,
|
|
||||||
WATER_2,
|
|
||||||
WATER_2,
|
|
||||||
|
|
||||||
WATER_1,
|
|
||||||
WATER_1,
|
|
||||||
WATER_1,
|
|
||||||
WATER_1,
|
|
||||||
WATER_1,
|
|
||||||
WATER_1,
|
|
||||||
WATER_1,
|
|
||||||
WATER_1,
|
|
||||||
WATER_1,
|
|
||||||
WATER_1,
|
|
||||||
];
|
|
||||||
|
|
||||||
pub const PRIDE_DASHBOARD: DashboardPattern = [PRIDE_RED, PRIDE_GREEN, PRIDE_INDIGO];
|
pub const PRIDE_DASHBOARD: DashboardPattern = [PRIDE_RED, PRIDE_GREEN, PRIDE_INDIGO];
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
adw = { version = "0.5", package = "libadwaita", features = [ "v1_2" ] }
|
adw = { version = "0.5", package = "libadwaita", features = [ "v1_2" ] }
|
||||||
async-std = "1.13.0"
|
|
||||||
cairo-rs = { version = "0.18" }
|
cairo-rs = { version = "0.18" }
|
||||||
fixed = { version = "1" }
|
fixed = { version = "1" }
|
||||||
gio = { version = "0.18" }
|
gio = { version = "0.18" }
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use async_std::channel::Sender;
|
|
||||||
use fixed::types::{I8F8, U128F0};
|
use fixed::types::{I8F8, U128F0};
|
||||||
use glib::Object;
|
use glib::{Object, Sender};
|
||||||
use gtk::subclass::prelude::*;
|
use gtk::subclass::prelude::*;
|
||||||
use lights_core::{
|
use lights_core::{
|
||||||
App, BodyPattern, DashboardPattern, Event, Instant, FPS, OFF_BODY, OFF_DASHBOARD, RGB, UI,
|
App, BodyPattern, DashboardPattern, Event, Instant, FPS, OFF_BODY, OFF_DASHBOARD, RGB, UI,
|
||||||
@ -46,12 +45,6 @@ glib::wrapper! {
|
|||||||
pub struct DashboardLights(ObjectSubclass<DashboardLightsPrivate>) @extends gtk::DrawingArea, gtk::Widget;
|
pub struct DashboardLights(ObjectSubclass<DashboardLightsPrivate>) @extends gtk::DrawingArea, gtk::Widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for DashboardLights {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DashboardLights {
|
impl DashboardLights {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let s: Self = Object::builder().build();
|
let s: Self = Object::builder().build();
|
||||||
@ -110,12 +103,6 @@ glib::wrapper! {
|
|||||||
pub struct BikeLights(ObjectSubclass<BikeLightsPrivate>) @extends gtk::DrawingArea, gtk::Widget;
|
pub struct BikeLights(ObjectSubclass<BikeLightsPrivate>) @extends gtk::DrawingArea, gtk::Widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for BikeLights {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BikeLights {
|
impl BikeLights {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let s: Self = Object::builder().build();
|
let s: Self = Object::builder().build();
|
||||||
@ -174,15 +161,12 @@ impl UI for GTKUI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn update_lights(&self, dashboard_lights: DashboardPattern, lights: BodyPattern) {
|
fn update_lights(&self, dashboard_lights: DashboardPattern, lights: BodyPattern) {
|
||||||
let tx = self.tx.clone();
|
self.tx
|
||||||
glib::spawn_future(async move {
|
.send(Update {
|
||||||
let _ = tx
|
dashboard: dashboard_lights,
|
||||||
.send(Update {
|
lights,
|
||||||
dashboard: dashboard_lights,
|
})
|
||||||
lights,
|
.unwrap();
|
||||||
})
|
|
||||||
.await;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +176,8 @@ fn main() {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
adw_app.connect_activate(move |adw_app| {
|
adw_app.connect_activate(move |adw_app| {
|
||||||
let (update_tx, update_rx) = async_std::channel::unbounded();
|
let (update_tx, update_rx) =
|
||||||
|
gtk::glib::MainContext::channel::<Update>(gtk::glib::Priority::DEFAULT);
|
||||||
let (event_tx, event_rx) = std::sync::mpsc::channel();
|
let (event_tx, event_rx) = std::sync::mpsc::channel();
|
||||||
|
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
@ -284,17 +269,6 @@ fn main() {
|
|||||||
layout.append(&dashboard_lights);
|
layout.append(&dashboard_lights);
|
||||||
layout.append(&bike_lights);
|
layout.append(&bike_lights);
|
||||||
|
|
||||||
glib::spawn_future_local({
|
|
||||||
let dashboard_lights = dashboard_lights.clone();
|
|
||||||
let bike_lights = bike_lights.clone();
|
|
||||||
async move {
|
|
||||||
while let Ok(Update { dashboard, lights }) = update_rx.recv().await {
|
|
||||||
dashboard_lights.set_lights(dashboard);
|
|
||||||
bike_lights.set_lights(lights);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
/*
|
|
||||||
update_rx.attach(None, {
|
update_rx.attach(None, {
|
||||||
let dashboard_lights = dashboard_lights.clone();
|
let dashboard_lights = dashboard_lights.clone();
|
||||||
let bike_lights = bike_lights.clone();
|
let bike_lights = bike_lights.clone();
|
||||||
@ -304,7 +278,6 @@ fn main() {
|
|||||||
glib::ControlFlow::Continue
|
glib::ControlFlow::Continue
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
*/
|
|
||||||
|
|
||||||
window.set_content(Some(&layout));
|
window.set_content(Some(&layout));
|
||||||
window.present();
|
window.present();
|
||||||
|
@ -40,12 +40,6 @@ macro_rules! define_config {
|
|||||||
values: std::collections::HashMap<ConfigName, ConfigOption>,
|
values: std::collections::HashMap<ConfigName, ConfigOption>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -145,7 +145,7 @@ mod tests {
|
|||||||
|
|
||||||
let coord2 = &lst1[idx];
|
let coord2 = &lst1[idx];
|
||||||
assert!(coord2.is_adjacent(&coord1));
|
assert!(coord2.is_adjacent(&coord1));
|
||||||
assert!(coord1.is_adjacent(coord2));
|
assert!(coord1.is_adjacent(&coord2));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -166,10 +166,10 @@ mod tests {
|
|||||||
let hexaddr = AxialAddr::new(q, r);
|
let hexaddr = AxialAddr::new(q, r);
|
||||||
let en_distancaj_hexaddr: Vec<AxialAddr> = hexaddr.addresses(distance).collect();
|
let en_distancaj_hexaddr: Vec<AxialAddr> = hexaddr.addresses(distance).collect();
|
||||||
|
|
||||||
let expected_cnt = (0..distance+1).map(|v| v * 6).fold(1, |acc, val| acc + val);
|
let expected_cnt = ((0..distance+1).map(|v| v * 6).fold(1, |acc, val| acc + val)) as usize;
|
||||||
assert_eq!(en_distancaj_hexaddr.len(), expected_cnt);
|
assert_eq!(en_distancaj_hexaddr.len(), expected_cnt);
|
||||||
for c in en_distancaj_hexaddr {
|
for c in en_distancaj_hexaddr {
|
||||||
assert!(c.distance(&hexaddr) <= distance);
|
assert!(c.distance(&hexaddr) <= distance as usize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,519 @@
|
|||||||
{
|
{
|
||||||
"git+https://github.com/yewstack/yew/#yew-macro@0.21.0": "1g47mpyzd2mib73cjrbmcivrp7kr16f6hbrmpaap56kbc518khwf",
|
"registry+https://github.com/rust-lang/crates.io-index#addr2line@0.21.0": "1jx0k3iwyqr8klqbzk6kjvr496yd94aspis10vwsj5wy7gib4c4a",
|
||||||
"git+https://github.com/yewstack/yew/#yew@0.21.0": "1g47mpyzd2mib73cjrbmcivrp7kr16f6hbrmpaap56kbc518khwf"
|
"registry+https://github.com/rust-lang/crates.io-index#adler32@1.2.0": "0d7jq7jsjyhsgbhnfq5fvrlh9j0i9g1fqrl2735ibv5f75yjgqda",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#adler@1.0.2": "1zim79cvzd5yrkzl3nyfx0avijwgk9fqv3yrscdy1cc79ih02qpj",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#ahash@0.8.6": "0yn9i8nc6mmv28ig9w3dga571q09vg9f1f650mi5z8phx42r6hli",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#aho-corasick@1.1.2": "1w510wnixvlgimkx1zjbvlxh6xps2vjgfqgwf5a6adlbjp5rv5mj",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#allocator-api2@0.2.16": "1iayppgq4wqbfbfcqmsbwgamj0s65012sskfvyx07pxavk3gyhh9",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#android-tzdata@0.1.1": "1w7ynjxrfs97xg3qlcdns4kgfpwcdv824g611fq32cag4cdr96g9",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#android_system_properties@0.1.5": "04b3wrz12837j7mdczqd95b732gw5q7q66cv4yn4646lvccp57l1",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#annotate-snippets@0.9.2": "07p8r6jzb7nqydq0kr5pllckqcdxlyld2g275v425axnzffpxbyc",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#anstream@0.6.5": "1dm1mdbs1x6y3m3pz0qlamgiskb50i4q859676kx0pz8r8pajr6n",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#anstyle-parse@0.2.3": "134jhzrz89labrdwxxnjxqjdg06qvaflj1wkfnmyapwyldfwcnn7",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#anstyle-query@1.0.2": "0j3na4b1nma39g4x7cwvj009awxckjf3z2vkwhldgka44hqj72g2",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#anstyle-wincon@3.0.2": "19v0fv400bmp4niqpzxnhg83vz12mmqv7l2l8vi80qcdxj0lpm8w",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#anstyle@1.0.4": "11yxw02b6parn29s757z96rgiqbn8qy0fk9a3p3bhczm85dhfybh",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#anyhow@1.0.75": "1rmcjkim91c5mw7h9wn8nv0k6x118yz0xg0z1q18svgn42mqqrm4",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#arrayvec@0.7.4": "04b7n722jij0v3fnm3qk072d5ysc2q30rl9fz33zpfhzah30mlwn",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#async-channel@1.9.0": "0dbdlkzlncbibd3ij6y6jmvjd0cmdn48ydcfdpfhw09njd93r5c1",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#async-channel@2.1.1": "1337ywc1paw03rdlwh100kh8pa0zyp0nrlya8bpsn6zdqi5kz8qw",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#async-executor@1.8.0": "0z7rpayidhdqs4sdzjhh26z5155c1n94fycqni9793n4zjz5xbhp",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#async-global-executor@2.4.1": "1762s45cc134d38rrv0hyp41hv4iv6nmx59vswid2p0il8rvdc85",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#async-io@2.3.1": "0rggn074kbqxxajci1aq14b17gp75rw9l6rpbazcv9q0bc6ap5wg",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#async-lock@3.3.0": "0yxflkfw46rad4lv86f59b5z555dlfmg1riz1n8830rgi0qb8d6h",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#async-std@1.13.0": "059nbiyijwbndyrz0050skvlvzhds0dmnl0biwmxwbw055glfd66",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#async-task@4.7.0": "16975vx6aqy5yf16fs9xz5vx1zq8mwkzfmykvcilc1j7b6c6xczv",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#async-trait@0.1.77": "1adf1jh2yg39rkpmqjqyr9xyd6849p0d95425i6imgbhx0syx069",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#atoi@2.0.0": "0a05h42fggmy7h0ajjv6m7z72l924i7igbx13hk9d8pyign9k3gj",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#atomic-waker@1.1.2": "1h5av1lw56m0jf0fd3bchxq8a30xv0b4wv8s4zkp4s0i7mfvs18m",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#atomic-write-file@0.1.2": "0dl4x0srdwjxm3zz3fj1c7m44i3b7mjiad550fqklj1n4bfbxkgd",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#autocfg@0.1.8": "0y4vw4l4izdxq1v0rrhvmlbqvalrqrmk60v1z0dqlgnlbzkl7phd",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#autocfg@1.1.0": "1ylp3cb47ylzabimazvbz9ms6ap784zhb6syaz6c1jqpmcmq0s6l",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#az@1.2.1": "0ww9k1w3al7x5qmb7f13v3s9c2pg1pdxbs8xshqy6zyrchj4qzkv",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#backtrace@0.3.69": "0dsq23dhw4pfndkx2nsa1ml2g31idm7ss7ljxp8d57avygivg290",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#bare-metal@0.2.5": "1cy5pbb92fznnri72y6drfpjxj4qdmd62f0rrlgy70dxlppn9ssx",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#base64@0.21.5": "1y8x2xs9nszj5ix7gg4ycn5a6wy7ca74zxwqri3bdqzdjha6lqrm",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#base64@0.9.3": "0hs62r35bgxslawyrn1vp9rmvrkkm76fqv0vqcwd048vs876r7a8",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#base64ct@1.6.0": "0nvdba4jb8aikv60az40x2w1y96sjdq8z3yp09rwzmkhiwv1lg4c",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#bindgen@0.69.4": "18194611hn3k1dkxlha7a52sr8vmfhl9blc54xhj08cahd8wh3d0",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#bit-set@0.5.3": "1wcm9vxi00ma4rcxkl3pzzjli6ihrpn9cfdi0c5b4cvga2mxs007",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#bit-vec@0.6.3": "1ywqjnv60cdh1slhz67psnp422md6jdliji6alq0gmly2xm9p7rl",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#bit_field@0.10.2": "0qav5rpm4hqc33vmf4vc4r0mh51yjx5vmd9zhih26n9yjs3730nw",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#bitfield@0.13.2": "06g7jb5r2b856vnhx76081fg90jvmy61kjqcfjysgmd5hclvvbs6",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#bitflags@1.3.2": "12ki6w8gn1ldq7yz9y680llwk5gmrhrzszaa17g1sbrw2r2qvwxy",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#bitflags@2.4.1": "01ryy3kd671b0ll4bhdvhsz67vwz1lz53fz504injrd7wpv64xrj",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#block-buffer@0.10.4": "0w9sa2ypmrsqqvc20nhwr75wbb5cjr4kkyhpjm1z1lv2kdicfy1h",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#blocking@1.5.1": "064i3d6b8ln34fgdw49nmx9m36bwi3r3nv8c9xhcrpf4ilz92dva",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#build_html@2.4.0": "188nibbsv33vgjjiq9cn2irsgdb75gxfipavcavnyydcwxpzw21i",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#bumpalo@3.14.0": "1v4arnv9kwk54v5d0qqpv4vyw2sgr660nk0w3apzixi1cm3yfc3z",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#bytemuck@1.14.0": "1ik1ma5n3bg700skkzhx50zjk7kj7mbsphi773if17l04pn2hk9p",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#byteorder@1.5.0": "0jzncxyf404mwqdbspihyzpkndfgda450l0893pz5xj685cg5l0z",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#bytes@1.5.0": "08w2i8ac912l8vlvkv3q51cd4gr09pwlg3sjsjffcizlrb0i5gd2",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#cairo-rs@0.18.3": "18d80lk853bjhx36rjaj78clzfjrmlgi01863drnmshdgxi16dpk",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#cairo-sys-rs@0.18.2": "0lfsxl7ylw3phbnwmz3k58j1gnqi6kc2hdc7g3bb7f4hwnl9yp38",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#cc@1.0.83": "1l643zidlb5iy1dskc5ggqs4wqa29a02f44piczqc8zcnsq4y5zi",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#cexpr@0.6.0": "0rl77bwhs5p979ih4r0202cn5jrfsrbgrksp40lkfz5vk1x3ib3g",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#cfg-expr@0.15.5": "1cqicd9qi8mzzgh63dw03zhbdihqfl3lbiklrkynyzkq67s5m483",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#cfg-if@1.0.0": "1za0vb97n4brpzpv8lsbnzmq5r8f2b0cpqqr0sy8h5bn751xxwds",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#chrono-tz-build@0.2.1": "03rmzd69cn7fp0fgkjr5042b3g54s2l941afjm3001ls7kqkjgj3",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#chrono-tz@0.8.4": "0xhd3dsfs72im0sbc7w889lfy7bxgjlbvqhj5a1yvxhxwb08acg2",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#chrono@0.4.31": "0f6vg67pipm8cziad2yms6a639pssnvysk1m05dd9crymmdnhb3z",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#clang-sys@1.8.1": "1x1r9yqss76z8xwpdanw313ss6fniwc1r7dzb5ycjn0ph53kj0hb",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#clap@4.4.11": "1wj5gb2fnqls00zfahg3490bdfc36d9cwpl80qjacb5jyrqzdbxz",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#clap_builder@4.4.11": "1fxdsmw1ilgswz3lg2hjlvsdyyz04k78scjirlbd7c9bc83ba5m2",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#clap_derive@4.4.7": "0hk4hcxl56qwqsf4hmf7c0gr19r9fbxk0ah2bgkr36pmmaph966g",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#clap_lex@0.6.0": "1l8bragdvim7mva9flvd159dskn2bdkpl0jqrr41wnjfn8pcfbvh",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#cloudabi@0.0.3": "0kxcg83jlihy0phnd2g8c2c303px3l2p3pkjz357ll6llnd5pz6x",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#color_quant@1.1.0": "12q1n427h2bbmmm1mnglr57jaz2dj9apk0plcxw7nwqiai7qjyrx",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#colorchoice@1.0.0": "1ix7w85kwvyybwi2jdkl3yva2r2bvdcc3ka2grjfzfgrapqimgxc",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#concurrent-queue@2.4.0": "0qvk23ynj311adb4z7v89wk3bs65blps4n24q8rgl23vjk6lhq6i",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#const-oid@0.9.6": "1y0jnqaq7p2wvspnx7qj76m7hjcqpz73qzvr9l2p9n2s51vr6if2",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#convert_case@0.6.0": "1jn1pq6fp3rri88zyw6jlhwwgf6qiyc08d6gjv0qypgkl862n67c",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#cookie-factory@0.3.3": "18mka6fk3843qq3jw1fdfvzyv05kx7kcmirfbs2vg2kbw9qzm1cq",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#cookie@0.17.0": "096c52jg9iq4lfcps2psncswv33fc30mmnaa2sbzzcfcw71kgyvy",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#cool_asserts@2.0.3": "1v18dg7ifx41k2f82j3gsnpm1fg9wk5s4zv7sf42c7pnad72b7zf",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#core-foundation-sys@0.8.6": "13w6sdf06r0hn7bx2b45zxsg1mm2phz34jikm6xc5qrbr6djpsh6",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#core-foundation@0.9.4": "13zvbbj07yk3b61b8fhwfzhy35535a583irf23vlcg59j7h9bqci",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#cortex-m-rt-macros@0.7.0": "1iyki0wq8pj0qbjhw1mbq5njraihhyr7ydcbqzdzwg10dziz7xph",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#cortex-m-rt@0.7.3": "1cfxg502gvcmaczmaij5maxbvaxnda5w6gp14cbin44ksl9yi17f",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#cortex-m@0.7.7": "1fbca698v4gv57mv5fc48jrz8wcy6sv675n6fsrsah4qykc11ilf",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#cpufeatures@0.2.11": "1l0gzsyy576n017g9bf0vkv5hhg9cpz1h1libxyfdlzcgbh0yhnf",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#crc-any@2.5.0": "0wzs26q5cf29fhfnrkrjsr8dpai0rlm4im8b53by8rbrbzzwjbm6",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#crc-catalog@2.4.0": "1xg7sz82w3nxp1jfn425fvn1clvbzb3zgblmxsyqpys0dckp9lqr",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#crc32fast@1.3.2": "03c8f29yx293yf43xar946xbls1g60c207m9drf8ilqhr25vsh5m",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#crc@3.0.1": "1zkx87a5x06xfd6xm5956w4vmdfs0wcxpsn7iwj5jbp2rcapmv46",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#critical-section@1.1.2": "05pj0pvkdyc9r30xxabam4n8zxdbzxcddr0gdypajcbqjgwgynbh",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#crossbeam-deque@0.8.4": "0la7fx9n1vbx3h23va0xmcy36hziql1pkik08s3j3asv4479ma7w",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#crossbeam-epoch@0.9.16": "1anr32r8px0vb65cgwbwp3zhqz69scz5dgq9bmx54w5qa59yjbrd",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#crossbeam-queue@0.3.9": "0lz17pgydh29w8brld8dysi1m4n5bxfpnj8w9bxk0q6xpyyzbg5r",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#crossbeam-utils@0.8.17": "13y7wh993i7q71kg6wcfj65w3rlmizzrz7cqgz1l9whlgw9rcvf0",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#crunchy@0.2.2": "1dx9mypwd5mpfbbajm78xcrg5lirqk7934ik980mmaffg3hdm0bs",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#crypto-common@0.1.6": "1cvby95a6xg7kxdz5ln3rl9xh66nz66w46mm3g56ri1z5x815yqv",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#data-encoding@2.5.0": "1rcbnwfmfxhlshzbn3r7srm3azqha3mn33yxyqxkzz2wpqcjm5ky",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#debug-helper@0.3.13": "0bhnpzpgmg8dkdr27g2b49slf6ca79m4idcb01z2krs0qkifhy7m",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#deflate@0.8.6": "0x6iqlayg129w63999kz97m279m0jj4x4sm6gkqlvmp73y70yxvk",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#der@0.7.8": "070bwiyr80800h31c5zd96ckkgagfjgnrrdmz3dzg2lccsd3dypz",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#deranged@0.3.10": "1p4i64nkadamksa943d6gk39sl1kximz0xr69n408fvsl1q0vcwf",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#digest@0.10.7": "14p2n6ih29x81akj097lvz7wi9b6b9hvls0lwrv7b6xwyy0s5ncy",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#dimensioned@0.7.0": "09ky8s3higkf677lmyqg30hmj66gpg7hx907s6hfvbk2a9av05r5",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#dimensioned@0.8.0": "15s3j4ry943xqlac63bp81sgdk9s3yilysabzww35j9ibmnaic50",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#displaydoc@0.2.4": "0p8pyg10csc782qlwx3znr6qx46ni96m1qh597kmyrf6s3s8axa8",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#dotenvy@0.15.7": "16s3n973n5aqym02692i1npb079n5mb0fwql42ikmwn8wnrrbbqs",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#either@1.9.0": "01qy3anr7jal5lpc20791vxrw0nl6vksb5j7x56q2fycgcyy8sm2",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#embedded-alloc@0.5.1": "05gqqv9nyr33vbd0i8ab2bmfcc5kwgk0msk4pk7w5fncba8igbnx",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#embedded-dma@0.2.0": "0ijld5jblcka4b95s1lwxd9k109nyaap34h44g122ddjbidpwkwr",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#embedded-hal@0.2.7": "1zv6pkgg2yl0mzvh3jp326rhryqfnv4l27h78v7p7maag629i51m",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#encoding_rs@0.8.33": "1qa5k4a0ipdrxq4xg9amms9r9pnnfn7nfh2i9m3mw0ka563b6s3j",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#env_logger@0.10.1": "1kmy9xmfjaqfvd4wkxr1f7d16ld3h9b487vqs2q9r0s8f3kg7cwm",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#equivalent@1.0.1": "1malmx5f4lkfvqasz319lq6gb3ddg19yzf9s8cykfsgzdmyq0hsl",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#errno@0.3.8": "0ia28ylfsp36i27g1qih875cyyy4by2grf80ki8vhgh6vinf8n52",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#etcetera@0.8.0": "0hxrsn75dirbjhwgkdkh0pnpqrnq17ypyhjpjaypgax1hd91nv8k",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#event-listener-strategy@0.4.0": "1lwprdjqp2ibbxhgm9khw7s7y7k4xiqj5i5yprqiks6mnrq4v3lm",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#event-listener@2.5.3": "1q4w3pndc518crld6zsqvvpy9lkzwahp2zgza9kbzmmqh9gif1h2",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#event-listener@4.0.1": "04k7qbi5kgs36s905gxijj41kcr78xs2s6cp6vbg50254z7wvwl4",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#exr@1.71.0": "1a58k179b0h8zpf1cfgc2vl60j2syg7cdgdzp9j6cgmb6lgpcal3",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#fastrand@2.0.1": "19flpv5zbzpf0rk4x77z4zf25in0brg8l7m304d3yrf47qvwxjr5",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#fdeflate@0.3.1": "0s5885wdsih2hqx3hsl7l8cl3666fgsgiwvglifzy229hpydmmk4",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#field-offset@0.3.6": "0zq5sssaa2ckmcmxxbly8qgz3sxpb8g1lwv90sdh1z74qif2gqiq",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#finl_unicode@1.2.0": "1ipdx778849czik798sjbgk5yhwxqybydac18d2g9jb20dxdrkwg",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#fixed@1.24.0": "0zbfwzk4mrfbawpx2ahz533bkb97jzihv7fxiyhpmwf0wzkrrih2",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#flate2@1.0.28": "03llhsh4gqdirnfxxb9g2w9n0721dyn4yjir3pz7z4vjaxb3yc26",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#fluent-bundle@0.15.2": "1zbzm13rfz7fay7bps7jd4j1pdnlxmdzzfymyq2iawf9vq0wchp2",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#fluent-langneg@0.13.0": "152yxplc11vmxkslvmaqak9x86xnavnhdqyhrh38ym37jscd0jic",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#fluent-syntax@0.11.0": "0y6ac7z7sbv51nsa6km5z8rkjj4nvqk91vlghq1ck5c3cjbyvay0",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#fluent@0.16.0": "19s7z0gw95qdsp9hhc00xcy11nwhnx93kknjmdvdnna435w97xk1",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#flume@0.11.0": "10girdbqn77wi802pdh55lwbmymy437k7kklnvj12aaiwaflbb2m",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#fnv@1.0.7": "1hc2mcqha06aibcaza94vbi81j6pr9a1bbxrxjfhc91zin8yr7iz",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#foreign-types-shared@0.1.1": "0jxgzd04ra4imjv8jgkmdq59kj8fsz6w4zxsbmlai34h26225c00",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#foreign-types@0.3.2": "1cgk0vyd7r45cj769jym4a6s7vwshvd0z4bqrb92q1fwibmkkwzn",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#form_urlencoded@1.2.1": "0milh8x7nl4f450s3ddhg57a3flcv6yq8hlkyk6fyr3mcb128dp1",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#frunk@0.4.2": "11v242h7zjka0lckxcffn5pjgr3jzxyljy7ffr0ppy8jkssm38qi",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#frunk_core@0.4.2": "1mjqnn7dclwn8d5g0mrfkg360cgn70a7mm8arx6fc1xxn3x6j95g",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#frunk_derives@0.4.2": "0blsy6aq6rbvxcc0337g15083w24s8539fmv8rwp1qan2qprkymh",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#frunk_proc_macro_helpers@0.1.2": "0b1xl4cfrfai7qi5cb4h9x0967miv3dvwvnsmr1vg4ljhgflmd9m",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#fuchsia-cprng@0.1.1": "1fnkqrbz7ixxzsb04bsz9p0zzazanma8znfdqjvh39n14vapfvx0",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#fugit@0.3.7": "1rzp49521akq49vs9m8llgmdkk08zb77rry10a7srm9797b6l60p",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#futures-channel@0.3.29": "1jxsifvrbqzdadk0svbax71cba5d3qg3wgjq8i160mxmd1kdckgz",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#futures-core@0.3.29": "1308bpj0g36nhx2y6bl4mm6f1gnh9xyvvw2q2wpdgnb6dv3247gb",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#futures-executor@0.3.29": "1g4pjni0sw28djx6mlcfz584abm2lpifz86cmng0kkxh7mlvhkqg",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#futures-intrusive@0.5.0": "0vwm08d1pli6bdaj0i7xhk3476qlx4pll6i0w03gzdnh7lh0r4qx",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#futures-io@0.3.29": "1ajsljgny3zfxwahba9byjzclrgvm1ypakca8z854k2w7cb4mwwb",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#futures-lite@2.2.0": "1flj85i6xm0rjicxixmajrp6rhq8i4bnbzffmrd6h23ln8jshns4",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#futures-macro@0.3.29": "1nwd18i8kvpkdfwm045hddjli0n96zi7pn6f99zi9c74j7ym7cak",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#futures-sink@0.3.29": "05q8jykqddxzp8nwf00wjk5m5mqi546d7i8hsxma7hiqxrw36vg3",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#futures-task@0.3.29": "1qmsss8rb5ppql4qvd4r70h9gpfcpd0bg2b3qilxrnhdkc397lgg",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#futures-util@0.3.29": "0141rkqh0psj4h8x8lgsl1p29dhqr7z2wcixkcbs60z74kb2d5d1",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#futures@0.3.29": "0dak2ilpcmyjrb1j54fzy9hlw6vd10vqljq9gd59pbrq9dqr00ns",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#gcd@2.3.0": "06l4fib4dh4m6gazdrzzzinhvcpcfh05r4i4gzscl03vnjhqnx8x",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#gdk-pixbuf-sys@0.18.0": "1xya543c4ffd2n7aiwwrdxsyc9casdbasafi6ixcknafckm3k61z",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#gdk-pixbuf@0.18.3": "0b68ssdyapvq3bgsna9frabbzhjkvvzz8jld4mxkphr29nvk4vs4",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#gdk4-sys@0.7.2": "1w7yvir565sjrrw828lss07749hfpfsr19jdjzwivkx36brl7ayv",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#gdk4@0.7.3": "1xiacc63p73apr033gjrb9dsk0y4yxnsljwfxbwfry41snd03nvy",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#generic-array@0.11.2": "0a7w8w0rg47nmcinnfzv443lcyb8mplwc251p1jyr5xj2yh6wzv6",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#generic-array@0.14.7": "16lyyrzrljfq424c3n8kfwkqihlimmsg5nhshbbp48np3yjrqr45",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#getrandom@0.2.11": "03q7120cc2kn7ry013i67zmjl2g9q73h1ks5z08hq5v9syz0d47y",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#gif@0.11.4": "01hbw3isapzpzff8l6aw55jnaqx2bcscrbwyf3rglkbbfp397p9y",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#gif@0.12.0": "0ibhjyrslfv9qm400gp4hd50v9ibva01j4ab9bwiq1aycy9jayc0",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#gimli@0.28.1": "0lv23wc8rxvmjia3mcxc6hj9vkqnv1bqq0h8nzjcgf71mrxx6wa2",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#gio-sys@0.18.1": "1lip8z35iy9d184x2qwjxlbxi64q9cpayy7v1p5y9xdsa3w6smip",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#gio@0.18.4": "0wsc6mnx057s4ailacg99dwgna38dbqli5x7a6y9rdw75x9qzz6l",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#glib-build-tools@0.16.3": "1z73bl10zmxwrv16v4f5wcky1f3z5a2v0hknca54al4k2p5ka695",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#glib-build-tools@0.17.10": "05p7ab2vn8962cbchi7a6hndhvw64nqk4w5kpg5z53iizsgdfrbs",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#glib-build-tools@0.18.0": "0p5c2ayiam5bkp9wvq9f9ihwp06nqs5j801npjlwnhrl8rpwac9l",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#glib-macros@0.18.3": "19crnw5a57w02njpbsmdqwbkncl6hw6g3mv554y8dqzcrri3jybj",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#glib-sys@0.18.1": "164qhsfmlzd5mhyxs8123jzbdfldwxbikfpq5cysj3lddbmy4g06",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#glib@0.18.4": "0kjws6ns6dym48nzxz9skhipk55flc2hy5q5kzg4w12wvizvs6wm",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#glob@0.3.1": "16zca52nglanv23q5qrwd5jinw3d3as5ylya6y1pbx47vkxvrynj",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#gloo-timers@0.3.0": "1519157n7xppkk6pdw5w52vy1llzn5iljkqd7q1h5609jv7l7cdv",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#gobject-sys@0.18.0": "0i6fhp3m6vs3wkzyc22rk2cqj68qvgddxmpaai34l72da5xi4l08",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#graphene-rs@0.18.1": "00f4q1ra4haap5i7lazwhkdgnb49fs8adk2nm6ki6mjhl76jh8iv",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#graphene-sys@0.18.1": "0n8zlg7z26lwpnvlqp1hjlgrs671skqwagdpm7r8i1zwx3748hfc",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#grid@0.9.0": "0iswdcxggyxp9m1rz0m7bfg4xacinvn78zp2fgfp0l0079x10d06",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#gsk4-sys@0.7.3": "0mbdlm9qi1hql48rr29vsj9vlqwc7gxg67wg1q19z67azwz9xg8j",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#gsk4@0.7.3": "0zhzs2dkgiinhgc11akpn2harq3x5n1iq21dnc4h689g3lsqx58d",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#gtk4-macros@0.7.2": "0bw3cchiycf7dw1bw4p8946gv38azxy05a5w0ndgcmxnz6fc8znm",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#gtk4-sys@0.7.3": "1f2ylskyqkjdik9fij2m46pra4jagnif5xyalbxfk3334fmc9n2l",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#gtk4@0.7.3": "0hh8nzglmz94v1m1h6vy8z12m6fr7ia467ry0md5fa4p7sm53sss",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#h2@0.3.22": "0y41jlflvw8niifdirgng67zdmic62cjf5m2z69hzrpn5qr50qjd",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#half@2.2.1": "1l1gdlzxgm7wc8xl5fxas20kfi1j35iyb7vfjkghbdzijcvazd02",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#hashbrown@0.14.3": "012nywlg0lj9kwanh69my5x67vjlfmzfi9a0rq4qvis2j8fil3r9",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#hashlink@0.8.4": "1xy8agkyp0llbqk9fcffc1xblayrrywlyrm2a7v93x8zygm4y2g8",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#headers-core@0.2.0": "0ab469xfpd411mc3dhmjhmzrhqikzyj8a17jn5bkj9zfpy0n9xp7",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#headers@0.3.9": "0w62gnwh2p1lml0zqdkrx9dp438881nhz32zrzdy61qa0a9kns06",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#heck@0.4.1": "1a7mqsnycv5z4z5vnv1k34548jzmc0ajic7c1j8jsaspnhw5ql4m",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#hermit-abi@0.3.9": "092hxjbjnq5fmz66grd9plxd0sh6ssg5fhgwwwqbrzgzkjwdycfj",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#hex-string@0.1.0": "02sgrgrbp693jv0v5iga7z47y6aj93cq0ia39finby9x17fw53l4",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#hex@0.4.3": "0w1a4davm1lgzpamwnba907aysmlrnygbqmfis2mqjx5m552a93z",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#hkdf@0.12.4": "1xxxzcarz151p1b858yn5skmhyrvn8fs4ivx5km3i1kjmnr8wpvv",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#hmac@0.12.1": "0pmbr069sfg76z7wsssfk5ddcqd9ncp79fyz6zcm6yn115yc6jbc",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#home@0.5.9": "19grxyg35rqfd802pcc9ys1q3lafzlcjcv2pl2s5q8xpyr5kblg3",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#http-body@0.4.6": "1lmyjfk6bqk6k9gkn1dxq770sb78pqbqshga241hr5p995bb5skw",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#http@0.2.11": "1fwz3mhh86h5kfnr5767jlx9agpdggclq7xsqx930fflzakb2iw9",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#http@1.0.0": "1sllw565jn8r5w7h928nsfqq33x586pyasdfr7vid01scwwgsamk",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#httparse@1.8.0": "010rrfahm1jss3p022fqf3j3jmm72vhn4iqhykahb9ynpaag75yq",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#httpdate@1.0.3": "1aa9rd2sac0zhjqh24c9xvir96g188zldkx0hr6dnnlx5904cfyz",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#humantime@2.1.0": "1r55pfkkf5v0ji1x6izrjwdq9v6sc7bv99xj6srywcar37xmnfls",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#hyper-tls@0.5.0": "01crgy13102iagakf6q4mb75dprzr7ps1gj0l5hxm1cvm7gks66n",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#hyper@0.10.16": "0wwjh9p3mzvg3fss2lqz5r7ddcgl1fh9w6my2j69d6k0lbcm41ha",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#hyper@0.14.28": "107gkvqx4h9bl17d602zkm2dgpfq86l2dr36yzfsi8l3xcsy35mz",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#iana-time-zone-haiku@0.1.2": "17r6jmj31chn7xs9698r122mapq85mfnv98bb4pg6spm0si2f67k",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#iana-time-zone@0.1.58": "081vcr8z8ddhl5r1ywif6grnswk01b2ac4nks2bhn8zzdimvh9l3",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#idna@0.1.5": "0kl4gs5kaydn4v07c6ka33spm9qdh2np0x7iw7g5zd8z1c7rxw1q",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#idna@0.5.0": "1xhjrcjqq0l5bpzvdgylvpkgk94panxgsirzhjnnqfdgc4a9nkb3",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#image@0.23.14": "18gn2f7xp30pf9aqka877knlq308khxqiwjvsccvzaa4f9zcpzr4",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#image@0.24.7": "04d7f25b8nlszfv9a474n4a0al4m2sv9gqj3yiphhqr0syyzsgbg",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#indent_write@2.2.0": "1hqjp80argdskrhd66g9sh542yxy8qi77j6rc69qd0l7l52rdzhc",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#indexmap@2.1.0": "07rxrqmryr1xfnmhrjlz8ic6jw28v6h5cig3ws2c9d0wifhy2c6m",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#intl-memoizer@0.5.1": "0vx6cji8ifw77zrgipwmvy1i3v43dcm58hwjxpb1h29i98z46463",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#intl_pluralrules@7.0.2": "0wprd3h6h8nfj62d8xk71h178q7zfn3srxm787w4sawsqavsg3h7",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#ipnet@2.9.0": "1hzrcysgwf0knf83ahb3535hrkw63mil88iqc6kjaryfblrqylcg",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#iron@0.6.1": "1s4mf8395f693nhwsr0znw3j5frzn56gzllypyl50il85p50ily6",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#is-terminal@0.4.9": "12xgvc7nsrp3pn8hcxajfhbli2l5wnh3679y2fmky88nhj4qj26b",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#itertools@0.10.5": "0ww45h7nxx5kj6z2y6chlskxd1igvs4j507anr6dzg99x1h25zdh",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#itertools@0.12.0": "1c07gzdlc6a1c8p8jrvvw3gs52bss3y58cs2s21d9i978l36pnr5",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#itoa@1.0.10": "0k7xjfki7mnv6yzjrbnbnjllg86acmbnk4izz2jmm1hx2wd6v95i",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#jpeg-decoder@0.1.22": "1wnh0bmmswpgwhgmlizz545x8334nlbmkq8imy9k224ri3am7792",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#jpeg-decoder@0.3.0": "0gkv0zx95i4fr40fj1a10d70lqi6lfyia8r5q8qjxj8j4pj0005w",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#js-sys@0.3.66": "1ji9la5ydg0vy17q54i7dnwc0wwb9zkx662w1583pblylm6wdsff",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#kv-log-macro@1.0.7": "0zwp4bxkkp87rl7xy2dain77z977rvcry1gmr5bssdbn541v7s0d",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#language-tags@0.2.2": "16hrjdpa827carq5x4b8zhas24d8kg4s16m6nmmn1kb7cr5qh7d9",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#lazy_static@1.4.0": "0in6ikhw8mgl33wjv6q6xfrb5b9jr16q8ygjy803fay4zcisvaz2",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#lazycell@1.3.0": "0m8gw7dn30i0zjjpjdyf6pc16c34nl71lpv461mix50x3p70h3c3",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#lebe@0.5.2": "1j2l6chx19qpa5gqcw434j83gyskq3g2cnffrbl3842ymlmpq203",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#libadwaita-sys@0.5.3": "16n6xsy6jhbj0jbpz8yvql6c9b89a99v9vhdz5s37mg1inisl42y",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#libadwaita@0.5.3": "174pzn9dwsk8ikvrhx13vkh0zrpvb3rhg9yd2q5d2zjh0q6fgrrg",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#libc@0.2.151": "1x28f0zgp4zcwr891p8n9ag9w371sbib30vp4y6hi2052frplb9h",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#libloading@0.8.5": "194dvczq4sifwkzllfmw0qkgvilpha7m5xy90gd6i446vcpz4ya9",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#libm@0.2.8": "0n4hk1rs8pzw8hdfmwn96c4568s93kfxqgcqswr7sajd2diaihjf",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#libspa-sys@0.8.0": "07yh4i5grzbxkchg6dnxlwbdw2wm5jnd7ffbhl77jr0388b9f3dz",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#libspa@0.8.0": "044qs48yl0llp2dmrgwxj9y1pgfy09i6fhq661zqqb9a3fwa9wv5",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#libsqlite3-sys@0.27.0": "05pp60ncrmyjlxxjj187808jkvpxm06w5lvvdwwvxd2qrmnj4kng",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#linked_list_allocator@0.10.5": "11k2dv6v5kq45kbvahll434f9iwfw0vsyaycp76q3vh5ahzldyls",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#linux-raw-sys@0.4.12": "0mhlla3gk1jgn6mrq9s255rvvq8a1w3yk2vpjiwsd6hmmy1imkf4",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#lock_api@0.4.11": "0iggx0h4jx63xm35861106af3jkxq06fpqhpkhgw0axi2n38y5iw",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#log@0.3.9": "0jq23hhn5h35k7pa8r7wqnsywji6x3wn1q5q7lif5q536if8v7p1",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#log@0.4.20": "13rf7wphnwd61vazpxr7fiycin6cb1g8fmvgqg18i464p0y1drmm",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#logger@0.4.0": "14xlxvkspcfnspjil0xi63qj5cybxn1hjmr5gq8m4v1g9k5p54bc",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#matches@0.1.10": "1994402fq4viys7pjhzisj4wcw894l53g798kkm2y74laxk0jci5",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#md-5@0.10.6": "1kvq5rnpm4fzwmyv5nmnxygdhhb2369888a06gdc9pxyrzh7x7nq",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#memchr@2.6.4": "0rq1ka8790ns41j147npvxcqcl2anxyngsdimy85ag2api0fwrgn",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#memoffset@0.9.0": "0v20ihhdzkfw1jx00a7zjpk2dcp5qjq6lz302nyqamd9c4f4nqss",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#mime@0.2.6": "1q1s1ax1gaz8ld3513nvhidfwnik5asbs1ma3hp6inp5dn56nqms",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#mime@0.3.17": "16hkibgvb9klh0w0jk5crr5xv90l3wlf77ggymzjmvl1818vnxv8",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#mime_guess@1.8.8": "18qcd5aa3363mb742y7lf39j7ha88pkzbv9ff2qidlsdxsjjjs91",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#mime_guess@2.0.4": "1vs28rxnbfwil6f48hh58lfcx90klcvg68gxdc60spwa4cy2d4j1",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#minimal-lexical@0.2.1": "16ppc5g84aijpri4jzv14rvcnslvlpphbszc7zzp6vfkddf4qdb8",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#miniz_oxide@0.3.7": "0dblrhgbm0wa8jjl8cjp81akaj36yna92df4z1h9b26n3spal7br",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#miniz_oxide@0.4.4": "0jsfv00hl5rmx1nijn59sr9jmjd4rjnjhh4kdjy8d187iklih9d9",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#miniz_oxide@0.7.1": "1ivl3rbbdm53bzscrd01g60l46lz5krl270487d8lhjvwl5hx0g7",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#mio@1.0.2": "1v1cnnn44awxbcfm4zlavwgkvbyg7gp5zzjm8mqf1apkrwflvq40",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#modifier@0.1.0": "0n3fmgli1nsskl0whrfzm1gk0rmwwl6pw1q4nb9sqqmn5h8wkxa1",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#multer@2.1.0": "1hjiphaypj3phqaj5igrzcia9xfmf4rr4ddigbh8zzb96k1bvb01",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#nary_tree@0.4.3": "1iqray1a716995l9mmvz5sfqrwg9a235bvrkpcn8bcqwjnwfv1pv",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#native-tls@0.2.11": "0bmrlg0fmzxaycjpkgkchi93av07v2yf9k33gc12ca9gqdrn28h7",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#nb@0.1.3": "0vyh31pbwrg21f8hz1ipb9i20qwnfwx47gz92i9frdhk0pd327c0",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#nb@1.1.0": "179kbn9l6vhshncycagis7f8mfjppz4fhvgnmcikqz30mp23jm4d",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#nix@0.27.1": "0ly0kkmij5f0sqz35lx9czlbk6zpihb7yh1bsy4irzwfd2f4xc1f",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#no-std-compat@0.4.1": "132vrf710zsdp40yp1z3kgc2ss8pi0z4gmihsz3y7hl4dpd56f5r",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#nom@7.1.3": "0jha9901wxam390jcf5pfa0qqfrgh8li787jx2ip0yk5b8y9hwyj",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#num-bigint-dig@0.8.4": "0lb12df24wgxxbspz4gw1sf1kdqwvpdcpwq4fdlwg4gj41c1k16w",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#num-integer@0.1.45": "1ncwavvwdmsqzxnn65phv6c6nn72pnv9xhpmjd6a429mzf4k6p92",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#num-iter@0.1.43": "0lp22isvzmmnidbq9n5kbdh8gj0zm3yhxv1ddsn5rp65530fc0vx",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#num-rational@0.3.2": "01sgiwny9iflyxh2xz02sak71v2isc3x608hfdpwwzxi3j5l5b0j",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#num-rational@0.4.1": "1c0rb8x4avxy3jvvzv764yk7afipzxncfnqlb10r3h53s34s2f06",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#num-traits@0.2.17": "0z16bi5zwgfysz6765v3rd6whfbjpihx3mhsn4dg8dzj2c221qrr",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#num_cpus@1.16.0": "0hra6ihpnh06dvfvz9ipscys0xfqa9ca9hzp384d5m02ssvgqqa1",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#num_enum@0.5.11": "1japmqhcxwn1d3k7q8jw58y7xfby51s16nzd6dkj483cj2pnqr0z",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#num_enum_derive@0.5.11": "16f7r4jila0ckcgdnfgqyhhb90w9m2pdbwayyqmwcci0j6ygkgyw",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#object@0.32.1": "1c02x4kvqpnl3wn7gz9idm4jrbirbycyqjgiw6lm1g9k77fzkxcw",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#once_cell@1.19.0": "14kvw7px5z96dk4dwdm1r9cqhhy2cyj1l5n5b29mynbb8yr15nrz",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#openssl-macros@0.1.1": "173xxvfc63rr5ybwqwylsir0vq6xsj4kxiv4hmg4c3vscdmncj59",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#openssl-probe@0.1.5": "1kq18qm48rvkwgcggfkqq6pm948190czqc94d6bm2sir5hq1l0gz",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#openssl-sys@0.9.97": "02s670ir38fsavphdna07144y41dkvrcfkwnjzg82zfrrlsavsn3",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#openssl@0.10.61": "0idv3n9n9f2sxq8cqzxvq44633vg5sx4n9q1p3g6dn66ikf1k13b",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#pango-sys@0.18.0": "1iaxalcaaj59cl9n10svh4g50v8jrc1a36kd7n9yahx8j7ikfrs3",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#pango@0.18.3": "1r5ygq7036sv7w32kp8yxr6vgggd54iaavh3yckanmq4xg0px8kw",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#panic-halt@0.2.0": "04nqaa97ph20ppyy58grwr23hrbw83pn0gf7apf73rdx1q7595ny",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#parking@2.2.0": "1blwbkq6im1hfxp5wlbr475mw98rsyc0bbr2d5n16m38z253p0dv",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#parking_lot@0.12.1": "13r2xk7mnxfc5g0g6dkdxqdqad99j7s7z8zhzz4npw5r0g0v4hip",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#parking_lot_core@0.9.9": "13h0imw1aq86wj28gxkblhkzx6z1gk8q18n0v76qmmj6cliajhjc",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#parse-zoneinfo@0.3.0": "0h8g6jy4kckn2gk8sd5adaws180n1ip65xhzw5jxlq4w8ibg41f7",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#paste@1.0.14": "0k7d54zz8zrz0623l3xhvws61z5q2wd3hkwim6gylk8212placfy",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#pem-rfc7468@0.7.0": "04l4852scl4zdva31c1z6jafbak0ni5pi0j38ml108zwzjdrrcw8",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#percent-encoding@1.0.1": "0cgq08v1fvr6bs5fvy390cz830lq4fak8havdasdacxcw790s09i",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#percent-encoding@2.3.1": "0gi8wgx0dcy8rnv1kywdv98lwcx67hz0a0zwpib5v2i08r88y573",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#phf@0.11.2": "1p03rsw66l7naqhpgr1a34r9yzi1gv9jh16g3fsk6wrwyfwdiqmd",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#phf@0.7.24": "066xwv4dr6056a9adlkarwp4n94kbpwngbmd47ngm3cfbyw49nmk",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#phf_codegen@0.11.2": "0nia6h4qfwaypvfch3pnq1nd2qj64dif4a6kai3b7rjrsf49dlz8",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#phf_codegen@0.7.24": "0zjiblicfm0nrmr2xxrs6pnf6zz2394wgch6dcbd8jijkq98agmh",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#phf_generator@0.11.2": "1c14pjyxbcpwkdgw109f7581cc5fa3fnkzdq1ikvx7mdq9jcrr28",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#phf_generator@0.7.24": "0qi62gxk3x3whrmw5c4i71406icqk11qmpgln438p6qm7k4lqdh9",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#phf_shared@0.11.2": "0azphb0a330ypqx3qvyffal5saqnks0xvl8rj73jlk3qxxgbkz4h",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#phf_shared@0.7.24": "18371fla0vsj7d6d5rlfb747xbr2in11ar9vgv5qna72bnhp2kr3",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#pin-project-internal@1.1.3": "01a4l3vb84brv9v7wl71chzxra2kynm6yvcjca66xv3ij6fgsna3",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#pin-project-lite@0.2.13": "0n0bwr5qxlf0mhn2xkl36sy55118s9qmvx2yl5f3ixkb007lbywa",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#pin-project@1.1.3": "08k4cpy8q3j93qqgnrbzkcgpn7g0a88l4a9nm33kyghpdhffv97x",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#pin-utils@0.1.0": "117ir7vslsl2z1a7qzhws4pd01cg2d3338c47swjyvqv2n60v1wb",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#pio@0.2.1": "1qvq03nbx6vjix7spr5fcxcbxw39flm1y72kxl1g728gnna9dq3n",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#piper@0.2.1": "1m45fkdq7q5l9mv3b0ra10qwm0kb67rjp2q8y91958gbqjqk33b6",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#pipewire-sys@0.8.0": "04hiy3rl8v3j2dfzp04gr7r8l5azzqqsvqdzwa7sipdij27ii7l4",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#pipewire@0.8.0": "1nldg1hz4v0qr26lzdxqpvrac4zbc3pb6436sl392425bjx4brh8",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#pkcs1@0.7.5": "0zz4mil3nchnxljdfs2k5ab1cjqn7kq5lqp62n9qfix01zqvkzy8",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#pkcs8@0.10.2": "1dx7w21gvn07azszgqd3ryjhyphsrjrmq5mmz1fbxkj5g0vv4l7r",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#pkg-config@0.3.27": "0r39ryh1magcq4cz5g9x88jllsnxnhcqr753islvyk4jp9h2h1r6",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#plugin@0.2.6": "1q7nghkpvxxr168y2jnzh3w7qc9vfrby9n7ygy3xpj0bj71hsshs",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#png@0.16.8": "1ipl44q3vy4kvx6j296vk7d4v8gvcg203lrkvvixwixq1j98fciw",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#png@0.17.10": "0r5a8a25ad0jq2pkp2zbab3wwhpgp6jmdg6d0ybjnw6kilnvyxfx",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#polling@3.4.0": "052am20b5r03nwhpnjw86rv3dwsdabvb07anv3fqxfbs65r4w19h",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#powerfmt@0.2.0": "14ckj2xdpkhv3h6l5sdmb9f1d57z8hbfpdldjc2vl5givq2y77j3",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#ppv-lite86@0.2.17": "1pp6g52aw970adv3x2310n7glqnji96z0a9wiamzw89ibf0ayh2v",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#pretty_env_logger@0.5.0": "076w9dnvcpx6d3mdbkqad8nwnsynb7c8haxmscyrz7g3vga28mw6",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#proc-macro-crate@1.3.1": "069r1k56bvgk0f58dm5swlssfcp79im230affwk6d9ck20g04k3z",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#proc-macro-crate@2.0.1": "06jbv5w6s04dbjbwq0iv7zil12ildf3w8dvvb4pqvhig4gm5zp4p",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#proc-macro-error-attr@1.0.4": "0sgq6m5jfmasmwwy8x4mjygx5l7kp8s4j60bv25ckv2j1qc41gm1",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#proc-macro-error@1.0.4": "1373bhxaf0pagd8zkyd03kkx6bchzf6g0dkwrwzsnal9z47lj9fs",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#proc-macro2@1.0.78": "1bjak27pqdn4f4ih1c9nr3manzyavsgqmf76ygw9k76q8pb2lhp2",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#proptest@1.4.0": "1gzmw40pgmwzb7x6jsyr88z5w151snv5rp1g0dlcp1iw3h9pdd1i",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#qoi@0.4.1": "00c0wkb112annn2wl72ixyd78mf56p4lxkhlmsggx65l3v3n8vbz",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#quick-error@1.2.3": "1q6za3v78hsspisc197bg3g7rpc989qycy8ypr8ap8igv10ikl51",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#quote@1.0.35": "1vv8r2ncaz4pqdr78x7f138ka595sp2ncr1sa2plm4zxbsmwj7i9",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rand@0.3.23": "0v679h38pjjqj5h4md7v2slsvj6686qgcn7p9fbw3h43iwnk1b34",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rand@0.4.6": "14qjfv3gggzhnma20k0sc1jf8y6pplsaq7n1j9ls5c8kf2wl0a2m",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rand@0.6.5": "1jl4449jcl4wgmzld6ffwqj5gwxrp8zvx8w573g1z368qg6xlwbd",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rand@0.8.5": "013l6931nn7gkc23jz5mm3qdhf93jjf0fg64nz2lp4i51qd8vbrl",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rand_chacha@0.1.1": "1vxwyzs4fy1ffjc8l00fsyygpiss135irjf7nyxgq2v0lqf3lvam",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rand_chacha@0.3.1": "123x2adin558xbhvqb8w4f6syjsdkmqff8cxwhmjacpsl1ihmhg6",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rand_core@0.3.1": "0jzdgszfa4bliigiy4hi66k7fs3gfwi2qxn8vik84ph77fwdwvvs",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rand_core@0.4.2": "1p09ynysrq1vcdlmcqnapq4qakl2yd1ng3kxh3qscpx09k2a6cww",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rand_core@0.6.4": "0b4j2v4cb5krak1pv6kakv4sz6xcwbrmy2zckc32hsigbrwy82zc",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rand_hc@0.1.0": "1i0vl8q5ddvvy0x8hf1zxny393miyzxkwqnw31ifg6p0gdy6fh3v",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rand_isaac@0.1.1": "027flpjr4znx2csxk7gxb7vrf9c7y5mydmvg5az2afgisp4rgnfy",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rand_jitter@0.1.4": "16z387y46bfz3csc42zxbjq89vcr1axqacncvv8qhyy93p4xarhi",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rand_os@0.1.3": "0wahppm0s64gkr2vmhcgwc0lij37in1lgfxg5rbgqlz0l5vgcxbv",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rand_pcg@0.1.2": "0i0bdla18a8x4jn1w0fxsbs3jg7ajllz6azmch1zw33r06dv1ydb",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rand_xorshift@0.1.1": "0p2x8nr00hricpi2m6ca5vysiha7ybnghz79yqhhx6sl4gkfkxyb",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rand_xorshift@0.3.0": "13vcag7gmqspzyabfl1gr9ykvxd2142q2agrj8dkyjmfqmgg4nyj",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rayon-core@1.12.0": "1vaq0q71yfvcwlmia0iqf6ixj2fibjcf2xjy92n1m1izv1mgpqsw",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rayon@1.8.0": "1cfdnvchf7j4cpha5jkcrrsr61li9i9lp5ak7xdq6d3pvc1xn9ww",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rdrand@0.4.0": "1cjq0kwx1bk7jx3kzyciiish5gqsj7620dm43dc52sr8fzmm9037",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#redox_syscall@0.4.1": "1aiifyz5dnybfvkk4cdab9p2kmphag1yad6iknc7aszlxxldf8j7",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#regex-automata@0.4.3": "0gs8q9yhd3kcg4pr00ag4viqxnh5l7jpyb9fsfr8hzh451w4r02z",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#regex-syntax@0.8.2": "17rd2s8xbiyf6lb4aj2nfi44zqlj98g2ays8zzj2vfs743k79360",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#regex@1.10.2": "0hxkd814n4irind8im5c9am221ri6bprx49nc7yxv02ykhd9a2rq",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#remove_dir_all@0.5.3": "1rzqbsgkmr053bxxl04vmvsd1njyz0nxvly97aip6aa2cmb15k9s",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#reqwest@0.11.23": "0hgvzb7r46656r9vqhl5qk1kbr2xzjb91yr2cb321160ka6sxc9p",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rp-pico@0.8.0": "0mmx8dyl0q1a9fgz12hrvwd7civqbd1j7g1w5c5i6pcfdwg7fhb3",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rp2040-boot2@0.3.0": "08dv9ndvdzyjz4wdlxcikf1m1s6wwi80027ldkihx59zyr2g74kw",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rp2040-hal-macros@0.1.0": "0piaczzlbrfdhidnqkg04xs1rzal3w3zjplrh6pf3vwpwiir0iw6",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rp2040-hal@0.9.2": "1jk725cf6nx6rhn06swbx47yaq3j134m0hpnv47p5mkdgspbkwhz",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rp2040-pac@0.5.0": "0k3fm4fww6gcy7w7zwbmmqn9wzz4sih13l1m93sl7x8mb0vxin8j",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rsa@0.9.6": "1z0d1aavfm0v4pv8jqmqhhvvhvblla1ydzlvwykpc3mkzhj523jx",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rustc-demangle@0.1.23": "0xnbk2bmyzshacjm2g1kd4zzv2y2az14bw3sjccq5qkpmsfvn9nn",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rustc-hash@1.1.0": "1qkc5khrmv5pqi5l5ca9p5nl5hs742cagrndhbrlk3dhlrx3zm08",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rustc_version@0.2.3": "02h3x57lcr8l2pm0a645s9whdh33pn5cnrwvn5cb57vcrc53x3hk",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rustc_version@0.4.0": "0rpk9rcdk405xhbmgclsh4pai0svn49x35aggl4nhbkd4a2zb85z",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rustix@0.38.28": "05m3vacvbqbg6r6ksmx9k5afpi0lppjdv712crrpsrfax2jp5rbj",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#rusty-fork@0.3.0": "0kxwq5c480gg6q0j3bg4zzyfh2kwmc3v2ba94jw8ncjc8mpcqgfb",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#ryu@1.0.16": "0k7b90xr48ag5bzmfjp82rljasw2fx28xr3bg1lrpx7b5sljm3gr",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#safemem@0.3.3": "0wp0d2b2284lw11xhybhaszsczpbq1jbdklkxgifldcknmy3nw7g",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#schannel@0.1.22": "126zy5jb95fc5hvzyjwiq6lc81r08rdcn6affn00ispp9jzk6dqc",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#scoped-tls@1.0.1": "15524h04mafihcvfpgxd8f4bgc3k95aclz8grjkg9a0rxcvn9kz1",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#scoped_threadpool@0.1.9": "1a26d3lk40s9mrf4imhbik7caahmw2jryhhb6vqv6fplbbgzal8x",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#scopeguard@1.2.0": "0jcz9sd47zlsgcnm1hdw0664krxwb5gczlif4qngj2aif8vky54l",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#security-framework-sys@2.9.1": "0yhciwlsy9dh0ps1gw3197kvyqx1bvc4knrhiznhid6kax196cp9",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#security-framework@2.9.2": "1pplxk15s5yxvi2m1sz5xfmjibp96cscdcl432w9jzbk0frlzdh5",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#self_cell@0.10.3": "0pci3zh23b7dg6jmlxbn8k4plb7hcg5jprd1qiz0rp04p1ilskp1",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#self_cell@1.0.2": "1rmdglwnd77wcw2gv76finpgzjhkynx422d0jpahrf2fsqn37273",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#semver-parser@0.7.0": "18vhypw6zgccnrlm5ps1pwa0khz7ry927iznpr88b87cagr1v2iq",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#semver@0.9.0": "00q4lkcj0rrgbhviv9sd4p6qmdsipkwkbra7rh11jrhq5kpvjzhx",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#semver@1.0.20": "140hmbfa743hbmah1zjf07s8apavhvn04204qjigjiz5w6iscvw3",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#serde@0.9.15": "1bsla8l5xr9pp5sirkal6mngxcq6q961km88jvf339j5ff8j7dil",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#serde@1.0.209": "029yqqbb3c8v3gc720fhxn49dhgvb88zbyprdg5621riwzzy1z4r",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#serde_derive@1.0.209": "0w114ksg1ymnmqdisd0g1j3g8jgz6pam45xg6yb47dfpkybip0x5",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#serde_json@1.0.127": "1b99lgg1d986gwz5fbmmzmvjmqg5bx0lzmhy6rqp5gc2kxnw0hw0",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#serde_spanned@0.6.5": "1hgh6s3jjwyzhfk3xwb6pnnr1misq9nflwq0f026jafi37s24dpb",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#serde_urlencoded@0.7.1": "1zgklbdaysj3230xivihs30qi5vkhigg323a9m62k8jwf4a1qjfk",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#sha1@0.10.6": "1fnnxlfg08xhkmwf2ahv634as30l1i3xhlhkvxflmasi5nd85gz3",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#sha2@0.10.8": "1j1x78zk9il95w9iv46dh9wm73r6xrgj32y6lzzw7bxws9dbfgbr",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#shlex@1.3.0": "0r1y6bv26c1scpxvhg2cabimrmwgbp4p3wy6syj9n0c4s3q2znhg",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#signal-hook-registry@1.4.1": "18crkkw5k82bvcx088xlf5g4n3772m24qhzgfan80nda7d3rn8nq",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#signature@2.2.0": "1pi9hd5vqfr3q3k49k37z06p7gs5si0in32qia4mmr1dancr6m3p",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#simd-adler32@0.3.7": "1zkq40c3iajcnr5936gjp9jjh1lpzhy44p3dq3fiw75iwr1w2vfn",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#siphasher@0.2.3": "1b53m53l24lyhr505lwqzrpjyq5qfnic71mynrcfvm43rybf938b",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#siphasher@0.3.11": "03axamhmwsrmh0psdw3gf7c0zc4fyl5yjxfifz9qfka6yhkqid9q",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#slab@0.4.9": "0rxvsgir0qw5lkycrqgb1cxsvxzjv9bmx73bk5y42svnzfba94lg",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#smallvec@1.11.2": "0w79x38f7c0np7hqfmzrif9zmn0avjvvm31b166zdk9d1aad1k2d",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#snowflake@1.3.0": "1wadr7bxdxbmkbqkqsvzan6q1h3mxqpxningi3ss3v9jaav7n817",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#socket2@0.5.5": "1sgq315f1njky114ip7wcy83qlphv9qclprfjwvxcpfblmcsqpvv",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#spin@0.5.2": "0b84m6dbzrwf2kxylnw82d3dr8w06av7rfkr8s85fb5f43rwyqvf",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#spin@0.9.8": "0rvam5r0p3a6qhc18scqpvpgb3ckzyqxpgdfyjnghh8ja7byi039",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#spki@0.7.3": "17fj8k5fmx4w9mp27l970clrh5qa7r5sjdvbsln987xhb34dc7nr",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#sqlformat@0.2.3": "0v0p70wjdshj18zgjjac9xlx8hmpx33xhq7g8x9rg4s4gjyvg0ff",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#sqlx-core@0.7.3": "1gdz44yb9qwxv4xl4hv6w4vbqx0zzdlzsf9j9gcj1qir6wy0ljyq",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#sqlx-macros-core@0.7.3": "0h88wahkxa6nam536lhwr1y0yxlr6la8b1x0hs0n88v790clbgfh",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#sqlx-macros@0.7.3": "19gjwisiym07q7ibkp9nkvvbywjh0r5rc572msvzyzadvh01r5l9",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#sqlx-mysql@0.7.3": "190ygz5a3pqcd9vvqjv2i4r1xh8vi53j4272yrld07zpblwrawg3",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#sqlx-postgres@0.7.3": "090wm9s6mm53ggn1xwr183cnn8yxly8rgcksdk4hrlfcnz1hmb6n",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#sqlx-sqlite@0.7.3": "143laha7wf8dmi0xwycwqmvxdcnb25dq7jnqrsgvmis8v6vpc291",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#sqlx@0.7.3": "1kv3hyx7izmmsjqh3l47zrfhjlcblpg20cvnk7pr8dm7klkkr86v",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#stable_deref_trait@1.2.0": "1lxjr8q2n534b2lhkxd6l6wcddzjvnksi58zv11f9y0jjmr15wd8",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#stringprep@0.1.4": "1rkfsf7riynsmqj3hbldfrvmna0i9chx2sz39qdpl40s4d7dfhdv",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#strsim@0.10.0": "08s69r4rcrahwnickvi0kq49z524ci50capybln83mg6b473qivk",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#subtle@2.5.0": "1g2yjs7gffgmdvkkq0wrrh0pxds3q0dv6dhkw9cdpbib656xdkc1",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#syn@1.0.109": "0ds2if4600bd59wsv7jjgfkayfzy3hnazs394kz6zdkmna8l3dkj",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#syn@2.0.48": "0gqgfygmrxmp8q32lia9p294kdd501ybn6kn2h4gqza0irik2d8g",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#system-configuration-sys@0.5.0": "1jckxvdr37bay3i9v52izgy52dg690x5xfg3hd394sv2xf4b2px7",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#system-configuration@0.5.1": "1rz0r30xn7fiyqay2dvzfy56cvaa3km74hnbz2d72p97bkf3lfms",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#system-deps@6.2.0": "0c836abhh3k8yn5ymg8wx383ay7n731gkrbbp3gma352yq7mhb9a",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#target-lexicon@0.12.12": "02lk65ik5ffb8vl9qzq02v0df8kxrp16zih78a33mji49789zhql",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#tempdir@0.3.7": "1n5n86zxpgd85y0mswrp5cfdisizq2rv3la906g6ipyc03xvbwhm",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#tempfile@3.8.1": "1r88v07zdafzf46y63vs39rmzwl4vqd4g2c5qarz9mqa8nnavwby",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#termcolor@1.4.0": "0jfllflbxxffghlq6gx4csv0bv0qv77943dcx01h9zssy39w66zz",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#thiserror-impl@1.0.51": "1ps9ylhlk2vn19fv3cxp40j3wcg1xmb117g2z2fbf4vmg2bj4x01",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#thiserror@1.0.51": "1drvyim21w5sga3izvnvivrdp06l2c24xwbhp0vg1mhn2iz2277i",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#tiff@0.6.1": "0ds48vs919ccxa3fv1www7788pzkvpg434ilqkq7sjb5dmqg8lws",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#tiff@0.9.0": "04b2fd3clxm0pmdlfip8xj594zyrsfwmh641i6x1gfiz9l7jn5vd",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#time-core@0.1.2": "1wx3qizcihw6z151hywfzzyd1y5dl804ydyxci6qm07vbakpr4pg",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#time-macros@0.2.16": "0gx4ngf5g7ydqa8lf7kh9sy72rd4dhvpi31y1jvswi0288rpw696",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#time@0.1.45": "0nl0pzv9yf56djy8y5dx25nka5pr2q1ivlandb3d24pksgx7ly8v",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#time@0.3.31": "0gjqcdsdbh0r5vi4c2vrj5a6prdviapx731wwn07cvpqqd1blmzn",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#tinystr@0.7.5": "1khf3j95bwwksj2hw76nlvwlwpwi4d1j421lj6x35arqqprjph43",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#tinyvec@1.6.0": "0l6bl2h62a5m44jdnpn7lmj14rd44via8180i7121fvm73mmrk47",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#tinyvec_macros@0.1.1": "081gag86208sc3y6sdkshgw3vysm5d34p431dzw0bshz66ncng0z",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#tokio-macros@2.4.0": "0lnpg14h1v3fh2jvnc8cz7cjf0m7z1xgkwfpcyy632g829imjgb9",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#tokio-native-tls@0.3.1": "1wkfg6zn85zckmv4im7mv20ca6b1vmlib5xwz9p7g19wjfmpdbmv",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#tokio-stream@0.1.14": "0hi8hcwavh5sdi1ivc9qc4yvyr32f153c212dpd7sb366y6rhz1r",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#tokio-tungstenite@0.21.0": "0f5wj0crsx74rlll97lhw0wk6y12nhdnqvmnjx002hjn08fmcfy8",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#tokio-util@0.7.10": "058y6x4mf0fsqji9rfyb77qbfyc50y4pk2spqgj6xsyr693z66al",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#tokio@1.39.3": "1xgzhj7bxqqpjaabjkgsx8hi0f600bzj4iyp9f0a9gr3k6dwkawv",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#toml@0.8.2": "0g9ysjaqvm2mv8q85xpqfn7hi710hj24sd56k49wyddvvyq8lp8q",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#toml_datetime@0.6.3": "0jsy7v8bdvmzsci6imj8fzgd255fmy5fzp6zsri14yrry7i77nkw",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#toml_edit@0.19.15": "08bl7rp5g6jwmfpad9s8jpw8wjrciadpnbaswgywpr9hv9qbfnqv",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#toml_edit@0.20.2": "0f7k5svmxw98fhi28jpcyv7ldr2s3c867pjbji65bdxjpd44svir",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#tower-service@0.3.2": "0lmfzmmvid2yp2l36mbavhmqgsvzqf7r2wiwz73ml4xmwaf1rg5n",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#tracing-attributes@0.1.27": "1rvb5dn9z6d0xdj14r403z0af0bbaqhg02hq4jc97g5wds6lqw1l",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#tracing-core@0.1.32": "0m5aglin3cdwxpvbg6kz0r9r0k31j48n0kcfwsp6l49z26k3svf0",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#tracing@0.1.40": "1vv48dac9zgj9650pg2b4d0j3w6f3x9gbggf43scq5hrlysklln3",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#traitobject@0.1.0": "0yb0n8822mr59j200fyr2fxgzzgqljyxflx9y8bdy3rlaqngilgg",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#try-lock@0.2.5": "0jqijrrvm1pyq34zn1jmy2vihd4jcrjlvsh4alkjahhssjnsn8g4",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#tungstenite@0.21.0": "1qaphb5kgwgid19p64grhv2b9kxy7f1059yy92l9kwrlx90sdwcy",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#type-map@0.4.0": "0ilsqq7pcl3k9ggxv2x5fbxxfd6x7ljsndrhc38jmjwnbr63dlxn",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#typeable@0.1.2": "11w8dywgnm32hb291izjvh4zjd037ccnkk77ahk63l913zwzc40l",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#typemap@0.3.3": "1xm1gbvz9qisj1l6d36hrl9pw8imr8ngs6qyanjnsad3h0yfcfv5",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#typenum@1.17.0": "09dqxv69m9lj9zvv6xw5vxaqx15ps0vxyy5myg33i0kbqvq0pzs2",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#typeshare-annotation@1.0.2": "1adpfhyz3lqjjbq2ym69mv62ymqyd5651gxlqdy8aa446l70srzw",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#typeshare@1.0.1": "1mi7snkx2b4g84x8vx38v1myg5r6g48c865j0nz5zcsc8lpilkgl",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#unarray@0.1.4": "154smf048k84prsdgh09nkm2n0w0336v84jd4zikyn6v6jrqbspa",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#unic-langid-impl@0.9.4": "1ijvqmsrg6qw3b1h9bh537pvwk2jn2kl6ck3z3qlxspxcch5mmab",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#unic-langid@0.9.4": "05pm5p3j29c9jw9a4dr3v64g3x6g3zh37splj47i7vclszk251r3",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#unicase@1.4.2": "0cwazh4qsmm9msckjk86zc1z35xg7hjxjykrgjalzdv367w6aivz",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#unicase@2.7.0": "12gd74j79f94k4clxpf06l99wiv4p30wjr0qm04ihqk9zgdd9lpp",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#unicode-bidi@0.3.14": "05i4ps31vskq1wdp8yf315fxivyh1frijly9d4gb5clygbr2h9bg",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#unicode-ident@1.0.12": "0jzf1znfpb2gx8nr8mvmyqs1crnv79l57nxnbiszc7xf7ynbjm1k",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#unicode-normalization@0.1.22": "08d95g7b1irc578b2iyhzv4xhsa4pfvwsqxcl9lbcpabzkq16msw",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#unicode-segmentation@1.10.1": "0dky2hm5k51xy11hc3nk85p533rvghd462b6i0c532b7hl4j9mhx",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#unicode-width@0.1.13": "0p92vl8n7qc8mxz45xn6qbgi0259z96n32a158l6vj5bywwdadh3",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#unicode_categories@0.1.1": "0kp1d7fryxxm7hqywbk88yb9d1avsam9sg76xh36k5qx2arj9v1r",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#unsafe-any@0.4.2": "0zwwphsqkw5qaiqmjwngnfpv9ym85qcsyj7adip9qplzjzbn00zk",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#url@1.7.2": "0nim1c90mxpi9wgdw2xh8dqd72vlklwlzam436akcrhjac6pqknx",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#url@2.5.0": "0cs65961miawncdg2z20171w0vqrmraswv2ihdpd8lxp7cp31rii",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#urlencoding@2.1.3": "1nj99jp37k47n0hvaz5fvz7z6jd0sb4ppvfy3nphr1zbnyixpy6s",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#usb-device@0.2.9": "0205a850jhw9gb96scwfx1k4iwpjvighvz3m80mjkda9r2nw6v0z",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#utf-8@0.7.6": "1a9ns3fvgird0snjkd3wbdhwd3zdpc2h5gpyybrfr6ra5pkqxk09",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#utf8parse@0.2.1": "02ip1a0az0qmc2786vxk2nqwsgcwf17d3a38fkf0q7hrmwh9c6vi",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#uuid@0.4.0": "0cdj2v6v2yy3zyisij69waksd17cyir1n58kwyk1n622105wbzkw",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#uuid@0.8.2": "1dy4ldcp7rnzjy56dxh7d2sgrcvn4q77y0a8r0a48946h66zjp5w",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#uuid@1.6.1": "0q45jxahvysldn3iy04m8xmr8hgig80855y9gq9di8x72v7myfay",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#value-bag@1.7.0": "02r8wccrzi3bzlkrslkcfw9pwp8kwif9szif2i9arn9dzqx44vhj",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#vcell@0.1.3": "00n0ss2z3rh0ihig6d4w7xp72g58f7g1m6s5v4h3nc6jacdrqhvp",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#vcpkg@0.2.15": "09i4nf5y8lig6xgj3f7fyrvzd3nlaw4znrihw8psidvv5yk4xkdc",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#version-compare@0.1.1": "0acg4pmjdbmclg0m7yhijn979mdy66z3k8qrcnvn634f1gy456jp",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#version_check@0.1.5": "1pf91pvj8n6akh7w6j5ypka6aqz08b3qpzgs0ak2kjf4frkiljwi",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#version_check@0.9.4": "0gs8grwdlgh0xq660d7wr80x14vxbizmd8dbp29p2pdncx8lp1s9",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#void@1.0.2": "0zc8f0ksxvmhvgx4fdg0zyn6vdnbxd2xv9hfx4nhzg6kbs4f80ka",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#volatile-register@0.2.2": "1k0rkm81qyhn4r8f03z0sch2kyikkgjjfalpaami9c08c8m7whyy",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#wait-timeout@0.2.0": "1xpkk0j5l9pfmjfh1pi0i89invlavfrd9av5xp0zhxgb29dhy84z",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#want@0.3.1": "03hbfrnvqqdchb5kgxyavb9jabwza0dmh2vw5kg0dq8rxl57d9xz",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#warp@0.3.7": "07137zd13lchy5hxpspd0hs6sl19b0fv2zc1chf02nwnzw1d4y23",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#wasi@0.10.0+wasi-snapshot-preview1": "07y3l8mzfzzz4cj09c8y90yak4hpsi9g7pllyzpr6xvwrabka50s",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#wasi@0.11.0+wasi-snapshot-preview1": "08z4hxwkpdpalxjps1ai9y7ihin26y9f476i53dv98v45gkqg3cw",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#wasm-bindgen-backend@0.2.89": "09l8lyylsdssz993h4fzja69zpvpykaw84fivs210fjgwqjzcmhv",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#wasm-bindgen-futures@0.4.39": "04lsxpw4jqfwh7c0crzx0smj52nvwp1w3bh4098sq90149da2dmc",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#wasm-bindgen-macro-support@0.2.89": "10sj1gr2naxv5q116yjb929hhpvz45dxbkvyk8hyc2lknzy85szh",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#wasm-bindgen-macro@0.2.89": "1cl2w7k5jn2jbd5kx613c8k8vjvda22hfgcgx7y2mk93fbrxnqh1",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#wasm-bindgen-shared@0.2.89": "17s5rppad113c6ggkaq8c3cg7a3zz15i78wxcg6mcl1n15iv7fbs",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#wasm-bindgen@0.2.89": "0kh6akdldy13z9xqj0skz6b4npq1d98bjkgzb8ccq59hibvd9l0f",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#web-sys@0.3.66": "03q1z22djv5ncqkyydcvnchmdsl5gvnyzcyixkxnifw6xi24mhjh",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#weezl@0.1.7": "1frdbq6y5jn2j93i20hc80swpkj30p1wffwxj1nr4fp09m6id4wi",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#whoami@1.4.1": "0l6ca9pl92wmngsn1dh9ih716v216nmn2zvcn94k04x9p1b3gz12",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#winapi-i686-pc-windows-gnu@0.4.0": "1dmpa6mvcvzz16zg6d5vrfy4bxgg541wxrcip7cnshi06v38ffxc",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#winapi-util@0.1.6": "15i5lm39wd44004i9d5qspry2cynkrpvwzghr6s2c3dsk28nz7pj",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#winapi-x86_64-pc-windows-gnu@0.4.0": "0gqq64czqb64kskjryj8isp62m2sgvx25yyj3kpc2myh85w24bki",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#winapi@0.3.9": "06gl025x418lchw1wxj64ycr7gha83m44cjr5sarhynd9xkrm0sw",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#windows-core@0.51.1": "0r1f57hsshsghjyc7ypp2s0i78f7b1vr93w68sdb8baxyf2czy7i",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#windows-sys@0.48.0": "1aan23v5gs7gya1lc46hqn9mdh8yph3fhxmhxlw36pn6pqc28zb7",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#windows-sys@0.52.0": "0gd3v4ji88490zgb6b5mq5zgbvwv7zx1ibn8v3x83rwcdbryaar8",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#windows-targets@0.48.5": "034ljxqshifs1lan89xwpcy1hp0lhdh4b5n0d2z4fwjx2piacbws",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#windows-targets@0.52.0": "1kg7a27ynzw8zz3krdgy6w5gbqcji27j1sz4p7xk2j5j8082064a",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#windows_aarch64_gnullvm@0.48.5": "1n05v7qblg1ci3i567inc7xrkmywczxrs1z3lj3rkkxw18py6f1b",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#windows_aarch64_gnullvm@0.52.0": "1shmn1kbdc0bpphcxz0vlph96bxz0h1jlmh93s9agf2dbpin8xyb",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#windows_aarch64_msvc@0.48.5": "1g5l4ry968p73g6bg6jgyvy9lb8fyhcs54067yzxpcpkf44k2dfw",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#windows_aarch64_msvc@0.52.0": "1vvmy1ypvzdvxn9yf0b8ygfl85gl2gpcyvsvqppsmlpisil07amv",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#windows_i686_gnu@0.48.5": "0gklnglwd9ilqx7ac3cn8hbhkraqisd0n83jxzf9837nvvkiand7",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#windows_i686_gnu@0.52.0": "04zkglz4p3pjsns5gbz85v4s5aw102raz4spj4b0lmm33z5kg1m2",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#windows_i686_msvc@0.48.5": "01m4rik437dl9rdf0ndnm2syh10hizvq0dajdkv2fjqcywrw4mcg",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#windows_i686_msvc@0.52.0": "16kvmbvx0vr0zbgnaz6nsks9ycvfh5xp05bjrhq65kj623iyirgz",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#windows_x86_64_gnu@0.48.5": "13kiqqcvz2vnyxzydjh73hwgigsdr2z1xpzx313kxll34nyhmm2k",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#windows_x86_64_gnu@0.52.0": "1zdy4qn178sil5sdm63lm7f0kkcjg6gvdwmcprd2yjmwn8ns6vrx",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#windows_x86_64_gnullvm@0.48.5": "1k24810wfbgz8k48c2yknqjmiigmql6kk3knmddkv8k8g1v54yqb",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#windows_x86_64_gnullvm@0.52.0": "17lllq4l2k1lqgcnw1cccphxp9vs7inq99kjlm2lfl9zklg7wr8s",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#windows_x86_64_msvc@0.48.5": "0f4mdp895kkjh9zv8dxvn4pc10xr7839lf5pa9l0193i2pkgr57d",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#windows_x86_64_msvc@0.52.0": "012wfq37f18c09ij5m6rniw7xxn5fcvrxbqd0wd8vgnl3hfn9yfz",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#winnow@0.5.30": "1ifj9vnqna5qp0d7nb9mrinzf8j7zi1m0gv75870vm91jyw3sp4v",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#winreg@0.50.0": "1cddmp929k882mdh6i9f2as848f13qqna6czwsqzkh1pqnr5fkjj",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#yansi-term@0.1.2": "1w8vjlvxba6yvidqdvxddx3crl6z66h39qxj8xi6aqayw2nk0p7y",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#zerocopy-derive@0.7.31": "06k0zk4x4n9s1blgxmxqb1g81y8q334aayx61gyy6v9y1dajkhdk",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#zerocopy@0.7.31": "0gcfyrmlrhmsz16qxjp2qzr6vixyaw1p04zl28f08lxkvfz62h0w",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#zeroize@1.7.0": "0bfvby7k9pdp6623p98yz2irqnamcyzpn7zh20nqmdn68b0lwnsj",
|
||||||
|
"registry+https://github.com/rust-lang/crates.io-index#zune-inflate@0.2.54": "00kg24jh3zqa3i6rg6yksnb71bch9yi1casqydl00s7nw8pk7avk"
|
||||||
}
|
}
|
@ -1,16 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "cyber-slides"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
async-std = "1.13.0"
|
|
||||||
cairo-rs = "0.18"
|
|
||||||
cyberpunk = { path = "../cyberpunk" }
|
|
||||||
gio = "0.18"
|
|
||||||
glib = "0.18"
|
|
||||||
gtk = { version = "0.7", package = "gtk4" }
|
|
||||||
serde = { version = "1.0.210", features = ["derive"] }
|
|
||||||
serde_yml = "0.0.12"
|
|
@ -1,410 +0,0 @@
|
|||||||
use std::{
|
|
||||||
cell::RefCell,
|
|
||||||
collections::HashMap,
|
|
||||||
fs::File,
|
|
||||||
io::Read,
|
|
||||||
ops::Index,
|
|
||||||
path::Path,
|
|
||||||
rc::Rc,
|
|
||||||
sync::{Arc, RwLock},
|
|
||||||
time::{Duration, Instant},
|
|
||||||
};
|
|
||||||
|
|
||||||
use cairo::{Context, Rectangle};
|
|
||||||
use cyberpunk::{AsymLine, AsymLineCutout, GlowPen, Pen, Text};
|
|
||||||
use glib::Object;
|
|
||||||
use gtk::{
|
|
||||||
glib::{self},
|
|
||||||
prelude::*,
|
|
||||||
subclass::prelude::*,
|
|
||||||
EventControllerKey,
|
|
||||||
};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
const FPS: u64 = 60;
|
|
||||||
const PURPLE: (f64, f64, f64) = (0.7, 0., 1.);
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
|
|
||||||
#[serde(rename_all = "lowercase")]
|
|
||||||
enum Position {
|
|
||||||
Top,
|
|
||||||
Middle,
|
|
||||||
Bottom,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
struct Step {
|
|
||||||
text: String,
|
|
||||||
position: Position,
|
|
||||||
transition: Duration,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
#[derive(Default)]
|
|
||||||
struct Script(Vec<Step>);
|
|
||||||
|
|
||||||
impl Script {
|
|
||||||
fn from_file(path: &Path) -> Result<Script, serde_yml::Error> {
|
|
||||||
let mut buf: Vec<u8> = Vec::new();
|
|
||||||
let mut f = File::open(path).unwrap();
|
|
||||||
f.read_to_end(&mut buf).unwrap();
|
|
||||||
let script = serde_yml::from_slice(&buf)?;
|
|
||||||
Ok(Self(script))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn iter(&self) -> impl Iterator<Item = &'_ Step> {
|
|
||||||
self.0.iter()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn len(&self) -> usize {
|
|
||||||
self.0.len()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl Index<usize> for Script {
|
|
||||||
type Output = Step;
|
|
||||||
|
|
||||||
fn index(&self, index: usize) -> &Self::Output {
|
|
||||||
&self.0[index]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Fade {
|
|
||||||
text: String,
|
|
||||||
position: Position,
|
|
||||||
duration: Duration,
|
|
||||||
|
|
||||||
start_time: Instant,
|
|
||||||
}
|
|
||||||
|
|
||||||
trait Animation {
|
|
||||||
fn position(&self) -> Position;
|
|
||||||
|
|
||||||
fn tick(&self, now: Instant, context: &Context, width: f64);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Animation for Fade {
|
|
||||||
fn position(&self) -> Position {
|
|
||||||
self.position.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tick(&self, now: Instant, context: &Context, width: f64) {
|
|
||||||
let total_frames = self.duration.as_secs() * FPS;
|
|
||||||
let alpha_rate: f64 = 1. / total_frames as f64;
|
|
||||||
|
|
||||||
let frames = (now - self.start_time).as_secs_f64() * FPS as f64;
|
|
||||||
let alpha = alpha_rate * frames;
|
|
||||||
|
|
||||||
let text_display = Text::new(self.text.clone(), context, 64., width);
|
|
||||||
context.move_to(0., text_display.extents().height());
|
|
||||||
context.set_source_rgba(PURPLE.0, PURPLE.1, PURPLE.2, alpha);
|
|
||||||
text_display.draw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CrossFade {
|
|
||||||
old_text: String,
|
|
||||||
new_text: String,
|
|
||||||
position: Position,
|
|
||||||
duration: Duration,
|
|
||||||
|
|
||||||
start_time: Instant,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Animation for CrossFade {
|
|
||||||
fn position(&self) -> Position {
|
|
||||||
self.position.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tick(&self, now: Instant, context: &Context, width: f64) {
|
|
||||||
let total_frames = self.duration.as_secs() * FPS;
|
|
||||||
let alpha_rate: f64 = 1. / total_frames as f64;
|
|
||||||
|
|
||||||
let frames = (now - self.start_time).as_secs_f64() * FPS as f64;
|
|
||||||
let alpha = alpha_rate * frames;
|
|
||||||
|
|
||||||
let text_display = Text::new(self.old_text.clone(), context, 64., width);
|
|
||||||
context.move_to(0., text_display.extents().height());
|
|
||||||
context.set_source_rgba(PURPLE.0, PURPLE.1, PURPLE.2, 1. - alpha);
|
|
||||||
text_display.draw();
|
|
||||||
|
|
||||||
let text_display = Text::new(self.new_text.clone(), context, 64., width);
|
|
||||||
context.move_to(0., text_display.extents().height());
|
|
||||||
context.set_source_rgba(PURPLE.0, PURPLE.1, PURPLE.2, alpha);
|
|
||||||
text_display.draw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct CyberScreenState {
|
|
||||||
script: Script,
|
|
||||||
idx: Option<usize>,
|
|
||||||
top: Option<Step>,
|
|
||||||
middle: Option<Step>,
|
|
||||||
bottom: Option<Step>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for CyberScreenState {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
script: Script(vec![]),
|
|
||||||
idx: None,
|
|
||||||
top: None,
|
|
||||||
middle: None,
|
|
||||||
bottom: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CyberScreenState {
|
|
||||||
fn new(script: Script) -> CyberScreenState {
|
|
||||||
CyberScreenState { script, ..Default::default() }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_page(&mut self) -> Box<dyn Animation> {
|
|
||||||
let idx = match self.idx {
|
|
||||||
None => 0,
|
|
||||||
Some(idx) => {
|
|
||||||
if idx < self.script.len() {
|
|
||||||
idx + 1
|
|
||||||
} else {
|
|
||||||
idx
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
self.idx = Some(idx);
|
|
||||||
let step = self.script[idx].clone();
|
|
||||||
|
|
||||||
let (old, new) = match step.position {
|
|
||||||
Position::Top => {
|
|
||||||
let old = self.top.replace(step.clone());
|
|
||||||
(old, step)
|
|
||||||
}
|
|
||||||
Position::Middle => {
|
|
||||||
let old = self.middle.replace(step.clone());
|
|
||||||
(old, step)
|
|
||||||
}
|
|
||||||
Position::Bottom => {
|
|
||||||
let old = self.bottom.replace(step.clone());
|
|
||||||
(old, step)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match old {
|
|
||||||
Some(old) => Box::new(CrossFade {
|
|
||||||
old_text: old.text.clone(),
|
|
||||||
new_text: new.text.clone(),
|
|
||||||
position: new.position,
|
|
||||||
duration: new.transition,
|
|
||||||
start_time: Instant::now(),
|
|
||||||
}),
|
|
||||||
None => Box::new(Fade {
|
|
||||||
text: new.text.clone(),
|
|
||||||
position: new.position,
|
|
||||||
duration: new.transition,
|
|
||||||
start_time: Instant::now(),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct CyberScreenPrivate {
|
|
||||||
state: Rc<RefCell<CyberScreenState>>,
|
|
||||||
// For crossfading to work, I have to detect that there is an old animation in a position, and
|
|
||||||
// replace it with the new one.
|
|
||||||
animations: Rc<RefCell<HashMap<Position, Box<dyn Animation>>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[glib::object_subclass]
|
|
||||||
impl ObjectSubclass for CyberScreenPrivate {
|
|
||||||
const NAME: &'static str = "CyberScreen";
|
|
||||||
type Type = CyberScreen;
|
|
||||||
type ParentType = gtk::DrawingArea;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ObjectImpl for CyberScreenPrivate {}
|
|
||||||
impl WidgetImpl for CyberScreenPrivate {}
|
|
||||||
impl DrawingAreaImpl for CyberScreenPrivate {}
|
|
||||||
|
|
||||||
impl CyberScreenPrivate {
|
|
||||||
fn set_script(&self, script: Script) {
|
|
||||||
*self.state.borrow_mut() = CyberScreenState::new(script);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_page(&self) {
|
|
||||||
let transition = self.state.borrow_mut().next_page();
|
|
||||||
self.animations
|
|
||||||
.borrow_mut()
|
|
||||||
.insert(transition.position(), transition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
glib::wrapper! {
|
|
||||||
pub struct CyberScreen(ObjectSubclass<CyberScreenPrivate>) @extends gtk::DrawingArea, gtk::Widget;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CyberScreen {
|
|
||||||
fn new(script: Script) -> Self {
|
|
||||||
let s: Self = Object::builder().build();
|
|
||||||
s.imp().set_script(script);
|
|
||||||
|
|
||||||
s.set_draw_func({
|
|
||||||
let s = s.clone();
|
|
||||||
move |_, context, width, height| {
|
|
||||||
let now = Instant::now();
|
|
||||||
context.set_source_rgb(0., 0., 0.);
|
|
||||||
let _ = context.paint();
|
|
||||||
|
|
||||||
let pen = GlowPen::new(width, height, 2., 8., (0.7, 0., 1.));
|
|
||||||
AsymLineCutout {
|
|
||||||
orientation: gtk::Orientation::Horizontal,
|
|
||||||
start_x: 25.,
|
|
||||||
start_y: height as f64 / 7.,
|
|
||||||
start_length: width as f64 / 3.,
|
|
||||||
cutout_length: width as f64 / 3. - 100.,
|
|
||||||
height: 50.,
|
|
||||||
end_length: width as f64 / 3. - 50.,
|
|
||||||
invert: false,
|
|
||||||
}
|
|
||||||
.draw(&pen);
|
|
||||||
pen.stroke();
|
|
||||||
|
|
||||||
AsymLine {
|
|
||||||
orientation: gtk::Orientation::Horizontal,
|
|
||||||
start_x: width as f64 / 4.,
|
|
||||||
start_y: height as f64 * 6. / 7.,
|
|
||||||
start_length: width as f64 * 2. / 3. - 25.,
|
|
||||||
height: 50.,
|
|
||||||
end_length: 0.,
|
|
||||||
invert: false,
|
|
||||||
}
|
|
||||||
.draw(&pen);
|
|
||||||
pen.stroke();
|
|
||||||
|
|
||||||
let tracery = pen.finish();
|
|
||||||
let _ = context.set_source(tracery);
|
|
||||||
let _ = context.paint();
|
|
||||||
|
|
||||||
let animations = s.imp().animations.borrow_mut();
|
|
||||||
|
|
||||||
let lr_margin = 50.;
|
|
||||||
let max_width = width as f64 - lr_margin * 2.;
|
|
||||||
let region_height = height as f64 / 5.;
|
|
||||||
|
|
||||||
if let Some(animation) = animations.get(&Position::Top) {
|
|
||||||
let y = height as f64 * 1. / 5.;
|
|
||||||
let surface = context
|
|
||||||
.target()
|
|
||||||
.create_for_rectangle(Rectangle::new(20., y, max_width, region_height))
|
|
||||||
.unwrap();
|
|
||||||
let ctx = Context::new(&surface).unwrap();
|
|
||||||
animation.tick(now, &ctx, max_width);
|
|
||||||
}
|
|
||||||
if let Some(animation) = animations.get(&Position::Middle) {
|
|
||||||
let y = height as f64 * 2. / 5.;
|
|
||||||
let surface = context
|
|
||||||
.target()
|
|
||||||
.create_for_rectangle(Rectangle::new(20., y, max_width, region_height))
|
|
||||||
.unwrap();
|
|
||||||
let ctx = Context::new(&surface).unwrap();
|
|
||||||
animation.tick(now, &ctx, max_width);
|
|
||||||
}
|
|
||||||
if let Some(animation) = animations.get(&Position::Bottom) {
|
|
||||||
let y = height as f64 * 3. / 5.;
|
|
||||||
let surface = context
|
|
||||||
.target()
|
|
||||||
.create_for_rectangle(Rectangle::new(20., y, max_width, region_height))
|
|
||||||
.unwrap();
|
|
||||||
let ctx = Context::new(&surface).unwrap();
|
|
||||||
animation.tick(now, &ctx, max_width);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
s
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_page(&self) {
|
|
||||||
self.imp().next_page();
|
|
||||||
self.queue_draw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let script = Arc::new(RwLock::new(Script::default()));
|
|
||||||
let app = gtk::Application::builder()
|
|
||||||
.application_id("com.luminescent-dreams.cyberpunk-slideshow")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
app.add_main_option(
|
|
||||||
"script",
|
|
||||||
glib::char::Char::from(b's'),
|
|
||||||
glib::OptionFlags::IN_MAIN,
|
|
||||||
glib::OptionArg::String,
|
|
||||||
"",
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
|
|
||||||
app.connect_handle_local_options({
|
|
||||||
let script = script.clone();
|
|
||||||
move |_, options| {
|
|
||||||
if let Some(script_path) = options.lookup::<String>("script").unwrap() {
|
|
||||||
let mut script = script.write().unwrap();
|
|
||||||
*script = Script::from_file(Path::new(&script_path)).unwrap();
|
|
||||||
-1
|
|
||||||
} else {
|
|
||||||
1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
app.connect_activate(move |app| {
|
|
||||||
let window = gtk::ApplicationWindow::new(app);
|
|
||||||
let screen = CyberScreen::new(script.read().unwrap().clone());
|
|
||||||
|
|
||||||
let events = EventControllerKey::new();
|
|
||||||
|
|
||||||
events.connect_key_released({
|
|
||||||
let app = app.clone();
|
|
||||||
let window = window.clone();
|
|
||||||
let screen = screen.clone();
|
|
||||||
move |_, key, _, _| {
|
|
||||||
let name = key
|
|
||||||
.name()
|
|
||||||
.map(|s| s.as_str().to_owned())
|
|
||||||
.unwrap_or("".to_owned());
|
|
||||||
match name.as_ref() {
|
|
||||||
"Right" => screen.next_page(),
|
|
||||||
"q" => app.quit(),
|
|
||||||
"Escape" => window.unfullscreen(),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
window.add_controller(events);
|
|
||||||
|
|
||||||
window.set_child(Some(&screen));
|
|
||||||
window.set_width_request(800);
|
|
||||||
window.set_height_request(600);
|
|
||||||
window.present();
|
|
||||||
|
|
||||||
window.connect_maximized_notify(|window| {
|
|
||||||
window.fullscreen();
|
|
||||||
});
|
|
||||||
|
|
||||||
let _ = glib::spawn_future_local({
|
|
||||||
let screen = screen.clone();
|
|
||||||
async move {
|
|
||||||
loop {
|
|
||||||
screen.queue_draw();
|
|
||||||
async_std::task::sleep(Duration::from_millis(1000 / FPS)).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
app.run();
|
|
||||||
}
|
|
@ -7,9 +7,7 @@ license = "GPL-3.0-only"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
async-std = { workspace = true }
|
cairo-rs = { version = "0.18" }
|
||||||
cairo-rs = { workspace = true }
|
gio = { version = "0.18" }
|
||||||
cyberpunk = { path = "../cyberpunk" }
|
glib = { version = "0.18" }
|
||||||
gio = { workspace = true }
|
gtk = { version = "0.7", package = "gtk4" }
|
||||||
glib = { workspace = true }
|
|
||||||
gtk = { workspace = true }
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
use cairo::{
|
use cairo::{
|
||||||
Context, FontSlant, FontWeight, Format, ImageSurface, LinearGradient, Pattern,
|
Context, FontSlant, FontWeight, Format, ImageSurface, LineCap, LinearGradient, Pattern,
|
||||||
TextExtents,
|
TextExtents,
|
||||||
};
|
};
|
||||||
use cyberpunk::{AsymLine, AsymLineCutout, GlowPen, Pen, SlashMeter};
|
|
||||||
use glib::Object;
|
use glib::Object;
|
||||||
use gtk::{prelude::*, subclass::prelude::*, EventControllerKey};
|
use gtk::{prelude::*, subclass::prelude::*, EventControllerKey};
|
||||||
use std::{
|
use std::{
|
||||||
@ -172,7 +171,7 @@ impl SplashPrivate {
|
|||||||
start_y: extents.height() + 10.,
|
start_y: extents.height() + 10.,
|
||||||
start_length: 0.,
|
start_length: 0.,
|
||||||
height: extents.height() / 2.,
|
height: extents.height() / 2.,
|
||||||
end_length: 0.,
|
total_length: extents.width() + extents.height() / 2.,
|
||||||
invert: false,
|
invert: false,
|
||||||
}
|
}
|
||||||
.draw(&pen);
|
.draw(&pen);
|
||||||
@ -184,7 +183,7 @@ impl SplashPrivate {
|
|||||||
start_y: extents.height() + 60.,
|
start_y: extents.height() + 60.,
|
||||||
start_length: extents.width(),
|
start_length: extents.width(),
|
||||||
height: extents.height() / 2.,
|
height: extents.height() / 2.,
|
||||||
end_length: 0.,
|
total_length: extents.width() + extents.height() / 2.,
|
||||||
invert: false,
|
invert: false,
|
||||||
}
|
}
|
||||||
.draw(&pen);
|
.draw(&pen);
|
||||||
@ -209,7 +208,7 @@ impl SplashPrivate {
|
|||||||
start_x: 20.,
|
start_x: 20.,
|
||||||
start_y: center_y - 20. - title_height / 2.,
|
start_y: center_y - 20. - title_height / 2.,
|
||||||
start_length,
|
start_length,
|
||||||
end_length: *self.width.borrow() as f64 - 120. - start_length,
|
total_length: *self.width.borrow() as f64 - 120.,
|
||||||
cutout_length: title_width,
|
cutout_length: title_width,
|
||||||
height: title_height,
|
height: title_height,
|
||||||
invert: false,
|
invert: false,
|
||||||
@ -244,7 +243,7 @@ impl SplashPrivate {
|
|||||||
start_y: *self.height.borrow() as f64 / 2. + 100.,
|
start_y: *self.height.borrow() as f64 / 2. + 100.,
|
||||||
start_length: 400.,
|
start_length: 400.,
|
||||||
height: 50.,
|
height: 50.,
|
||||||
end_length: 0.,
|
total_length: 650.,
|
||||||
invert: true,
|
invert: true,
|
||||||
}
|
}
|
||||||
.draw(&pen);
|
.draw(&pen);
|
||||||
@ -259,7 +258,7 @@ impl SplashPrivate {
|
|||||||
start_y: *self.height.borrow() as f64 / 2. + 200.,
|
start_y: *self.height.borrow() as f64 / 2. + 200.,
|
||||||
start_length: 600.,
|
start_length: 600.,
|
||||||
height: 50.,
|
height: 50.,
|
||||||
end_length: 0.,
|
total_length: 650.,
|
||||||
invert: false,
|
invert: false,
|
||||||
}
|
}
|
||||||
.draw(&pen);
|
.draw(&pen);
|
||||||
@ -420,6 +419,212 @@ impl Splash {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct AsymLineCutout {
|
||||||
|
orientation: gtk::Orientation,
|
||||||
|
start_x: f64,
|
||||||
|
start_y: f64,
|
||||||
|
start_length: f64,
|
||||||
|
total_length: f64,
|
||||||
|
cutout_length: f64,
|
||||||
|
height: f64,
|
||||||
|
invert: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsymLineCutout {
|
||||||
|
fn draw(&self, pen: &impl Pen) {
|
||||||
|
let dodge = if self.invert {
|
||||||
|
self.height
|
||||||
|
} else {
|
||||||
|
-self.height
|
||||||
|
};
|
||||||
|
match self.orientation {
|
||||||
|
gtk::Orientation::Horizontal => {
|
||||||
|
pen.move_to(self.start_x, self.start_y);
|
||||||
|
pen.line_to(self.start_x + self.start_length, self.start_y);
|
||||||
|
pen.line_to(
|
||||||
|
self.start_x + self.start_length + self.height,
|
||||||
|
self.start_y + dodge,
|
||||||
|
);
|
||||||
|
pen.line_to(
|
||||||
|
self.start_x + self.start_length + self.height + self.cutout_length,
|
||||||
|
self.start_y + dodge,
|
||||||
|
);
|
||||||
|
pen.line_to(
|
||||||
|
self.start_x
|
||||||
|
+ self.start_length
|
||||||
|
+ self.height
|
||||||
|
+ self.cutout_length
|
||||||
|
+ (self.height / 2.),
|
||||||
|
self.start_y + dodge / 2.,
|
||||||
|
);
|
||||||
|
pen.line_to(self.total_length, self.start_y + dodge / 2.);
|
||||||
|
}
|
||||||
|
gtk::Orientation::Vertical => {
|
||||||
|
pen.move_to(self.start_x, self.start_y);
|
||||||
|
pen.line_to(self.start_x, self.start_y + self.start_length);
|
||||||
|
pen.line_to(
|
||||||
|
self.start_x + dodge,
|
||||||
|
self.start_y + self.start_length + self.height,
|
||||||
|
);
|
||||||
|
pen.line_to(
|
||||||
|
self.start_x + dodge,
|
||||||
|
self.start_y + self.start_length + self.height + self.cutout_length,
|
||||||
|
);
|
||||||
|
pen.line_to(
|
||||||
|
self.start_x + dodge / 2.,
|
||||||
|
self.start_y
|
||||||
|
+ self.start_length
|
||||||
|
+ self.height
|
||||||
|
+ self.cutout_length
|
||||||
|
+ (self.height / 2.),
|
||||||
|
);
|
||||||
|
pen.line_to(self.start_x + dodge / 2., self.total_length);
|
||||||
|
}
|
||||||
|
_ => panic!("unknown orientation"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AsymLine {
|
||||||
|
orientation: gtk::Orientation,
|
||||||
|
start_x: f64,
|
||||||
|
start_y: f64,
|
||||||
|
start_length: f64,
|
||||||
|
height: f64,
|
||||||
|
total_length: f64,
|
||||||
|
invert: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsymLine {
|
||||||
|
fn draw(&self, pen: &impl Pen) {
|
||||||
|
let dodge = if self.invert {
|
||||||
|
self.height
|
||||||
|
} else {
|
||||||
|
-self.height
|
||||||
|
};
|
||||||
|
match self.orientation {
|
||||||
|
gtk::Orientation::Horizontal => {
|
||||||
|
pen.move_to(self.start_x, self.start_y);
|
||||||
|
pen.line_to(self.start_x + self.start_length, self.start_y);
|
||||||
|
pen.line_to(
|
||||||
|
self.start_x + self.start_length + self.height,
|
||||||
|
self.start_y + dodge,
|
||||||
|
);
|
||||||
|
pen.line_to(self.start_x + self.total_length, self.start_y + dodge);
|
||||||
|
}
|
||||||
|
gtk::Orientation::Vertical => {}
|
||||||
|
_ => panic!("unknown orientation"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SlashMeter {
|
||||||
|
orientation: gtk::Orientation,
|
||||||
|
start_x: f64,
|
||||||
|
start_y: f64,
|
||||||
|
count: u8,
|
||||||
|
fill_count: u8,
|
||||||
|
height: f64,
|
||||||
|
length: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SlashMeter {
|
||||||
|
fn draw(&self, context: &Context) {
|
||||||
|
match self.orientation {
|
||||||
|
gtk::Orientation::Horizontal => {
|
||||||
|
let angle: f64 = 0.8;
|
||||||
|
let run = self.height / angle.tan();
|
||||||
|
let width = self.length / (self.count as f64 * 2.);
|
||||||
|
|
||||||
|
for c in 0..self.count {
|
||||||
|
context.set_line_width(1.);
|
||||||
|
|
||||||
|
let start_x = self.start_x + c as f64 * width * 2.;
|
||||||
|
context.move_to(start_x, self.start_y);
|
||||||
|
context.line_to(start_x + run, self.start_y - self.height);
|
||||||
|
context.line_to(start_x + run + width, self.start_y - self.height);
|
||||||
|
context.line_to(start_x + width, self.start_y);
|
||||||
|
context.line_to(start_x, self.start_y);
|
||||||
|
if c < self.fill_count {
|
||||||
|
let _ = context.fill();
|
||||||
|
} else {
|
||||||
|
let _ = context.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gtk::Orientation::Vertical => {}
|
||||||
|
_ => panic!("unknown orientation"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Pen {
|
||||||
|
fn move_to(&self, x: f64, y: f64);
|
||||||
|
fn line_to(&self, x: f64, y: f64);
|
||||||
|
fn stroke(&self);
|
||||||
|
|
||||||
|
fn finish(self) -> Pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GlowPen {
|
||||||
|
blur_context: Context,
|
||||||
|
draw_context: Context,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GlowPen {
|
||||||
|
fn new(
|
||||||
|
width: i32,
|
||||||
|
height: i32,
|
||||||
|
line_width: f64,
|
||||||
|
blur_line_width: f64,
|
||||||
|
color: (f64, f64, f64),
|
||||||
|
) -> Self {
|
||||||
|
let blur_context =
|
||||||
|
Context::new(ImageSurface::create(Format::Rgb24, width, height).unwrap()).unwrap();
|
||||||
|
blur_context.set_line_width(blur_line_width);
|
||||||
|
blur_context.set_source_rgba(color.0, color.1, color.2, 0.5);
|
||||||
|
blur_context.push_group();
|
||||||
|
blur_context.set_line_cap(LineCap::Round);
|
||||||
|
|
||||||
|
let draw_context =
|
||||||
|
Context::new(ImageSurface::create(Format::Rgb24, width, height).unwrap()).unwrap();
|
||||||
|
draw_context.set_line_width(line_width);
|
||||||
|
draw_context.set_source_rgb(color.0, color.1, color.2);
|
||||||
|
draw_context.push_group();
|
||||||
|
draw_context.set_line_cap(LineCap::Round);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
blur_context,
|
||||||
|
draw_context,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pen for GlowPen {
|
||||||
|
fn move_to(&self, x: f64, y: f64) {
|
||||||
|
self.blur_context.move_to(x, y);
|
||||||
|
self.draw_context.move_to(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn line_to(&self, x: f64, y: f64) {
|
||||||
|
self.blur_context.line_to(x, y);
|
||||||
|
self.draw_context.line_to(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stroke(&self) {
|
||||||
|
self.blur_context.stroke().expect("to draw the blur line");
|
||||||
|
self.draw_context
|
||||||
|
.stroke()
|
||||||
|
.expect("to draw the regular line");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish(self) -> Pattern {
|
||||||
|
let foreground = self.draw_context.pop_group().unwrap();
|
||||||
|
self.blur_context.set_source(foreground).unwrap();
|
||||||
|
self.blur_context.paint().unwrap();
|
||||||
|
self.blur_context.pop_group().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let app = gtk::Application::builder()
|
let app = gtk::Application::builder()
|
||||||
@ -497,7 +702,8 @@ fn main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.connect_activate(move |app| {
|
app.connect_activate(move |app| {
|
||||||
let (gtk_tx, gtk_rx) = async_std::channel::unbounded();
|
let (gtk_tx, gtk_rx) =
|
||||||
|
gtk::glib::MainContext::channel::<State>(gtk::glib::Priority::DEFAULT);
|
||||||
|
|
||||||
let window = gtk::ApplicationWindow::new(app);
|
let window = gtk::ApplicationWindow::new(app);
|
||||||
window.present();
|
window.present();
|
||||||
@ -528,25 +734,19 @@ fn main() {
|
|||||||
});
|
});
|
||||||
window.add_controller(keyboard_events);
|
window.add_controller(keyboard_events);
|
||||||
|
|
||||||
glib::spawn_future_local({
|
gtk_rx.attach(None, move |state| {
|
||||||
let splash = splash.clone();
|
splash.set_state(state);
|
||||||
async move {
|
glib::ControlFlow::Continue
|
||||||
while let Ok(state) = gtk_rx.recv().await {
|
|
||||||
println!("received state");
|
|
||||||
splash.set_state(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
glib::spawn_future_local({
|
std::thread::spawn({
|
||||||
let state = state.clone();
|
let state = state.clone();
|
||||||
async move {
|
move || {
|
||||||
state.write().unwrap().start();
|
state.write().unwrap().start();
|
||||||
loop {
|
loop {
|
||||||
async_std::task::sleep(Duration::from_millis(1000 / 60)).await;
|
std::thread::sleep(Duration::from_millis(1000 / 60));
|
||||||
state.write().unwrap().run(Instant::now());
|
state.write().unwrap().run(Instant::now());
|
||||||
println!("state: {:?}", state.read().unwrap());
|
let _ = gtk_tx.send(*state.read().unwrap());
|
||||||
let _ = gtk_tx.send(*state.read().unwrap()).await;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "cyberpunk"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
cairo-rs = { workspace = true }
|
|
||||||
gio = { workspace = true }
|
|
||||||
glib = { workspace = true }
|
|
||||||
gtk = { workspace = true }
|
|
@ -1,301 +0,0 @@
|
|||||||
use cairo::{
|
|
||||||
Context, FontSlant, FontWeight, Format, ImageSurface, LineCap, Pattern,
|
|
||||||
TextExtents,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct AsymLineCutout {
|
|
||||||
pub orientation: gtk::Orientation,
|
|
||||||
pub start_x: f64,
|
|
||||||
pub start_y: f64,
|
|
||||||
pub start_length: f64,
|
|
||||||
pub cutout_length: f64,
|
|
||||||
pub end_length: f64,
|
|
||||||
pub height: f64,
|
|
||||||
pub invert: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsymLineCutout {
|
|
||||||
pub fn draw(&self, pen: &impl Pen) {
|
|
||||||
let dodge = if self.invert {
|
|
||||||
self.height
|
|
||||||
} else {
|
|
||||||
-self.height
|
|
||||||
};
|
|
||||||
match self.orientation {
|
|
||||||
gtk::Orientation::Horizontal => {
|
|
||||||
pen.move_to(self.start_x, self.start_y);
|
|
||||||
pen.line_to(self.start_x + self.start_length, self.start_y);
|
|
||||||
pen.line_to(
|
|
||||||
self.start_x + self.start_length + self.height,
|
|
||||||
self.start_y + dodge,
|
|
||||||
);
|
|
||||||
pen.line_to(
|
|
||||||
self.start_x + self.start_length + self.height + self.cutout_length,
|
|
||||||
self.start_y + dodge,
|
|
||||||
);
|
|
||||||
pen.line_to(
|
|
||||||
self.start_x
|
|
||||||
+ self.start_length
|
|
||||||
+ self.height
|
|
||||||
+ self.cutout_length
|
|
||||||
+ (self.height / 2.),
|
|
||||||
self.start_y + dodge / 2.,
|
|
||||||
);
|
|
||||||
pen.line_to(
|
|
||||||
self.start_x
|
|
||||||
+ self.start_length
|
|
||||||
+ self.height
|
|
||||||
+ self.cutout_length
|
|
||||||
+ (self.height / 2.)
|
|
||||||
+ self.end_length,
|
|
||||||
self.start_y + dodge / 2.,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
gtk::Orientation::Vertical => {
|
|
||||||
pen.move_to(self.start_x, self.start_y);
|
|
||||||
pen.line_to(self.start_x, self.start_y + self.start_length);
|
|
||||||
pen.line_to(
|
|
||||||
self.start_x + dodge,
|
|
||||||
self.start_y + self.start_length + self.height,
|
|
||||||
);
|
|
||||||
pen.line_to(
|
|
||||||
self.start_x + dodge,
|
|
||||||
self.start_y + self.start_length + self.height + self.cutout_length,
|
|
||||||
);
|
|
||||||
pen.line_to(
|
|
||||||
self.start_x + dodge / 2.,
|
|
||||||
self.start_y
|
|
||||||
+ self.start_length
|
|
||||||
+ self.height
|
|
||||||
+ self.cutout_length
|
|
||||||
+ (self.height / 2.),
|
|
||||||
);
|
|
||||||
pen.line_to(
|
|
||||||
self.start_x + dodge / 2.,
|
|
||||||
self.start_y
|
|
||||||
+ self.start_length
|
|
||||||
+ self.height
|
|
||||||
+ self.cutout_length
|
|
||||||
+ (self.height / 2.)
|
|
||||||
+ self.end_length,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => panic!("unknown orientation"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Represents an asymetrical line that starts at one location, then a 45-degree angle and then
|
|
||||||
// another line afterwards.
|
|
||||||
pub struct AsymLine {
|
|
||||||
// Will this be drawn left-to-right or up-to-down?
|
|
||||||
pub orientation: gtk::Orientation,
|
|
||||||
|
|
||||||
// Starting address
|
|
||||||
pub start_x: f64,
|
|
||||||
pub start_y: f64,
|
|
||||||
|
|
||||||
// Length of the first segment
|
|
||||||
pub start_length: f64,
|
|
||||||
|
|
||||||
// Height to dodge over to the next section
|
|
||||||
pub height: f64,
|
|
||||||
|
|
||||||
// Total length of the entire line.
|
|
||||||
pub end_length: f64,
|
|
||||||
|
|
||||||
// When normal, the angle dodge is upwards. When inverted, the angle dodge is downwards.
|
|
||||||
pub invert: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsymLine {
|
|
||||||
pub fn draw(&self, pen: &impl Pen) {
|
|
||||||
let dodge = if self.invert {
|
|
||||||
self.height
|
|
||||||
} else {
|
|
||||||
-self.height
|
|
||||||
};
|
|
||||||
match self.orientation {
|
|
||||||
gtk::Orientation::Horizontal => {
|
|
||||||
pen.move_to(self.start_x, self.start_y);
|
|
||||||
pen.line_to(self.start_x + self.start_length, self.start_y);
|
|
||||||
pen.line_to(
|
|
||||||
self.start_x + self.start_length + self.height,
|
|
||||||
self.start_y + dodge,
|
|
||||||
);
|
|
||||||
pen.line_to(
|
|
||||||
self.start_x + self.start_length + self.height + self.end_length,
|
|
||||||
self.start_y + dodge,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
gtk::Orientation::Vertical => {}
|
|
||||||
_ => panic!("unknown orientation"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SlashMeter {
|
|
||||||
pub orientation: gtk::Orientation,
|
|
||||||
pub start_x: f64,
|
|
||||||
pub start_y: f64,
|
|
||||||
pub count: u8,
|
|
||||||
pub fill_count: u8,
|
|
||||||
pub height: f64,
|
|
||||||
pub length: f64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SlashMeter {
|
|
||||||
pub fn draw(&self, context: &Context) {
|
|
||||||
match self.orientation {
|
|
||||||
gtk::Orientation::Horizontal => {
|
|
||||||
let angle: f64 = 0.8;
|
|
||||||
let run = self.height / angle.tan();
|
|
||||||
let width = self.length / (self.count as f64 * 2.);
|
|
||||||
|
|
||||||
for c in 0..self.count {
|
|
||||||
context.set_line_width(1.);
|
|
||||||
|
|
||||||
let start_x = self.start_x + c as f64 * width * 2.;
|
|
||||||
context.move_to(start_x, self.start_y);
|
|
||||||
context.line_to(start_x + run, self.start_y - self.height);
|
|
||||||
context.line_to(start_x + run + width, self.start_y - self.height);
|
|
||||||
context.line_to(start_x + width, self.start_y);
|
|
||||||
context.line_to(start_x, self.start_y);
|
|
||||||
if c < self.fill_count {
|
|
||||||
let _ = context.fill();
|
|
||||||
} else {
|
|
||||||
let _ = context.stroke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gtk::Orientation::Vertical => {}
|
|
||||||
_ => panic!("unknown orientation"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents a pen for drawing a pattern. This is good for complex patterns that may require
|
|
||||||
/// multiple identical steps.
|
|
||||||
pub trait Pen {
|
|
||||||
/// Move the pen to a location.
|
|
||||||
fn move_to(&self, x: f64, y: f64);
|
|
||||||
|
|
||||||
/// Draw a line from the current location to the specified destination.
|
|
||||||
fn line_to(&self, x: f64, y: f64);
|
|
||||||
|
|
||||||
/// Instantiate the line.
|
|
||||||
fn stroke(&self);
|
|
||||||
|
|
||||||
/// Convert all of the drawing into a pattern that can be painted to a drawing context.
|
|
||||||
fn finish(self) -> Pattern;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct GlowPen {
|
|
||||||
blur_context: Context,
|
|
||||||
draw_context: Context,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GlowPen {
|
|
||||||
pub fn new(
|
|
||||||
width: i32,
|
|
||||||
height: i32,
|
|
||||||
line_width: f64,
|
|
||||||
blur_line_width: f64,
|
|
||||||
color: (f64, f64, f64),
|
|
||||||
) -> Self {
|
|
||||||
let blur_context =
|
|
||||||
Context::new(ImageSurface::create(Format::Rgb24, width, height).unwrap()).unwrap();
|
|
||||||
blur_context.set_line_width(blur_line_width);
|
|
||||||
blur_context.set_source_rgba(color.0, color.1, color.2, 0.5);
|
|
||||||
blur_context.push_group();
|
|
||||||
blur_context.set_line_cap(LineCap::Round);
|
|
||||||
|
|
||||||
let draw_context =
|
|
||||||
Context::new(ImageSurface::create(Format::Rgb24, width, height).unwrap()).unwrap();
|
|
||||||
draw_context.set_line_width(line_width);
|
|
||||||
draw_context.set_source_rgb(color.0, color.1, color.2);
|
|
||||||
draw_context.push_group();
|
|
||||||
draw_context.set_line_cap(LineCap::Round);
|
|
||||||
|
|
||||||
Self {
|
|
||||||
blur_context,
|
|
||||||
draw_context,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Pen for GlowPen {
|
|
||||||
fn move_to(&self, x: f64, y: f64) {
|
|
||||||
self.blur_context.move_to(x, y);
|
|
||||||
self.draw_context.move_to(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn line_to(&self, x: f64, y: f64) {
|
|
||||||
self.blur_context.line_to(x, y);
|
|
||||||
self.draw_context.line_to(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn stroke(&self) {
|
|
||||||
self.blur_context.stroke().expect("to draw the blur line");
|
|
||||||
self.draw_context
|
|
||||||
.stroke()
|
|
||||||
.expect("to draw the regular line");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn finish(self) -> Pattern {
|
|
||||||
let foreground = self.draw_context.pop_group().unwrap();
|
|
||||||
self.blur_context.set_source(foreground).unwrap();
|
|
||||||
self.blur_context.paint().unwrap();
|
|
||||||
self.blur_context.pop_group().unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Text<'a> {
|
|
||||||
content: Vec<String>,
|
|
||||||
context: &'a Context,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Text<'a> {
|
|
||||||
pub fn new(content: String, context: &'a Context, size: f64, width: f64) -> Self {
|
|
||||||
context.select_font_face("Alegreya Sans SC", FontSlant::Normal, FontWeight::Bold);
|
|
||||||
context.set_font_size(size);
|
|
||||||
|
|
||||||
let lines = word_wrap(content, context, width);
|
|
||||||
|
|
||||||
Self { content: lines, context }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn extents(&self) -> TextExtents {
|
|
||||||
self.context.text_extents(&self.content[0]).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn draw(&self) {
|
|
||||||
let mut baseline = 0.;
|
|
||||||
for line in self.content.iter() {
|
|
||||||
baseline += self.context.text_extents(line).unwrap().height() + 10.;
|
|
||||||
self.context.move_to(0., baseline);
|
|
||||||
let _ = self.context.show_text(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn word_wrap(content: String, context: &Context, max_width: f64) -> Vec<String> {
|
|
||||||
let mut lines = vec![];
|
|
||||||
let words: Vec<&str> = content.split_whitespace().collect();
|
|
||||||
let mut start: usize = 0;
|
|
||||||
let mut line = String::new();
|
|
||||||
|
|
||||||
for idx in 0..words.len() + 1 {
|
|
||||||
line = words[start..idx].join(" ");
|
|
||||||
let extents = context.text_extents(&line).unwrap();
|
|
||||||
if extents.width() > max_width {
|
|
||||||
let line = words[start..idx-1].join(" ");
|
|
||||||
start = idx-1;
|
|
||||||
lines.push(line.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !line.is_empty() {
|
|
||||||
lines.push(line);
|
|
||||||
}
|
|
||||||
lines
|
|
||||||
}
|
|
@ -31,9 +31,7 @@ impl ApplicationWindow {
|
|||||||
|
|
||||||
let provider = gtk::CssProvider::new();
|
let provider = gtk::CssProvider::new();
|
||||||
provider.load_from_data(&stylesheet);
|
provider.load_from_data(&stylesheet);
|
||||||
#[allow(deprecated)]
|
|
||||||
let context = window.style_context();
|
let context = window.style_context();
|
||||||
#[allow(deprecated)]
|
|
||||||
context.add_provider(&provider, STYLE_PROVIDER_PRIORITY_USER);
|
context.add_provider(&provider, STYLE_PROVIDER_PRIORITY_USER);
|
||||||
|
|
||||||
let layout = gtk::Box::builder()
|
let layout = gtk::Box::builder()
|
||||||
|
@ -36,7 +36,6 @@ impl Default for TransitClock {
|
|||||||
s.set_draw_func({
|
s.set_draw_func({
|
||||||
let s = s.clone();
|
let s = s.clone();
|
||||||
move |_, context, width, height| {
|
move |_, context, width, height| {
|
||||||
#[allow(deprecated)]
|
|
||||||
let style_context = WidgetExt::style_context(&s);
|
let style_context = WidgetExt::style_context(&s);
|
||||||
let center_x = width as f64 / 2.;
|
let center_x = width as f64 / 2.;
|
||||||
let center_y = height as f64 / 2.;
|
let center_y = height as f64 / 2.;
|
||||||
@ -46,9 +45,7 @@ impl Default for TransitClock {
|
|||||||
let sunrise = info.sunrise - NaiveTime::from_hms_opt(0, 0, 0).unwrap();
|
let sunrise = info.sunrise - NaiveTime::from_hms_opt(0, 0, 0).unwrap();
|
||||||
let sunset = info.sunset - NaiveTime::from_hms_opt(0, 0, 0).unwrap();
|
let sunset = info.sunset - NaiveTime::from_hms_opt(0, 0, 0).unwrap();
|
||||||
|
|
||||||
#[allow(deprecated)]
|
|
||||||
let night_color = style_context.lookup_color("dark_5").unwrap();
|
let night_color = style_context.lookup_color("dark_5").unwrap();
|
||||||
#[allow(deprecated)]
|
|
||||||
let day_color = style_context.lookup_color("blue_1").unwrap();
|
let day_color = style_context.lookup_color("blue_1").unwrap();
|
||||||
|
|
||||||
PieChart::new(&style_context)
|
PieChart::new(&style_context)
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
use cairo::Context;
|
use cairo::Context;
|
||||||
use gtk::{gdk::RGBA, prelude::*};
|
use gtk::{gdk::RGBA, prelude::*, StyleContext};
|
||||||
#[allow(deprecated)]
|
|
||||||
use gtk::StyleContext;
|
|
||||||
use std::f64::consts::PI;
|
use std::f64::consts::PI;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -29,9 +27,7 @@ pub struct PieChart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PieChart {
|
impl PieChart {
|
||||||
#[allow(deprecated)]
|
|
||||||
pub fn new(style_context: &StyleContext) -> Self {
|
pub fn new(style_context: &StyleContext) -> Self {
|
||||||
#[allow(deprecated)]
|
|
||||||
Self {
|
Self {
|
||||||
rotation: 0.,
|
rotation: 0.,
|
||||||
wedges: vec![],
|
wedges: vec![],
|
||||||
|
@ -132,7 +132,7 @@ impl SolunaClient {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use serde_json;
|
||||||
|
|
||||||
const EXAMPLE: &str = "{\"sunRise\":\"7:15\",\"sunTransit\":\"12:30\",\"sunSet\":\"17:45\",\"moonRise\":null,\"moonTransit\":\"7:30\",\"moonUnder\":\"19:54\",\"moonSet\":\"15:02\",\"moonPhase\":\"Waning Crescent\",\"moonIllumination\":0.35889454647387764,\"sunRiseDec\":7.25,\"sunTransitDec\":12.5,\"sunSetDec\":17.75,\"moonRiseDec\":null,\"moonSetDec\":15.033333333333333,\"moonTransitDec\":7.5,\"moonUnderDec\":19.9,\"minor1Start\":null,\"minor1Stop\":null,\"minor2StartDec\":14.533333333333333,\"minor2Start\":\"14:32\",\"minor2StopDec\":15.533333333333333,\"minor2Stop\":\"15:32\",\"major1StartDec\":6.5,\"major1Start\":\"06:30\",\"major1StopDec\":8.5,\"major1Stop\":\"08:30\",\"major2StartDec\":18.9,\"major2Start\":\"18:54\",\"major2StopDec\":20.9,\"major2Stop\":\"20:54\",\"dayRating\":1,\"hourlyRating\":{\"0\":20,\"1\":20,\"2\":0,\"3\":0,\"4\":0,\"5\":0,\"6\":20,\"7\":40,\"8\":40,\"9\":20,\"10\":0,\"11\":0,\"12\":0,\"13\":0,\"14\":0,\"15\":20,\"16\":20,\"17\":20,\"18\":40,\"19\":20,\"20\":20,\"21\":20,\"22\":0,\"23\":0}}";
|
const EXAMPLE: &str = "{\"sunRise\":\"7:15\",\"sunTransit\":\"12:30\",\"sunSet\":\"17:45\",\"moonRise\":null,\"moonTransit\":\"7:30\",\"moonUnder\":\"19:54\",\"moonSet\":\"15:02\",\"moonPhase\":\"Waning Crescent\",\"moonIllumination\":0.35889454647387764,\"sunRiseDec\":7.25,\"sunTransitDec\":12.5,\"sunSetDec\":17.75,\"moonRiseDec\":null,\"moonSetDec\":15.033333333333333,\"moonTransitDec\":7.5,\"moonUnderDec\":19.9,\"minor1Start\":null,\"minor1Stop\":null,\"minor2StartDec\":14.533333333333333,\"minor2Start\":\"14:32\",\"minor2StopDec\":15.533333333333333,\"minor2Stop\":\"15:32\",\"major1StartDec\":6.5,\"major1Start\":\"06:30\",\"major1StopDec\":8.5,\"major1Stop\":\"08:30\",\"major2StartDec\":18.9,\"major2Start\":\"18:54\",\"major2StopDec\":20.9,\"major2Stop\":\"20:54\",\"dayRating\":1,\"hourlyRating\":{\"0\":20,\"1\":20,\"2\":0,\"3\":0,\"4\":0,\"5\":0,\"6\":20,\"7\":40,\"8\":40,\"9\":20,\"10\":0,\"11\":0,\"12\":0,\"13\":0,\"14\":0,\"15\":20,\"16\":20,\"17\":20,\"18\":40,\"19\":20,\"20\":20,\"21\":20,\"22\":0,\"23\":0}}";
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ documentation = "https://docs.rs/emseries"
|
|||||||
homepage = "https://github.com/luminescent-dreams/emseries"
|
homepage = "https://github.com/luminescent-dreams/emseries"
|
||||||
repository = "https://github.com/luminescent-dreams/emseries"
|
repository = "https://github.com/luminescent-dreams/emseries"
|
||||||
categories = ["database-implementations"]
|
categories = ["database-implementations"]
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
include = [
|
include = [
|
||||||
"**/*.rs",
|
"**/*.rs",
|
||||||
|
@ -10,7 +10,7 @@ Luminescent Dreams Tools is distributed in the hope that it will be useful, but
|
|||||||
You should have received a copy of the GNU General Public License along with Lumeto. If not, see <https://www.gnu.org/licenses/>.
|
You should have received a copy of the GNU General Public License along with Lumeto. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::types::{Recordable, Timestamp};
|
use types::{Recordable, Timestamp};
|
||||||
|
|
||||||
/// This trait is used for constructing queries for searching the database.
|
/// This trait is used for constructing queries for searching the database.
|
||||||
pub trait Criteria {
|
pub trait Criteria {
|
||||||
|
@ -10,6 +10,10 @@ Luminescent Dreams Tools is distributed in the hope that it will be useful, but
|
|||||||
You should have received a copy of the GNU General Public License along with Lumeto. If not, see <https://www.gnu.org/licenses/>.
|
You should have received a copy of the GNU General Public License along with Lumeto. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
extern crate serde;
|
||||||
|
extern crate serde_json;
|
||||||
|
extern crate uuid;
|
||||||
|
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde::ser::Serialize;
|
use serde::ser::Serialize;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
@ -20,8 +24,8 @@ use std::fs::OpenOptions;
|
|||||||
use std::io::{BufRead, BufReader, LineWriter, Write};
|
use std::io::{BufRead, BufReader, LineWriter, Write};
|
||||||
use std::iter::Iterator;
|
use std::iter::Iterator;
|
||||||
|
|
||||||
use crate::criteria::Criteria;
|
use criteria::Criteria;
|
||||||
use crate::types::{EmseriesReadError, EmseriesWriteError, Record, RecordId, Recordable};
|
use types::{EmseriesReadError, EmseriesWriteError, Record, RecordId, Recordable};
|
||||||
|
|
||||||
// A RecordOnDisk, a private data structure, is useful for handling all of the on-disk
|
// A RecordOnDisk, a private data structure, is useful for handling all of the on-disk
|
||||||
// representations of a record. Unlike [Record], this one can accept an empty data value to
|
// representations of a record. Unlike [Record], this one can accept an empty data value to
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
version: '3'
|
|
||||||
|
|
||||||
tasks:
|
|
||||||
build:
|
|
||||||
cmds:
|
|
||||||
- cargo build
|
|
||||||
|
|
||||||
lint:
|
|
||||||
cmds:
|
|
||||||
- cargo watch -x clippy
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
|||||||
use std::fmt::Display;
|
|
||||||
|
|
||||||
use build_html::{self, Html, HtmlContainer};
|
use build_html::{self, Html, HtmlContainer};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
@ -25,14 +23,13 @@ impl FromIterator<(&str, &str)> for Attributes {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
impl Display for Attributes {
|
impl ToString for Attributes {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn to_string(&self) -> String {
|
||||||
let result = self.0
|
self.0
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(key, value)| format!("{}=\"{}\"", key, value))
|
.map(|(key, value)| format!("{}=\"{}\"", key, value))
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(" ");
|
.join(" ")
|
||||||
write!(f, "{}", result)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,7 +202,7 @@ impl Html for Button {
|
|||||||
"<button {ty} {name} {attrs}>{label}</button>",
|
"<button {ty} {name} {attrs}>{label}</button>",
|
||||||
name = name,
|
name = name,
|
||||||
label = self.label,
|
label = self.label,
|
||||||
attrs = self.attributes
|
attrs = self.attributes.to_string()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,21 +118,17 @@ impl Deref for FileId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
pub trait FileRoot {
|
pub trait FileRoot {
|
||||||
fn root(&self) -> PathBuf;
|
fn root(&self) -> PathBuf;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
// pub struct Context(PathBuf);
|
pub struct Context(PathBuf);
|
||||||
|
|
||||||
/*
|
|
||||||
impl FileRoot for Context {
|
impl FileRoot for Context {
|
||||||
fn root(&self) -> PathBuf {
|
fn root(&self) -> PathBuf {
|
||||||
self.0.clone()
|
self.0.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
pub struct Store {
|
pub struct Store {
|
||||||
files_root: PathBuf,
|
files_root: PathBuf,
|
||||||
|
@ -6,20 +6,20 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
adw = { workspace = true }
|
adw = { version = "0.5", package = "libadwaita", features = [ "v1_4" ] }
|
||||||
async-channel = { workspace = true }
|
async-channel = { version = "2.1" }
|
||||||
async-trait = { workspace = true }
|
async-trait = { version = "0.1" }
|
||||||
chrono = { workspace = true }
|
chrono = { version = "0.4" }
|
||||||
chrono-tz = { workspace = true }
|
chrono-tz = { version = "0.8" }
|
||||||
dimensioned = { workspace = true }
|
dimensioned = { version = "0.8", features = [ "serde" ] }
|
||||||
emseries = { path = "../../emseries" }
|
emseries = { path = "../../emseries" }
|
||||||
ft-core = { path = "../core" }
|
ft-core = { path = "../core" }
|
||||||
gio = { workspace = true }
|
gio = { version = "0.18" }
|
||||||
glib = { workspace = true }
|
glib = { version = "0.18" }
|
||||||
gdk = { workspace = true }
|
gdk = { version = "0.7", package = "gdk4" }
|
||||||
gtk = { workspace = true }
|
gtk = { version = "0.7", package = "gtk4", features = [ "v4_10" ] }
|
||||||
thiserror = { workspace = true }
|
thiserror = { version = "1.0" }
|
||||||
tokio = { workspace = true }
|
tokio = { version = "1.34", features = [ "full" ] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
glib-build-tools = "0.18"
|
glib-build-tools = "0.18"
|
||||||
|
@ -153,7 +153,7 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn it_allows_valid_dates() {
|
fn it_allows_valid_dates() {
|
||||||
let reference = chrono::NaiveDate::from_ymd_opt(2006, 1, 2).unwrap();
|
let reference = chrono::NaiveDate::from_ymd_opt(2006, 01, 02).unwrap();
|
||||||
let field = DateField::new(reference);
|
let field = DateField::new(reference);
|
||||||
field.imp().year.set_value(Some(2023));
|
field.imp().year.set_value(Some(2023));
|
||||||
field.imp().month.set_value(Some(10));
|
field.imp().month.set_value(Some(10));
|
||||||
|
@ -80,10 +80,10 @@ impl TimeFormatter {
|
|||||||
0 => Err(ParseError),
|
0 => Err(ParseError),
|
||||||
1 => Err(ParseError),
|
1 => Err(ParseError),
|
||||||
2 => chrono::NaiveTime::from_hms_opt(parts[0], parts[1], 0)
|
2 => chrono::NaiveTime::from_hms_opt(parts[0], parts[1], 0)
|
||||||
.map(TimeFormatter)
|
.map(|v| TimeFormatter(v))
|
||||||
.ok_or(ParseError),
|
.ok_or(ParseError),
|
||||||
3 => chrono::NaiveTime::from_hms_opt(parts[0], parts[1], parts[2])
|
3 => chrono::NaiveTime::from_hms_opt(parts[0], parts[1], parts[2])
|
||||||
.map(TimeFormatter)
|
.map(|v| TimeFormatter(v))
|
||||||
.ok_or(ParseError),
|
.ok_or(ParseError),
|
||||||
_ => Err(ParseError),
|
_ => Err(ParseError),
|
||||||
}
|
}
|
||||||
|
@ -443,7 +443,7 @@ mod test {
|
|||||||
async fn put_record(&self, record: TraxRecord) -> Result<RecordId, WriteError> {
|
async fn put_record(&self, record: TraxRecord) -> Result<RecordId, WriteError> {
|
||||||
let id = RecordId::default();
|
let id = RecordId::default();
|
||||||
let record = Record {
|
let record = Record {
|
||||||
id,
|
id: id,
|
||||||
data: record,
|
data: record,
|
||||||
};
|
};
|
||||||
self.put_records.write().unwrap().push(record.clone());
|
self.put_records.write().unwrap().push(record.clone());
|
||||||
@ -509,7 +509,7 @@ mod test {
|
|||||||
Record {
|
Record {
|
||||||
id: RecordId::default(),
|
id: RecordId::default(),
|
||||||
data: TraxRecord::TimeDistance(ft_core::TimeDistance {
|
data: TraxRecord::TimeDistance(ft_core::TimeDistance {
|
||||||
datetime: oct_13_am,
|
datetime: oct_13_am.clone(),
|
||||||
activity: TimeDistanceActivity::Biking,
|
activity: TimeDistanceActivity::Biking,
|
||||||
distance: Some(15000. * si::M),
|
distance: Some(15000. * si::M),
|
||||||
duration: Some(3600. * si::S),
|
duration: Some(3600. * si::S),
|
||||||
|
@ -144,7 +144,7 @@ impl HistoricalView {
|
|||||||
let mut model = gio::ListStore::new::<Date>();
|
let mut model = gio::ListStore::new::<Date>();
|
||||||
let mut days = interval.days().map(Date::new).collect::<Vec<Date>>();
|
let mut days = interval.days().map(Date::new).collect::<Vec<Date>>();
|
||||||
days.reverse();
|
days.reverse();
|
||||||
model.extend(days);
|
model.extend(days.into_iter());
|
||||||
self.imp()
|
self.imp()
|
||||||
.list_view
|
.list_view
|
||||||
.set_model(Some(>k::NoSelection::new(Some(model))));
|
.set_model(Some(>k::NoSelection::new(Some(model))));
|
||||||
|
@ -6,12 +6,12 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
chrono = { workspace = true }
|
chrono = { version = "0.4" }
|
||||||
chrono-tz = { workspace = true }
|
chrono-tz = { version = "0.8" }
|
||||||
dimensioned = { workspace = true }
|
dimensioned = { version = "0.8", features = [ "serde" ] }
|
||||||
emseries = { path = "../../emseries" }
|
emseries = { path = "../../emseries" }
|
||||||
serde = { workspace = true }
|
serde = { version = "1", features = [ "derive" ] }
|
||||||
serde_json = { workspace = true }
|
serde_json = { version = "1" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = "*"
|
tempfile = "*"
|
||||||
|
@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with Fit
|
|||||||
use chrono::SecondsFormat;
|
use chrono::SecondsFormat;
|
||||||
use chrono_tz::Etc::UTC;
|
use chrono_tz::Etc::UTC;
|
||||||
use dimensioned::si;
|
use dimensioned::si;
|
||||||
use emseries::{Record, RecordId};
|
use emseries::{Record, RecordId, Series, Timestamp};
|
||||||
use ft_core::{self, DurationWorkout, DurationWorkoutActivity, SetRepActivity, TraxRecord};
|
use ft_core::{self, DurationWorkout, DurationWorkoutActivity, SetRepActivity, TraxRecord};
|
||||||
use serde::{
|
use serde::{
|
||||||
de::{self, Visitor},
|
de::{self, Visitor},
|
||||||
@ -26,7 +26,7 @@ use serde::{
|
|||||||
use std::{
|
use std::{
|
||||||
fmt,
|
fmt,
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{BufRead, BufReader},
|
io::{BufRead, BufReader, Read},
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
26
flake.lock
generated
26
flake.lock
generated
@ -5,11 +5,11 @@
|
|||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1710146030,
|
"lastModified": 1681202837,
|
||||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -20,26 +20,26 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1740339700,
|
"lastModified": 1704732714,
|
||||||
"narHash": "sha256-cbrw7EgQhcdFnu6iS3vane53bEagZQy/xyIkDWpCgVE=",
|
"narHash": "sha256-ABqK/HggMYA/jMUXgYyqVAcQ8QjeMyr1jcXfTpSHmps=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "04ef94c4c1582fd485bbfdb8c4a8ba250e359195",
|
"rev": "6723fa4e4f1a30d42a633bef5eb01caeb281adc3",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"id": "nixpkgs",
|
"id": "nixpkgs",
|
||||||
"ref": "nixos-24.11",
|
"ref": "nixos-23.11",
|
||||||
"type": "indirect"
|
"type": "indirect"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1714906307,
|
"lastModified": 1681303793,
|
||||||
"narHash": "sha256-UlRZtrCnhPFSJlDQE7M0eyhgvuuHBTe1eJ9N9AQlJQ0=",
|
"narHash": "sha256-JEdQHsYuCfRL2PICHlOiH/2ue3DwoxUX7DJ6zZxZXFk=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "25865a40d14b3f9cf19f19b924e2ab4069b09588",
|
"rev": "fe2ecaf706a5907b5e54d979fbde4924d84b65fc",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@ -76,11 +76,11 @@
|
|||||||
"nixpkgs": "nixpkgs_2"
|
"nixpkgs": "nixpkgs_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1731966246,
|
"lastModified": 1698205128,
|
||||||
"narHash": "sha256-e/V7Ffm5wPd9DVzCThnPZ7lFxd43bb64tSk8/oGP4Ag=",
|
"narHash": "sha256-jP+81TkldLtda8bzmsBWahETGsyFkoDOCT244YkA+S4=",
|
||||||
"owner": "1Password",
|
"owner": "1Password",
|
||||||
"repo": "typeshare",
|
"repo": "typeshare",
|
||||||
"rev": "e0e5f27ee34d7d4da76a9dc96a11552e98be56da",
|
"rev": "c3ee2ad8f27774c45db7af4f2ba746c4ae11de21",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
23
flake.nix
23
flake.nix
@ -2,7 +2,7 @@
|
|||||||
description = "Lumenescent Dreams Tools";
|
description = "Lumenescent Dreams Tools";
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "nixpkgs/nixos-24.11";
|
nixpkgs.url = "nixpkgs/nixos-23.11";
|
||||||
unstable.url = "nixpkgs/nixos-unstable";
|
unstable.url = "nixpkgs/nixos-unstable";
|
||||||
typeshare.url = "github:1Password/typeshare";
|
typeshare.url = "github:1Password/typeshare";
|
||||||
};
|
};
|
||||||
@ -22,10 +22,8 @@
|
|||||||
name = "ld-tools-devshell";
|
name = "ld-tools-devshell";
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
pkgs.cargo-nextest
|
pkgs.cargo-nextest
|
||||||
pkgs.cargo-watch
|
|
||||||
pkgs.clang
|
pkgs.clang
|
||||||
pkgs.crate2nix
|
pkgs.crate2nix
|
||||||
pkgs.trunk
|
|
||||||
pkgs.glib
|
pkgs.glib
|
||||||
pkgs.gst_all_1.gst-plugins-bad
|
pkgs.gst_all_1.gst-plugins-bad
|
||||||
pkgs.gst_all_1.gst-plugins-base
|
pkgs.gst_all_1.gst-plugins-base
|
||||||
@ -36,17 +34,17 @@
|
|||||||
pkgs.libadwaita
|
pkgs.libadwaita
|
||||||
pkgs.librsvg
|
pkgs.librsvg
|
||||||
pkgs.nodejs
|
pkgs.nodejs
|
||||||
|
pkgs.nodePackages.eslint
|
||||||
|
pkgs.nodePackages.typescript
|
||||||
|
pkgs.nodePackages.typescript-language-server
|
||||||
pkgs.openssl
|
pkgs.openssl
|
||||||
pkgs.pipewire
|
pkgs.pipewire
|
||||||
pkgs.pkg-config
|
pkgs.pkg-config
|
||||||
pkgs.rustup
|
pkgs.rustup
|
||||||
pkgs.sqlite
|
pkgs.sqlite
|
||||||
pkgs.cargo-nextest
|
|
||||||
pkgs.wasm-pack
|
|
||||||
pkgs.sqlx-cli
|
pkgs.sqlx-cli
|
||||||
pkgs.udev
|
pkgs.udev
|
||||||
pkgs.wasm-pack
|
pkgs.wasm-pack
|
||||||
pkgs.go-task
|
|
||||||
typeshare.packages."x86_64-linux".default
|
typeshare.packages."x86_64-linux".default
|
||||||
pkgs.nodePackages_latest.typescript-language-server
|
pkgs.nodePackages_latest.typescript-language-server
|
||||||
];
|
];
|
||||||
@ -57,6 +55,7 @@
|
|||||||
packages."x86_64-linux" =
|
packages."x86_64-linux" =
|
||||||
let
|
let
|
||||||
pkgs = import nixpkgs { system = "x86_64-linux"; };
|
pkgs = import nixpkgs { system = "x86_64-linux"; };
|
||||||
|
|
||||||
gtkNativeInputs = [
|
gtkNativeInputs = [
|
||||||
pkgs.pkg-config
|
pkgs.pkg-config
|
||||||
pkgs.gtk4
|
pkgs.gtk4
|
||||||
@ -83,24 +82,20 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
in rec {
|
in rec {
|
||||||
cyber-slides = cargo_nix.workspaceMembers.cyber-slides.build;
|
|
||||||
cyberpunk-splash = cargo_nix.workspaceMembers.cyberpunk-splash.build;
|
cyberpunk-splash = cargo_nix.workspaceMembers.cyberpunk-splash.build;
|
||||||
dashboard = cargo_nix.workspaceMembers.dashboard.build;
|
dashboard = cargo_nix.workspaceMembers.dashboard.build;
|
||||||
# file-service = cargo_nix.workspaceMembers.file-service.build;
|
file-service = cargo_nix.workspaceMembers.file-service.build;
|
||||||
fitnesstrax = cargo_nix.workspaceMembers.fitnesstrax.build;
|
fitnesstrax = cargo_nix.workspaceMembers.fitnesstrax.build;
|
||||||
l10n-db = cargo_nix.workspaceMembers.l10n-db.build;
|
|
||||||
otg-gtk = cargo_nix.workspaceMembers.otg-gtk.build;
|
otg-gtk = cargo_nix.workspaceMembers.otg-gtk.build;
|
||||||
|
|
||||||
all = pkgs.symlinkJoin {
|
all = pkgs.symlinkJoin {
|
||||||
name = "all";
|
name = "all";
|
||||||
paths = [
|
paths = [
|
||||||
# cyber-slides
|
|
||||||
cyberpunk-splash
|
cyberpunk-splash
|
||||||
# dashboard
|
dashboard
|
||||||
# file-service
|
file-service
|
||||||
fitnesstrax
|
fitnesstrax
|
||||||
l10n-db
|
otg-gtk
|
||||||
# otg-gtk
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -294,21 +294,21 @@ mod tests {
|
|||||||
use fluent_bundle::{FluentArgs, FluentValue};
|
use fluent_bundle::{FluentArgs, FluentValue};
|
||||||
use unic_langid::LanguageIdentifier;
|
use unic_langid::LanguageIdentifier;
|
||||||
|
|
||||||
const EN_TRANSLATIONS: &str = "
|
const EN_TRANSLATIONS: &'static str = "
|
||||||
preferences = Preferences
|
preferences = Preferences
|
||||||
history = History
|
history = History
|
||||||
time_display = {$time} during the day
|
time_display = {$time} during the day
|
||||||
nested_display = nesting a time display: {time_display}
|
nested_display = nesting a time display: {time_display}
|
||||||
";
|
";
|
||||||
|
|
||||||
const EO_TRANSLATIONS: &str = "
|
const EO_TRANSLATIONS: &'static str = "
|
||||||
history = Historio
|
history = Historio
|
||||||
";
|
";
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn translations() {
|
fn translations() {
|
||||||
let en_id = "en-US".parse::<LanguageIdentifier>().unwrap();
|
let en_id = "en-US".parse::<LanguageIdentifier>().unwrap();
|
||||||
let mut fluent = FluentErgo::new(&[en_id.clone()]);
|
let mut fluent = FluentErgo::new(&vec![en_id.clone()]);
|
||||||
fluent
|
fluent
|
||||||
.add_from_text(en_id, String::from(EN_TRANSLATIONS))
|
.add_from_text(en_id, String::from(EN_TRANSLATIONS))
|
||||||
.expect("text should load");
|
.expect("text should load");
|
||||||
@ -322,7 +322,7 @@ history = Historio
|
|||||||
fn translation_fallback() {
|
fn translation_fallback() {
|
||||||
let eo_id = "eo".parse::<LanguageIdentifier>().unwrap();
|
let eo_id = "eo".parse::<LanguageIdentifier>().unwrap();
|
||||||
let en_id = "en".parse::<LanguageIdentifier>().unwrap();
|
let en_id = "en".parse::<LanguageIdentifier>().unwrap();
|
||||||
let mut fluent = FluentErgo::new(&[eo_id.clone(), en_id.clone()]);
|
let mut fluent = FluentErgo::new(&vec![eo_id.clone(), en_id.clone()]);
|
||||||
fluent
|
fluent
|
||||||
.add_from_text(en_id, String::from(EN_TRANSLATIONS))
|
.add_from_text(en_id, String::from(EN_TRANSLATIONS))
|
||||||
.expect("text should load");
|
.expect("text should load");
|
||||||
@ -342,7 +342,7 @@ history = Historio
|
|||||||
#[test]
|
#[test]
|
||||||
fn placeholder_insertion_should_strip_placeholder_markers() {
|
fn placeholder_insertion_should_strip_placeholder_markers() {
|
||||||
let en_id = "en".parse::<LanguageIdentifier>().unwrap();
|
let en_id = "en".parse::<LanguageIdentifier>().unwrap();
|
||||||
let mut fluent = FluentErgo::new(&[en_id.clone()]);
|
let mut fluent = FluentErgo::new(&vec![en_id.clone()]);
|
||||||
fluent
|
fluent
|
||||||
.add_from_text(en_id, String::from(EN_TRANSLATIONS))
|
.add_from_text(en_id, String::from(EN_TRANSLATIONS))
|
||||||
.expect("text should load");
|
.expect("text should load");
|
||||||
@ -357,7 +357,7 @@ history = Historio
|
|||||||
#[test]
|
#[test]
|
||||||
fn placeholder_insertion_should_strip_nested_placeholder_markers() {
|
fn placeholder_insertion_should_strip_nested_placeholder_markers() {
|
||||||
let en_id = "en".parse::<LanguageIdentifier>().unwrap();
|
let en_id = "en".parse::<LanguageIdentifier>().unwrap();
|
||||||
let mut fluent = FluentErgo::new(&[en_id.clone()]);
|
let mut fluent = FluentErgo::new(&vec![en_id.clone()]);
|
||||||
fluent
|
fluent
|
||||||
.add_from_text(en_id, String::from(EN_TRANSLATIONS))
|
.add_from_text(en_id, String::from(EN_TRANSLATIONS))
|
||||||
.expect("text should load");
|
.expect("text should load");
|
||||||
|
@ -7,8 +7,8 @@ use std::iter::Iterator;
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ApplicationWindow {
|
pub struct ApplicationWindow {
|
||||||
pub window: adw::ApplicationWindow,
|
pub window: adw::ApplicationWindow,
|
||||||
// pub layout: gtk::FlowBox,
|
pub layout: gtk::FlowBox,
|
||||||
// pub playlists: Vec<PlaylistCard>,
|
pub playlists: Vec<PlaylistCard>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApplicationWindow {
|
impl ApplicationWindow {
|
||||||
@ -31,9 +31,7 @@ impl ApplicationWindow {
|
|||||||
|
|
||||||
let provider = gtk::CssProvider::new();
|
let provider = gtk::CssProvider::new();
|
||||||
provider.load_from_data(&stylesheet);
|
provider.load_from_data(&stylesheet);
|
||||||
#[allow(deprecated)]
|
|
||||||
let context = window.style_context();
|
let context = window.style_context();
|
||||||
#[allow(deprecated)]
|
|
||||||
context.add_provider(&provider, STYLE_PROVIDER_PRIORITY_USER);
|
context.add_provider(&provider, STYLE_PROVIDER_PRIORITY_USER);
|
||||||
|
|
||||||
let layout = gtk::FlowBox::new();
|
let layout = gtk::FlowBox::new();
|
||||||
@ -59,10 +57,8 @@ impl ApplicationWindow {
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
window,
|
window,
|
||||||
/*
|
|
||||||
layout,
|
layout,
|
||||||
playlists,
|
playlists,
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,12 +27,12 @@ impl State {
|
|||||||
|
|
||||||
fn add_audio(&self, device: String) {
|
fn add_audio(&self, device: String) {
|
||||||
let mut st = self.internal.write().unwrap();
|
let mut st = self.internal.write().unwrap();
|
||||||
st.device_list.push(device);
|
(*st).device_list.push(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn audio_devices(&self) -> Vec<String> {
|
fn audio_devices(&self) -> Vec<String> {
|
||||||
let st = self.internal.read().unwrap();
|
let st = self.internal.read().unwrap();
|
||||||
st.device_list.clone()
|
(*st).device_list.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,6 +107,8 @@ impl ObjectSubclass for HexGridWindowPrivate {
|
|||||||
layout.append(&drawing_area);
|
layout.append(&drawing_area);
|
||||||
layout.append(&sidebar);
|
layout.append(&sidebar);
|
||||||
|
|
||||||
|
layout.show();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
drawing_area,
|
drawing_area,
|
||||||
hex_address,
|
hex_address,
|
||||||
|
400
ifc/Cargo.lock
generated
Normal file
400
ifc/Cargo.lock
generated
Normal file
@ -0,0 +1,400 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "android_system_properties"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bumpalo"
|
||||||
|
version = "3.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.78"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chrono"
|
||||||
|
version = "0.4.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
|
||||||
|
dependencies = [
|
||||||
|
"iana-time-zone",
|
||||||
|
"js-sys",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
"time",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "codespan-reporting"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
|
||||||
|
dependencies = [
|
||||||
|
"termcolor",
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation-sys"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cxx"
|
||||||
|
version = "1.0.85"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5add3fc1717409d029b20c5b6903fc0c0b02fa6741d820054f4a2efa5e5816fd"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"cxxbridge-flags",
|
||||||
|
"cxxbridge-macro",
|
||||||
|
"link-cplusplus",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cxx-build"
|
||||||
|
version = "1.0.85"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4c87959ba14bc6fbc61df77c3fcfe180fc32b93538c4f1031dd802ccb5f2ff0"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"codespan-reporting",
|
||||||
|
"once_cell",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"scratch",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cxxbridge-flags"
|
||||||
|
version = "1.0.85"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "69a3e162fde4e594ed2b07d0f83c6c67b745e7f28ce58c6df5e6b6bef99dfb59"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cxxbridge-macro"
|
||||||
|
version = "1.0.85"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3e7e2adeb6a0d4a282e581096b06e1791532b7d576dcde5ccd9382acf55db8e6"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone"
|
||||||
|
version = "0.1.53"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765"
|
||||||
|
dependencies = [
|
||||||
|
"android_system_properties",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"iana-time-zone-haiku",
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone-haiku"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
|
||||||
|
dependencies = [
|
||||||
|
"cxx",
|
||||||
|
"cxx-build",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "international-fixed-calendar"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"serde",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "js-sys"
|
||||||
|
version = "0.3.60"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
|
||||||
|
dependencies = [
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.139"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "link-cplusplus"
|
||||||
|
version = "1.0.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.49"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scratch"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.152"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.152"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.107"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termcolor"
|
||||||
|
version = "1.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.38"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.38"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time"
|
||||||
|
version = "0.1.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.10.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen"
|
||||||
|
version = "0.2.83"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"wasm-bindgen-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-backend"
|
||||||
|
version = "0.2.83"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"log",
|
||||||
|
"once_cell",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro"
|
||||||
|
version = "0.2.83"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"wasm-bindgen-macro-support",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro-support"
|
||||||
|
version = "0.2.83"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-backend",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-shared"
|
||||||
|
version = "0.2.83"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-util"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
14
ifc/Cargo.toml
Normal file
14
ifc/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "ifc"
|
||||||
|
description = "chrono-compatible-ish date objects for the International Fixed Calendar"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Savanni D'Gerinel <savanni@luminescent-dreams.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
keywords = ["date", "time", "calendar"]
|
||||||
|
categories = ["date-and-time"]
|
||||||
|
license = "GPL-3.0-only"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
chrono = { version = "0.4" }
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
thiserror = { version = "1" }
|
8
ifc/readme.md
Normal file
8
ifc/readme.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# International Fixed Calendar
|
||||||
|
|
||||||
|
This is a fun project implementing a library for the [International Fixed Calendar](https://en.wikipedia.org/wiki/International_Fixed_Calendar).
|
||||||
|
|
||||||
|
This is at least somewhat compatible with [Chrono](https://github.com/chronotope/chrono), in that I have implemented these traits:
|
||||||
|
|
||||||
|
* `From<NaiveDate>`
|
||||||
|
* `Datelike`
|
1042
ifc/src/lib.rs
Normal file
1042
ifc/src/lib.rs
Normal file
File diff suppressed because it is too large
Load Diff
34
ifc/src/static/index.html
Normal file
34
ifc/src/static/index.html
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title> {{month}} {{year}} </title>
|
||||||
|
<link href="/css" rel="stylesheet" type="text/css" media="screen" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1> IFC Fixed Calendar: {{month}}, {{year}} years after the invention of agriculture </h1>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th> Sunday </th>
|
||||||
|
<th> Monday </th>
|
||||||
|
<th> Tuesday </th>
|
||||||
|
<th> Wednesday </th>
|
||||||
|
<th> Thursday </th>
|
||||||
|
<th> Friday </th>
|
||||||
|
<th> Saturday </th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{{#weeks}}
|
||||||
|
<tr>
|
||||||
|
{{#days}}
|
||||||
|
<td class="{{highlight}}"> {{day}} </td>
|
||||||
|
{{/days}}
|
||||||
|
</tr>
|
||||||
|
{{/weeks}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
35
ifc/src/static/month.html
Normal file
35
ifc/src/static/month.html
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{{month}} {{year}}</title>
|
||||||
|
<link href="/css" rel="stylesheet" type="text/css" media="screen" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>
|
||||||
|
IFC Fixed Calendar: {{month}}, {{year}} years after the invention of
|
||||||
|
agriculture
|
||||||
|
</h1>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Sunday</th>
|
||||||
|
<th>Monday</th>
|
||||||
|
<th>Tuesday</th>
|
||||||
|
<th>Wednesday</th>
|
||||||
|
<th>Thursday</th>
|
||||||
|
<th>Friday</th>
|
||||||
|
<th>Saturday</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{{#weeks}}
|
||||||
|
<tr>
|
||||||
|
{{#days}}
|
||||||
|
<td class="{{highlight}}">{{day}}</td>
|
||||||
|
{{/days}}
|
||||||
|
</tr>
|
||||||
|
{{/weeks}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
12
ifc/src/static/out_of_time.html
Normal file
12
ifc/src/static/out_of_time.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{{day_out_of_time}} {{year}}</title>
|
||||||
|
<link href="/css" rel="stylesheet" type="text/css" media="screen" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>
|
||||||
|
IFC Fixed Calendar: {{day_out_of_time}}, {{year}} years after the
|
||||||
|
invention of agriculture
|
||||||
|
</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
18
ifc/src/static/styles.css
Normal file
18
ifc/src/static/styles.css
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
table {
|
||||||
|
width: 98%;
|
||||||
|
border: 1px solid black;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
width: 14%;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: larger;
|
||||||
|
border: 1px solid black;
|
||||||
|
padding: 1em 0em 5em 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.today {
|
||||||
|
background-color: rgb(200, 200, 255);
|
||||||
|
}
|
22
ifc/src/today.rs
Normal file
22
ifc/src/today.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020-2023, Savanni D'Gerinel <savanni@luminescent-dreams.com>
|
||||||
|
|
||||||
|
This file is part of the Luminescent Dreams Tools.
|
||||||
|
|
||||||
|
Luminescent Dreams Tools 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 3 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Luminescent Dreams Tools 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 Lumeto. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern crate chrono;
|
||||||
|
extern crate chrono_tz;
|
||||||
|
extern crate ifc as IFC;
|
||||||
|
|
||||||
|
use chrono::{Datelike, Utc};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let d = IFC::IFC::from(Utc::today());
|
||||||
|
println!("{} {}, {}", d.month(), d.day(), d.year());
|
||||||
|
}
|
119
ifc/src/web.rs
Normal file
119
ifc/src/web.rs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020-2023, Savanni D'Gerinel <savanni@luminescent-dreams.com>
|
||||||
|
|
||||||
|
This file is part of the Luminescent Dreams Tools.
|
||||||
|
|
||||||
|
Luminescent Dreams Tools 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 3 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Luminescent Dreams Tools 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 Lumeto. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use chrono::{Datelike, Utc};
|
||||||
|
use ifc as IFC;
|
||||||
|
use iron::headers;
|
||||||
|
use iron::middleware::Handler;
|
||||||
|
use iron::modifiers::Header;
|
||||||
|
use iron::prelude::*;
|
||||||
|
use iron::status;
|
||||||
|
use mustache::{compile_str, Template};
|
||||||
|
use router::Router;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
pub const STYLES: &'static str = include_str!("static/styles.css");
|
||||||
|
pub const INDEX: &'static str = include_str!("static/index.html");
|
||||||
|
|
||||||
|
pub struct IndexHandler {
|
||||||
|
pub template: Template,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct DayEntry {
|
||||||
|
day: u8,
|
||||||
|
highlight: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct Week {
|
||||||
|
days: Vec<DayEntry>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Week {
|
||||||
|
fn new(start_day: u8, today: u8) -> Week {
|
||||||
|
Week {
|
||||||
|
days: (1..8)
|
||||||
|
.map(|d| DayEntry {
|
||||||
|
day: d + start_day,
|
||||||
|
highlight: if today == (d + start_day) {
|
||||||
|
String::from("today")
|
||||||
|
} else {
|
||||||
|
String::from("")
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct IndexTemplateParams {
|
||||||
|
month: String,
|
||||||
|
year: i32,
|
||||||
|
weeks: Vec<Week>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IndexTemplateParams {
|
||||||
|
fn new(date: IFC::IFC) -> IndexTemplateParams {
|
||||||
|
let day = date.day() as u8;
|
||||||
|
IndexTemplateParams {
|
||||||
|
month: String::from(IFC::Month::from(date.month())),
|
||||||
|
year: date.year(),
|
||||||
|
weeks: (0..4).map(|wn| Week::new(wn * 7, day)).collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Handler for IndexHandler {
|
||||||
|
fn handle(&self, _: &mut Request) -> IronResult<Response> {
|
||||||
|
let d = IFC::IFC::from(Utc::today());
|
||||||
|
Ok(Response::with((
|
||||||
|
status::Ok,
|
||||||
|
Header(headers::ContentType(iron::mime::Mime(
|
||||||
|
iron::mime::TopLevel::Text,
|
||||||
|
iron::mime::SubLevel::Html,
|
||||||
|
vec![],
|
||||||
|
))),
|
||||||
|
self.template
|
||||||
|
.render_to_string(&IndexTemplateParams::new(d))
|
||||||
|
.expect("the template to render"),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn css(_: &mut Request) -> IronResult<Response> {
|
||||||
|
Ok(Response::with((
|
||||||
|
status::Ok,
|
||||||
|
Header(headers::ContentType(iron::mime::Mime(
|
||||||
|
iron::mime::TopLevel::Text,
|
||||||
|
iron::mime::SubLevel::Css,
|
||||||
|
vec![],
|
||||||
|
))),
|
||||||
|
STYLES,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut router = Router::new();
|
||||||
|
router.get(
|
||||||
|
"/",
|
||||||
|
IndexHandler {
|
||||||
|
template: compile_str(INDEX).expect("the template to compile"),
|
||||||
|
},
|
||||||
|
"index",
|
||||||
|
);
|
||||||
|
|
||||||
|
router.get("/css", css, "styles");
|
||||||
|
|
||||||
|
Iron::new(router).http("127.0.0.1:3000").unwrap();
|
||||||
|
}
|
@ -1,24 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "l10n-db"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
chrono = { version = "0.4.39", features = ["serde"] }
|
|
||||||
clap = { version = "4.5.30", features = ["derive"] }
|
|
||||||
icu_locid = { version = "1.5.0", features = ["serde"] }
|
|
||||||
serde = { version = "1.0.218", features = ["derive"] }
|
|
||||||
serde_json = "1.0.139"
|
|
||||||
tempfile = "3.17.1"
|
|
||||||
thiserror = "2.0.11"
|
|
||||||
toml = "0.8.20"
|
|
||||||
xml-rs = "0.8.25"
|
|
||||||
|
|
||||||
# [lib]
|
|
||||||
# name = "l10n_db"
|
|
||||||
# path = "src/lib.rs"
|
|
||||||
#
|
|
||||||
# [[bin]]
|
|
||||||
# name = "l10n-db"
|
|
||||||
# path = "src/main.rs"
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
|||||||
db_path = "./i18n"
|
|
||||||
base_locale = "en"
|
|
||||||
locales = [
|
|
||||||
"en",
|
|
||||||
"eo",
|
|
||||||
"de",
|
|
||||||
"es",
|
|
||||||
]
|
|
@ -1,22 +0,0 @@
|
|||||||
key = "SaveSettings"
|
|
||||||
description = "This is a label on a button which will save the settings when clicked"
|
|
||||||
|
|
||||||
[variants.eo]
|
|
||||||
locale = "eo"
|
|
||||||
content = "Konservi Agordojn"
|
|
||||||
modified = "2025-02-24T19:32:11.246639077Z"
|
|
||||||
|
|
||||||
[variants.es]
|
|
||||||
locale = "es"
|
|
||||||
content = "Guardar Configuraciones"
|
|
||||||
modified = "2025-02-24T19:33:23.861329923Z"
|
|
||||||
|
|
||||||
[variants.en]
|
|
||||||
locale = "en"
|
|
||||||
content = "Save Settings"
|
|
||||||
modified = "2025-02-22T23:44:18.874218939Z"
|
|
||||||
|
|
||||||
[variants.de]
|
|
||||||
locale = "de"
|
|
||||||
content = "Einstellungen Speichern"
|
|
||||||
modified = "2025-02-24T19:33:19.516005843Z"
|
|
@ -1,22 +0,0 @@
|
|||||||
key = "TimeDistance"
|
|
||||||
description = "A summary of a workout or many workouts that involve a time and a distance"
|
|
||||||
|
|
||||||
[variants.es]
|
|
||||||
locale = "es"
|
|
||||||
content = "{distance} de {activity} en {hours, plural, one {}=1 {{hours} hora} other {{hours} horas}} y {minutes, plural, one {}=1 {{minutes} minuto} other {{minutes} minutos}}"
|
|
||||||
modified = "2025-02-24T19:33:23.861604738Z"
|
|
||||||
|
|
||||||
[variants.eo]
|
|
||||||
locale = "eo"
|
|
||||||
content = "{distance} de {activity} en {hours, plural, =1 {{hours} horo} other {{hours} horoj}} {minutes, plural, =1 {{minutes} minuto} other {{minutes} minutoj}}"
|
|
||||||
modified = "2025-02-24T19:32:11.246943602Z"
|
|
||||||
|
|
||||||
[variants.en]
|
|
||||||
locale = "en"
|
|
||||||
content = "{distance} of {activity} in {hours, plural, =1 {{hours} hour} other {{hours} hours}} and {minutes, plural, =1 {{minutes} minute} other {{minutes} minutes}}"
|
|
||||||
modified = "2025-02-24T14:09:17.361641899Z"
|
|
||||||
|
|
||||||
[variants.de]
|
|
||||||
locale = "de"
|
|
||||||
content = "{distance} von {activity} in {hours, plural, one {}=1 {{hours} Stunde} other {{hours} Stunden}} und {minutes, plural, one {}=1 {{minutes} Minute} other {{minutes} Minuten}}"
|
|
||||||
modified = "2025-02-24T19:33:19.516210807Z"
|
|
@ -1,22 +0,0 @@
|
|||||||
key = "Welcome"
|
|
||||||
description = "This is a welcome content that will be shown on first app opening, before configuration."
|
|
||||||
|
|
||||||
[variants.en]
|
|
||||||
locale = "en"
|
|
||||||
content = "Welcome to FitnessTrax, the privacy-centered fitness tracker"
|
|
||||||
modified = "2025-02-25T02:12:25.757240004Z"
|
|
||||||
|
|
||||||
[variants.eo]
|
|
||||||
locale = "eo"
|
|
||||||
content = "Bonvenon al FitnessTrax"
|
|
||||||
modified = "2025-02-24T19:32:11.246407627Z"
|
|
||||||
|
|
||||||
[variants.es]
|
|
||||||
locale = "es"
|
|
||||||
content = "Bienvenido a FitnessTrax"
|
|
||||||
modified = "2025-02-24T19:33:23.861143003Z"
|
|
||||||
|
|
||||||
[variants.de]
|
|
||||||
locale = "de"
|
|
||||||
content = "Willkommen bei FitnessTrax"
|
|
||||||
modified = "2025-02-24T19:33:19.515861453Z"
|
|
@ -1,143 +0,0 @@
|
|||||||
use std::{fmt, path::PathBuf};
|
|
||||||
|
|
||||||
use clap::{Parser, Subcommand};
|
|
||||||
|
|
||||||
use icu_locid::{langid, LanguageIdentifier};
|
|
||||||
use l10n_db::{
|
|
||||||
self, js, read_file,
|
|
||||||
xliff::{self, import_file},
|
|
||||||
Bundle, Editor, ReadError,
|
|
||||||
};
|
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
#[derive(Parser)]
|
|
||||||
#[command(version, about, long_about = None)]
|
|
||||||
struct Cli {
|
|
||||||
#[command(subcommand)]
|
|
||||||
command: Option<Commands>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
|
||||||
enum Commands {
|
|
||||||
/// Edit, potentially creating, a key
|
|
||||||
EditKey {
|
|
||||||
#[arg(short, long)]
|
|
||||||
key: String,
|
|
||||||
#[arg(short, long)]
|
|
||||||
locale: Option<String>,
|
|
||||||
},
|
|
||||||
/// List al keys in the database
|
|
||||||
ListKeys,
|
|
||||||
// Search the database
|
|
||||||
// Search { },
|
|
||||||
Import {
|
|
||||||
#[arg(short, long)]
|
|
||||||
file: String,
|
|
||||||
},
|
|
||||||
/// Export the database
|
|
||||||
Export {
|
|
||||||
#[arg(short, long)]
|
|
||||||
format: String,
|
|
||||||
#[arg(short, long)]
|
|
||||||
file: String,
|
|
||||||
#[arg(short, long)]
|
|
||||||
locale: Option<String>,
|
|
||||||
},
|
|
||||||
Report,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
struct Config {
|
|
||||||
db_path: PathBuf,
|
|
||||||
base_locale: LanguageIdentifier,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn edit_key(bundle: &mut Bundle, key: String, locale: LanguageIdentifier, editor: &str) {
|
|
||||||
let message = bundle.message(key);
|
|
||||||
Editor::edit(message, locale, editor);
|
|
||||||
bundle.save();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
|
||||||
struct Report {
|
|
||||||
keys: Vec<String>,
|
|
||||||
// source_deleted: Vec<String>,
|
|
||||||
out_of_date: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for Report {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
writeln!(f, "{} messages in bundle", self.keys.len())?;
|
|
||||||
writeln!(f, "Out of date messages")?;
|
|
||||||
for key in self.out_of_date.iter() {
|
|
||||||
writeln!(f, "\t{}", key)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate_report(bundle: &Bundle, base_locale: &LanguageIdentifier) -> Report {
|
|
||||||
let mut report: Report = Default::default();
|
|
||||||
for (key, message) in bundle.message_iter() {
|
|
||||||
report.keys.push(key.to_owned());
|
|
||||||
if !message.variants_out_of_date(base_locale).is_empty() {
|
|
||||||
report.out_of_date.push(key.to_owned())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
report
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let editor = std::env::var("EDITOR").expect("Set EDITOR to the path to your favorite editor");
|
|
||||||
|
|
||||||
let config: Config = read_file(&PathBuf::from("./config.toml"))
|
|
||||||
.and_then(|bytes| String::from_utf8(bytes).map_err(|_| ReadError::InvalidFormat))
|
|
||||||
.and_then(|content| toml::from_str(&content).map_err(|_| ReadError::InvalidFormat))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let cli = Cli::parse();
|
|
||||||
|
|
||||||
let mut bundle = Bundle::load_from_disk(PathBuf::from(&config.db_path));
|
|
||||||
|
|
||||||
match &cli.command {
|
|
||||||
Some(Commands::EditKey { key, locale }) => {
|
|
||||||
let identifier = locale.as_ref()
|
|
||||||
.map(|l| l.parse::<LanguageIdentifier>().unwrap())
|
|
||||||
.unwrap_or(config.base_locale);
|
|
||||||
edit_key(&mut bundle, key.to_owned(), identifier, &editor)
|
|
||||||
}
|
|
||||||
Some(Commands::ListKeys) => {
|
|
||||||
for (key, _) in bundle.message_iter() {
|
|
||||||
println!("{}", key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(Commands::Import { file }) => {
|
|
||||||
import_file(&mut bundle, &PathBuf::from(file)).unwrap();
|
|
||||||
bundle.save();
|
|
||||||
}
|
|
||||||
Some(Commands::Export {
|
|
||||||
format,
|
|
||||||
file,
|
|
||||||
locale,
|
|
||||||
}) => {
|
|
||||||
let locale = locale
|
|
||||||
.as_ref()
|
|
||||||
.map(|l| l.clone().parse::<LanguageIdentifier>().unwrap())
|
|
||||||
.unwrap_or(langid!("en"));
|
|
||||||
|
|
||||||
match format.as_ref() {
|
|
||||||
"js" => js::export_file(&bundle, locale, &PathBuf::from(file)).unwrap(),
|
|
||||||
"xliff" => {
|
|
||||||
xliff::export_file(&bundle, locale, &PathBuf::from(file)).unwrap()
|
|
||||||
}
|
|
||||||
_ => todo!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(Commands::Report) => {
|
|
||||||
let report = generate_report(&bundle, &config.base_locale);
|
|
||||||
println!("{}", report);
|
|
||||||
}
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,143 +0,0 @@
|
|||||||
use std::{collections::HashMap, fs::File, io::{BufReader, Read, Write}, path::{Path, PathBuf}};
|
|
||||||
|
|
||||||
use chrono::{DateTime, Utc};
|
|
||||||
use icu_locid::LanguageIdentifier;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
pub struct Bundle {
|
|
||||||
path: PathBuf,
|
|
||||||
messages: HashMap<String, Message>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Bundle {
|
|
||||||
pub fn load_from_disk(path: PathBuf) -> Self {
|
|
||||||
let mut messages = HashMap::new();
|
|
||||||
if path.is_dir() {
|
|
||||||
for entry in std::fs::read_dir(&path).unwrap() {
|
|
||||||
let entry = entry.unwrap();
|
|
||||||
let path = entry.path().clone();
|
|
||||||
let key = path.file_stem().unwrap();
|
|
||||||
|
|
||||||
let message = Message::from_file(&entry.path());
|
|
||||||
messages.insert(key.to_str().unwrap().to_owned(), message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Self { path, messages }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn message_iter(&self) -> impl Iterator<Item = (&String, &Message)> {
|
|
||||||
self.messages.iter()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn message(&mut self, name: String) -> &mut Message {
|
|
||||||
self.messages
|
|
||||||
.entry(name.to_owned())
|
|
||||||
.or_insert(Message::new(name.to_owned()))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn save(&self) {
|
|
||||||
self.messages.iter().for_each(|(key, value)| {
|
|
||||||
let mut path = self.path.clone();
|
|
||||||
path.push(key);
|
|
||||||
path.set_extension("toml");
|
|
||||||
save_file(&path, toml::to_string(value).unwrap().as_bytes());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn save_file(path: &PathBuf, s: &[u8]) {
|
|
||||||
let mut f = File::create(path).unwrap();
|
|
||||||
let _ = f.write(s).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
|
||||||
pub struct Message {
|
|
||||||
key: String,
|
|
||||||
description: String,
|
|
||||||
variants: HashMap<LanguageIdentifier, Variant>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Message {
|
|
||||||
pub fn new(key: String) -> Self {
|
|
||||||
Self {
|
|
||||||
key,
|
|
||||||
description: "".to_owned(),
|
|
||||||
variants: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_file(path: &Path) -> Message {
|
|
||||||
let file = std::fs::File::open(path).unwrap();
|
|
||||||
let mut content = Vec::new();
|
|
||||||
let mut reader = BufReader::new(file);
|
|
||||||
let _ = reader.read_to_end(&mut content);
|
|
||||||
toml::from_str(&String::from_utf8(content).unwrap()).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_description(&mut self, desc: String) {
|
|
||||||
self.description = desc;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn description(&self) -> &str {
|
|
||||||
&self.description
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn variant(&self, locale: &LanguageIdentifier) -> Option<&Variant> {
|
|
||||||
self.variants.get(locale)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn variant_mut(&mut self, locale: LanguageIdentifier) -> &mut Variant {
|
|
||||||
self.variants.entry(locale.clone()).or_insert(Variant {
|
|
||||||
locale,
|
|
||||||
content: "".to_owned(),
|
|
||||||
modified: Utc::now(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn variants_out_of_date(
|
|
||||||
&self,
|
|
||||||
base_locale: &LanguageIdentifier,
|
|
||||||
) -> Vec<LanguageIdentifier> {
|
|
||||||
match self
|
|
||||||
.variants
|
|
||||||
.get(base_locale)
|
|
||||||
.map(|variant| variant.modified())
|
|
||||||
{
|
|
||||||
Some(base_date) => self
|
|
||||||
.variants
|
|
||||||
.iter()
|
|
||||||
.filter(|(_, value)| base_date > value.modified())
|
|
||||||
.map(|(locale, _)| locale.clone())
|
|
||||||
.collect(),
|
|
||||||
None => vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// pub fn missing_variants(&self, locals: Vec<LanguageIdentifier>) -> Vec<LanguageIdentifier> {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
|
||||||
pub struct Variant {
|
|
||||||
locale: LanguageIdentifier,
|
|
||||||
content: String,
|
|
||||||
modified: DateTime<Utc>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Variant {
|
|
||||||
pub fn content(&self) -> &str {
|
|
||||||
&self.content
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_content(&mut self, content: String) {
|
|
||||||
self.content = content;
|
|
||||||
self.modified = Utc::now();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn modified(&self) -> DateTime<Utc> {
|
|
||||||
self.modified
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {}
|
|
@ -1,43 +0,0 @@
|
|||||||
use std::{io::Write, process::Command};
|
|
||||||
|
|
||||||
use icu_locid::{langid, LanguageIdentifier};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::{read_fh, Message};
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
||||||
struct EditorMessage {
|
|
||||||
description: String,
|
|
||||||
source: String,
|
|
||||||
content: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Editor {}
|
|
||||||
|
|
||||||
impl Editor {
|
|
||||||
pub fn edit(msg: &mut Message, locale: LanguageIdentifier, editor: &str) {
|
|
||||||
let description = msg.description().to_owned();
|
|
||||||
let source_string = msg.variant_mut(langid!("en")).content().to_owned();
|
|
||||||
let variant = msg.variant_mut(locale);
|
|
||||||
// let editable_content = EditorMessage::from_variant(description, &variant);
|
|
||||||
let editable_content = EditorMessage {
|
|
||||||
description,
|
|
||||||
source: source_string,
|
|
||||||
content: variant.content().to_owned(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut file = tempfile::NamedTempFile::new().unwrap();
|
|
||||||
let _ = file.write(toml::to_string(&editable_content).unwrap().as_bytes());
|
|
||||||
let _ = file.flush();
|
|
||||||
let mut cmd = Command::new(editor).args([file.path()]).spawn().unwrap();
|
|
||||||
cmd.wait().unwrap();
|
|
||||||
let file = file.reopen().unwrap();
|
|
||||||
let content = read_fh(&file).unwrap();
|
|
||||||
|
|
||||||
let new_variant: EditorMessage =
|
|
||||||
toml::from_str(&String::from_utf8(content).unwrap()).unwrap();
|
|
||||||
|
|
||||||
variant.set_content(new_variant.content);
|
|
||||||
msg.set_description(new_variant.description);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
use std::{collections::BTreeMap, fs::File, io::Write, path::Path};
|
|
||||||
|
|
||||||
use icu_locid::LanguageIdentifier;
|
|
||||||
|
|
||||||
use crate::{Bundle, WriteError};
|
|
||||||
|
|
||||||
pub fn export_file(bundle: &Bundle, locale: LanguageIdentifier, path: &Path) -> Result<(), WriteError> {
|
|
||||||
let mut file = File::create(path).unwrap();
|
|
||||||
export_fh(bundle, locale, &mut file)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn export_fh(bundle: &Bundle, locale: LanguageIdentifier, fh: &mut File) -> Result<(), WriteError> {
|
|
||||||
let messages = bundle.message_iter().map(|(key, message)| {
|
|
||||||
let content = message.variant(&locale).unwrap().content().to_owned();
|
|
||||||
(key.to_owned(), content)
|
|
||||||
}).collect::<Vec<(String, String)>>();
|
|
||||||
|
|
||||||
let messages: BTreeMap<String, String> = messages.into_iter().collect();
|
|
||||||
let _ = fh.write(serde_json::to_string_pretty(&messages).unwrap().as_bytes()).unwrap();
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
pub mod js;
|
|
||||||
pub mod xliff;
|
|
||||||
|
|
||||||
|
|
@ -1,146 +0,0 @@
|
|||||||
use std::{
|
|
||||||
fs::File,
|
|
||||||
io::{BufReader, Read, Write},
|
|
||||||
path::Path,
|
|
||||||
};
|
|
||||||
|
|
||||||
use icu_locid::{langid, LanguageIdentifier};
|
|
||||||
use xml::{attribute::OwnedAttribute, reader, writer, EmitterConfig, EventReader, EventWriter};
|
|
||||||
|
|
||||||
use crate::{Bundle, Message, ReadError, WriteError};
|
|
||||||
|
|
||||||
pub fn export_file(
|
|
||||||
bundle: &Bundle,
|
|
||||||
locale: LanguageIdentifier,
|
|
||||||
path: &Path,
|
|
||||||
) -> Result<(), WriteError> {
|
|
||||||
let mut file = File::create(path).unwrap();
|
|
||||||
export_fh(bundle, locale, &mut file)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn export_fh<W>(bundle: &Bundle, locale: LanguageIdentifier, fh: W) -> Result<(), WriteError>
|
|
||||||
where
|
|
||||||
W: Write,
|
|
||||||
{
|
|
||||||
let mut writer = EmitterConfig::new().perform_indent(true).create_writer(fh);
|
|
||||||
|
|
||||||
writer
|
|
||||||
.write(
|
|
||||||
writer::XmlEvent::start_element("xliff")
|
|
||||||
.attr("xmlns", "urn:oasis:names:tc:xliff:document:2.0")
|
|
||||||
.attr("version", "2.0")
|
|
||||||
.attr("srcLang", &format!("{}", locale)),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
writer
|
|
||||||
.write(writer::XmlEvent::start_element("file").attr("id", "main"))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
for (key, message) in bundle.message_iter() {
|
|
||||||
write_message(&mut writer, key, message, &locale);
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.write(writer::XmlEvent::end_element()).unwrap();
|
|
||||||
writer.write(writer::XmlEvent::end_element()).unwrap();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn import_file(bundle: &mut Bundle, path: &Path) -> Result<(), ReadError> {
|
|
||||||
let file = File::open(path).unwrap();
|
|
||||||
let file = BufReader::new(file);
|
|
||||||
|
|
||||||
import_reader(bundle, file)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn import_reader<R>(bundle: &mut Bundle, fh: R) -> Result<(), ReadError>
|
|
||||||
where
|
|
||||||
R: Read,
|
|
||||||
{
|
|
||||||
let parser = EventReader::new(fh);
|
|
||||||
|
|
||||||
let mut locale: LanguageIdentifier = langid!("en");
|
|
||||||
let mut current_key = None;
|
|
||||||
let mut current_text: Option<String> = None;
|
|
||||||
let mut in_target = false;
|
|
||||||
|
|
||||||
for event in parser {
|
|
||||||
match event {
|
|
||||||
Ok(reader::XmlEvent::StartElement {
|
|
||||||
name, attributes, ..
|
|
||||||
}) => match name.local_name.as_ref() {
|
|
||||||
"xliff" => {
|
|
||||||
locale = find_attribute(&attributes, "trgLang")
|
|
||||||
.unwrap()
|
|
||||||
.parse::<LanguageIdentifier>()
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
"unit" => current_key = find_attribute(&attributes, "id"),
|
|
||||||
"target" => in_target = true,
|
|
||||||
_ => println!("name: {}", name),
|
|
||||||
},
|
|
||||||
Ok(reader::XmlEvent::EndElement { name }) => match name.local_name.as_ref() {
|
|
||||||
"unit" => {
|
|
||||||
if let Some(key) = current_key {
|
|
||||||
let message = bundle.message(key);
|
|
||||||
let variant = message.variant_mut(locale.clone());
|
|
||||||
if let Some(ref text) = current_text {
|
|
||||||
variant.set_content(text.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
current_key = None;
|
|
||||||
}
|
|
||||||
"target" => in_target = false,
|
|
||||||
_ => {}
|
|
||||||
},
|
|
||||||
Ok(reader::XmlEvent::Characters(data)) => {
|
|
||||||
if in_target {
|
|
||||||
current_text = Some(data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("error: {e}");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_message<T>(
|
|
||||||
writer: &mut EventWriter<T>,
|
|
||||||
key: &str,
|
|
||||||
message: &Message,
|
|
||||||
locale: &LanguageIdentifier,
|
|
||||||
) where
|
|
||||||
T: std::io::Write,
|
|
||||||
{
|
|
||||||
[
|
|
||||||
writer::XmlEvent::start_element("unit")
|
|
||||||
.attr("id", key)
|
|
||||||
.into(),
|
|
||||||
writer::XmlEvent::start_element("notes").into(),
|
|
||||||
writer::XmlEvent::start_element("note").into(),
|
|
||||||
writer::XmlEvent::characters(message.description()),
|
|
||||||
writer::XmlEvent::end_element().into(),
|
|
||||||
writer::XmlEvent::end_element().into(),
|
|
||||||
writer::XmlEvent::start_element("segment").into(),
|
|
||||||
writer::XmlEvent::start_element("source").into(),
|
|
||||||
writer::XmlEvent::characters(message.variant(locale).unwrap().content()),
|
|
||||||
writer::XmlEvent::end_element().into(),
|
|
||||||
writer::XmlEvent::end_element().into(),
|
|
||||||
writer::XmlEvent::end_element().into(),
|
|
||||||
]
|
|
||||||
.into_iter()
|
|
||||||
.for_each(|elem: writer::XmlEvent| writer.write(elem).unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_attribute(attrs: &Vec<OwnedAttribute>, name: &str) -> Option<String> {
|
|
||||||
for f in attrs {
|
|
||||||
if name == f.name.local_name {
|
|
||||||
return Some(f.value.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
mod bundle;
|
|
||||||
pub use bundle::{Bundle, Message, Variant};
|
|
||||||
|
|
||||||
mod editor;
|
|
||||||
pub use editor::Editor;
|
|
||||||
|
|
||||||
mod formats;
|
|
||||||
pub use formats::{js, xliff};
|
|
||||||
|
|
||||||
mod utils;
|
|
||||||
pub use utils::*;
|
|
@ -1,37 +0,0 @@
|
|||||||
use std::{fs::File, io::{BufReader, ErrorKind, Read}, path::Path};
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
|
||||||
pub enum ReadError {
|
|
||||||
#[error("file not found")]
|
|
||||||
FileNotFound,
|
|
||||||
|
|
||||||
#[error("invalid file format")]
|
|
||||||
InvalidFormat,
|
|
||||||
|
|
||||||
#[error("unhandled read error")]
|
|
||||||
Unhandled(ErrorKind),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_file(path: &Path) -> Result<Vec<u8>, ReadError> {
|
|
||||||
let file = File::open(path).map_err(|err| {
|
|
||||||
match err.kind() {
|
|
||||||
ErrorKind::NotFound => ReadError::FileNotFound,
|
|
||||||
_ => ReadError::Unhandled( err.kind()),
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
read_fh(&file)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_fh(file: &File) -> Result<Vec<u8>, ReadError> {
|
|
||||||
let mut content = Vec::new();
|
|
||||||
let mut reader = BufReader::new(file);
|
|
||||||
reader.read_to_end(&mut content).map_err(|err| ReadError::Unhandled(err.kind()))?;
|
|
||||||
Ok(content)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
|
||||||
pub enum WriteError {
|
|
||||||
#[error("unhandled write error")]
|
|
||||||
Unhandled(ErrorKind),
|
|
||||||
}
|
|
@ -78,7 +78,7 @@ mod tests {
|
|||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(value, Value(16));
|
assert_eq!(value, Value(16));
|
||||||
assert!(*run.read().unwrap());
|
assert_eq!(*run.read().unwrap(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
@ -97,6 +97,6 @@ mod tests {
|
|||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(value, Value(15));
|
assert_eq!(value, Value(15));
|
||||||
assert!(!(*run.read().unwrap()));
|
assert_eq!(*run.read().unwrap(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,12 +80,12 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use cool_asserts::assert_matches;
|
use cool_asserts::assert_matches;
|
||||||
|
|
||||||
const DATA: &str = "15";
|
const DATA: &'static str = "15";
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn function() {
|
fn function() {
|
||||||
let resp = parse_number_a::<nom::error::VerboseError<&str>>()
|
let resp = parse_number_a::<nom::error::VerboseError<&str>>()
|
||||||
.map(Container)
|
.map(|val| Container(val))
|
||||||
.parse(DATA);
|
.parse(DATA);
|
||||||
assert_matches!(resp, Ok((_, content)) =>
|
assert_matches!(resp, Ok((_, content)) =>
|
||||||
assert_eq!(content, Container(15))
|
assert_eq!(content, Container(15))
|
||||||
@ -95,7 +95,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn parser() {
|
fn parser() {
|
||||||
let resp = parse_number_b::<nom::error::VerboseError<&str>>()
|
let resp = parse_number_b::<nom::error::VerboseError<&str>>()
|
||||||
.map(Container)
|
.map(|val| Container(val))
|
||||||
.parse(DATA);
|
.parse(DATA);
|
||||||
assert_matches!(resp, Ok((_, content)) =>
|
assert_matches!(resp, Ok((_, content)) =>
|
||||||
assert_eq!(content, Container(15))
|
assert_eq!(content, Container(15))
|
||||||
|
@ -396,7 +396,8 @@ mod test {
|
|||||||
(Coordinate { column: 17, row: 0 }, Color::White),
|
(Coordinate { column: 17, row: 0 }, Color::White),
|
||||||
(Coordinate { column: 17, row: 1 }, Color::White),
|
(Coordinate { column: 17, row: 1 }, Color::White),
|
||||||
(Coordinate { column: 18, row: 1 }, Color::White),
|
(Coordinate { column: 18, row: 1 }, Color::White),
|
||||||
],
|
]
|
||||||
|
.into_iter(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
test(board);
|
test(board);
|
||||||
@ -435,32 +436,33 @@ mod test {
|
|||||||
},
|
},
|
||||||
Color::Black,
|
Color::Black,
|
||||||
),
|
),
|
||||||
],
|
]
|
||||||
|
.into_iter(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(board.group(&Coordinate { column: 18, row: 3 }).is_none());
|
assert!(board.group(&Coordinate { column: 18, row: 3 }).is_none());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
board
|
board
|
||||||
.group(&Coordinate { column: 3, row: 3 })
|
.group(&Coordinate { column: 3, row: 3 })
|
||||||
.map(|g| board.liberties(g)),
|
.map(|g| board.liberties(&g)),
|
||||||
Some(4)
|
Some(4)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
board
|
board
|
||||||
.group(&Coordinate { column: 0, row: 3 })
|
.group(&Coordinate { column: 0, row: 3 })
|
||||||
.map(|g| board.liberties(g)),
|
.map(|g| board.liberties(&g)),
|
||||||
Some(3)
|
Some(3)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
board
|
board
|
||||||
.group(&Coordinate { column: 0, row: 0 })
|
.group(&Coordinate { column: 0, row: 0 })
|
||||||
.map(|g| board.liberties(g)),
|
.map(|g| board.liberties(&g)),
|
||||||
Some(2)
|
Some(2)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
board
|
board
|
||||||
.group(&Coordinate { column: 18, row: 9 })
|
.group(&Coordinate { column: 18, row: 9 })
|
||||||
.map(|g| board.liberties(g)),
|
.map(|g| board.liberties(&g)),
|
||||||
Some(3)
|
Some(3)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -469,7 +471,7 @@ mod test {
|
|||||||
column: 18,
|
column: 18,
|
||||||
row: 18
|
row: 18
|
||||||
})
|
})
|
||||||
.map(|g| board.liberties(g)),
|
.map(|g| board.liberties(&g)),
|
||||||
Some(2)
|
Some(2)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -612,7 +614,7 @@ mod test {
|
|||||||
for (board, coordinate, group, liberties) in test_cases {
|
for (board, coordinate, group, liberties) in test_cases {
|
||||||
assert_eq!(board.group(&coordinate), group.as_ref());
|
assert_eq!(board.group(&coordinate), group.as_ref());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
board.group(&coordinate).map(|g| board.liberties(g)),
|
board.group(&coordinate).map(|g| board.liberties(&g)),
|
||||||
liberties,
|
liberties,
|
||||||
"{:?}",
|
"{:?}",
|
||||||
coordinate
|
coordinate
|
||||||
@ -686,11 +688,11 @@ mod test {
|
|||||||
fn validate_group_comparisons() {
|
fn validate_group_comparisons() {
|
||||||
{
|
{
|
||||||
let b1 = Goban::from_coordinates(
|
let b1 = Goban::from_coordinates(
|
||||||
vec![(Coordinate { column: 7, row: 9 }, Color::White)],
|
vec![(Coordinate { column: 7, row: 9 }, Color::White)].into_iter(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let b2 = Goban::from_coordinates(
|
let b2 = Goban::from_coordinates(
|
||||||
vec![(Coordinate { column: 7, row: 9 }, Color::White)],
|
vec![(Coordinate { column: 7, row: 9 }, Color::White)].into_iter(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@ -702,14 +704,16 @@ mod test {
|
|||||||
vec![
|
vec![
|
||||||
(Coordinate { column: 7, row: 9 }, Color::White),
|
(Coordinate { column: 7, row: 9 }, Color::White),
|
||||||
(Coordinate { column: 8, row: 10 }, Color::White),
|
(Coordinate { column: 8, row: 10 }, Color::White),
|
||||||
],
|
]
|
||||||
|
.into_iter(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let b2 = Goban::from_coordinates(
|
let b2 = Goban::from_coordinates(
|
||||||
vec![
|
vec![
|
||||||
(Coordinate { column: 8, row: 10 }, Color::White),
|
(Coordinate { column: 8, row: 10 }, Color::White),
|
||||||
(Coordinate { column: 7, row: 9 }, Color::White),
|
(Coordinate { column: 7, row: 9 }, Color::White),
|
||||||
],
|
]
|
||||||
|
.into_iter(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
@ -728,7 +732,8 @@ mod test {
|
|||||||
(Coordinate { column: 10, row: 9 }, Color::Black),
|
(Coordinate { column: 10, row: 9 }, Color::Black),
|
||||||
(Coordinate { column: 9, row: 8 }, Color::Black),
|
(Coordinate { column: 9, row: 8 }, Color::Black),
|
||||||
(Coordinate { column: 9, row: 10 }, Color::Black),
|
(Coordinate { column: 9, row: 10 }, Color::Black),
|
||||||
],
|
]
|
||||||
|
.into_iter(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -587,7 +587,8 @@ mod test {
|
|||||||
(Coordinate { column: 17, row: 0 }, Color::White),
|
(Coordinate { column: 17, row: 0 }, Color::White),
|
||||||
(Coordinate { column: 17, row: 1 }, Color::White),
|
(Coordinate { column: 17, row: 1 }, Color::White),
|
||||||
(Coordinate { column: 18, row: 1 }, Color::White),
|
(Coordinate { column: 18, row: 1 }, Color::White),
|
||||||
],
|
]
|
||||||
|
.into_iter(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
state.current_player = Color::Black;
|
state.current_player = Color::Black;
|
||||||
@ -611,7 +612,8 @@ mod test {
|
|||||||
(Coordinate { column: 10, row: 9 }, Color::Black),
|
(Coordinate { column: 10, row: 9 }, Color::Black),
|
||||||
(Coordinate { column: 9, row: 8 }, Color::Black),
|
(Coordinate { column: 9, row: 8 }, Color::Black),
|
||||||
(Coordinate { column: 9, row: 10 }, Color::Black),
|
(Coordinate { column: 9, row: 10 }, Color::Black),
|
||||||
],
|
]
|
||||||
|
.into_iter(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -132,10 +132,10 @@ impl GameReviewViewModel {
|
|||||||
// the board state by applying the child.
|
// the board state by applying the child.
|
||||||
pub fn next_move(&self) {
|
pub fn next_move(&self) {
|
||||||
let mut inner = self.inner.write().unwrap();
|
let mut inner = self.inner.write().unwrap();
|
||||||
let current_position = inner.current_position;
|
let current_position = inner.current_position.clone();
|
||||||
match current_position {
|
match current_position {
|
||||||
Some(current_position) => {
|
Some(current_position) => {
|
||||||
let current_id = current_position;
|
let current_id = current_position.clone();
|
||||||
let node = inner.game.trees[0].get(current_id).unwrap();
|
let node = inner.game.trees[0].get(current_id).unwrap();
|
||||||
if let Some(next_id) = node.first_child().map(|child| child.node_id()) {
|
if let Some(next_id) = node.first_child().map(|child| child.node_id()) {
|
||||||
inner.current_position = Some(next_id);
|
inner.current_position = Some(next_id);
|
||||||
@ -180,7 +180,7 @@ mod test {
|
|||||||
where
|
where
|
||||||
F: FnOnce(GameReviewViewModel),
|
F: FnOnce(GameReviewViewModel),
|
||||||
{
|
{
|
||||||
let records = sgf::parse_sgf_file(Path::new("../../sgf/test_data/branch_test.sgf"))
|
let records = sgf::parse_sgf_file(&Path::new("../../sgf/test_data/branch_test.sgf"))
|
||||||
.expect("to successfully load the test file");
|
.expect("to successfully load the test file");
|
||||||
let record = records[0]
|
let record = records[0]
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -18,7 +18,7 @@ use crate::{CoreApi, ResourceManager};
|
|||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
|
|
||||||
use glib::Propagation;
|
use glib::Propagation;
|
||||||
use gtk::EventControllerKey;
|
use gtk::{gdk::Key, EventControllerKey};
|
||||||
use otg_core::{
|
use otg_core::{
|
||||||
settings::{SettingsRequest, SettingsResponse},
|
settings::{SettingsRequest, SettingsResponse},
|
||||||
CoreRequest, CoreResponse, GameReviewViewModel,
|
CoreRequest, CoreResponse, GameReviewViewModel,
|
||||||
|
@ -102,8 +102,14 @@ impl GameReview {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref mut goban) = *s.goban.borrow_mut() { goban.set_board_state(view.game_view()) };
|
match *s.goban.borrow_mut() {
|
||||||
if let Some(ref tree) = *s.review_tree.borrow() { tree.queue_draw() }
|
Some(ref mut goban) => goban.set_board_state(view.game_view()),
|
||||||
|
None => {}
|
||||||
|
};
|
||||||
|
match *s.review_tree.borrow() {
|
||||||
|
Some(ref tree) => tree.queue_draw(),
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
Propagation::Stop
|
Propagation::Stop
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -163,6 +169,9 @@ impl GameReview {
|
|||||||
*self.review_tree.borrow_mut() = Some(review_tree);
|
*self.review_tree.borrow_mut() = Some(review_tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn redraw(&self) {
|
||||||
|
}
|
||||||
|
|
||||||
pub fn widget(&self) -> gtk::Widget {
|
pub fn widget(&self) -> gtk::Widget {
|
||||||
self.widget.clone().upcast::<gtk::Widget>()
|
self.widget.clone().upcast::<gtk::Widget>()
|
||||||
}
|
}
|
||||||
|
10
otg/pwa/.eslintrc.js
Normal file
10
otg/pwa/.eslintrc.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
module.exports = {
|
||||||
|
env: {
|
||||||
|
node: true,
|
||||||
|
jest: true,
|
||||||
|
},
|
||||||
|
extends: ['plugin:@typescript-eslint/recommended', 'eslint:recommended'],
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
plugins: ['@typescript-eslint'],
|
||||||
|
root: true,
|
||||||
|
}
|
5
otg/pwa/jest.config.js
Normal file
5
otg/pwa/jest.config.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
/** @type {import('ts-jest').JestConfigWithTsJest} */
|
||||||
|
module.exports = {
|
||||||
|
preset: 'ts-jest',
|
||||||
|
testEnvironment: 'node',
|
||||||
|
};
|
5210
otg/pwa/package-lock.json
generated
Normal file
5210
otg/pwa/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
24
otg/pwa/package.json
Normal file
24
otg/pwa/package.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "otg-pwa",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc",
|
||||||
|
"lint": "eslint ./src/**/.ts",
|
||||||
|
"test": "jest",
|
||||||
|
"test:watch": "jest --watch"
|
||||||
|
},
|
||||||
|
"author": "Savanni D'Gerinel <savanni@luminescent-dreams.com>",
|
||||||
|
"license": "GPL-3.0-or-later",
|
||||||
|
"dependencies": {
|
||||||
|
"@typescript-eslint/eslint-plugin": "^7.10.0",
|
||||||
|
"@typescript-eslint/parser": "^7.10.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/jest": "^29.5.12",
|
||||||
|
"http-server": "^14.1.1",
|
||||||
|
"jest": "^29.7.0",
|
||||||
|
"ts-jest": "^29.1.3"
|
||||||
|
}
|
||||||
|
}
|
37
otg/pwa/src/conversions.test.ts
Normal file
37
otg/pwa/src/conversions.test.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { c_to_k, f_to_k, k_to_c, k_to_f } from './conversions';
|
||||||
|
|
||||||
|
describe('temperature conversions', () => {
|
||||||
|
it('should convert celsius to kelvin', () => {
|
||||||
|
expect(c_to_k(0)).toBe(273.15);
|
||||||
|
expect(c_to_k(100)).toBe(373.15);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert fahrenheit to kelvin', () => {
|
||||||
|
expect(f_to_k(32)).toBe(273.15);
|
||||||
|
expect(f_to_k(212)).toBe(373.15);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert kelvin to celsius', () => {
|
||||||
|
expect(k_to_c(273.15)).toBe(0);
|
||||||
|
expect(k_to_c(373.15)).toBe(100);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert kelvin to fahrenheit', () => {
|
||||||
|
expect(k_to_f(273.15)).toBe(32);
|
||||||
|
expect(k_to_f(373.15)).toBe(212);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
import { getMessage } from './index'
|
||||||
|
|
||||||
|
describe('getMessage()', () => {
|
||||||
|
it('should return the correct message when called', () => {
|
||||||
|
expect(getMessage()).toBe('Hello, world')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should be super smart', () => {
|
||||||
|
expect(true).toBe(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
*/
|
6
otg/pwa/src/conversions.ts
Normal file
6
otg/pwa/src/conversions.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export const c_to_k = (value: number) => value + 273.15;
|
||||||
|
export const f_to_k = (value: number) => ((value - 32) * 5 / 9) + 273.15;
|
||||||
|
export const k_to_c = (value: number) => value - 273.15;
|
||||||
|
export const k_to_f = (value: number) => (value - 273.15) * 9 / 5 + 32;
|
||||||
|
|
||||||
|
|
18
otg/pwa/src/index.html
Normal file
18
otg/pwa/src/index.html
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>On The Grid</title>
|
||||||
|
<style>
|
||||||
|
:body {
|
||||||
|
font-family: "sans-serif";
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module" src="./index.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
83
otg/pwa/src/index.ts
Normal file
83
otg/pwa/src/index.ts
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
import { c_to_k, f_to_k, k_to_c, k_to_f } from './conversions';
|
||||||
|
|
||||||
|
interface TemperatureChanged {
|
||||||
|
source: string,
|
||||||
|
value: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
class TemperatureField extends HTMLElement {
|
||||||
|
static observedAttributes = ['value'];
|
||||||
|
|
||||||
|
value = 0;
|
||||||
|
inputElement: HTMLInputElement;
|
||||||
|
shadow: ShadowRoot;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.inputElement = document.createElement('input');
|
||||||
|
this.inputElement.type = "text";
|
||||||
|
this.shadow = this.attachShadow({ mode: 'open' });
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
this.render();
|
||||||
|
this.inputElement.onchange = ev => {
|
||||||
|
if (ev.target instanceof HTMLInputElement) {
|
||||||
|
let value = parseFloat(ev.target.value);
|
||||||
|
|
||||||
|
if (this.id == "f") {
|
||||||
|
const event = new CustomEvent('temperature-changed', { detail: { source: this.id, value: f_to_k(value) } });
|
||||||
|
this.dispatchEvent(event);
|
||||||
|
} else if (this.id == "c") {
|
||||||
|
const event = new CustomEvent('temperature-changed', { detail: { source: this.id, value: c_to_k(value) } });
|
||||||
|
this.dispatchEvent(event);
|
||||||
|
} else if (this.id == "k") {
|
||||||
|
const event = new CustomEvent('temperature-changed', { detail: { source: this.id, value } });
|
||||||
|
this.dispatchEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
this.shadow.appendChild(this.inputElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTemperature(v: number) {
|
||||||
|
console.log("set the temperature on ", this.id, "to ", v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class App {
|
||||||
|
temperatureK = 0;
|
||||||
|
|
||||||
|
updateTemperature(value: number) {
|
||||||
|
const f = document.getElementById("f");
|
||||||
|
if (f instanceof TemperatureField) {
|
||||||
|
f.setTemperature(value);
|
||||||
|
}
|
||||||
|
const c = document.getElementById("c");
|
||||||
|
if (c instanceof TemperatureField) {
|
||||||
|
c.setTemperature(value);
|
||||||
|
}
|
||||||
|
const k = document.getElementById("k");
|
||||||
|
if (k instanceof TemperatureField) {
|
||||||
|
k.setTemperature(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.customElements.define('temperature-field', TemperatureField);
|
||||||
|
|
||||||
|
const app = new App();
|
||||||
|
|
||||||
|
document.getElementById("f")?.addEventListener('temperature-changed', ev => {
|
||||||
|
if (ev instanceof CustomEvent) { app.updateTemperature(ev.detail.value) }
|
||||||
|
});
|
||||||
|
document.getElementById("c")?.addEventListener('temperature-changed', ev => {
|
||||||
|
if (ev instanceof CustomEvent) { app.updateTemperature(ev.detail.value) }
|
||||||
|
});
|
||||||
|
document.getElementById("k")?.addEventListener('temperature-changed', ev => {
|
||||||
|
if (ev instanceof CustomEvent) { app.updateTemperature(ev.detail.value) }
|
||||||
|
});
|
||||||
|
|
@ -1,15 +1,13 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es2016",
|
"strict": true,
|
||||||
|
"target": "ESNext",
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"declaration": true,
|
"rootDir": "./src",
|
||||||
"declarationMap": true,
|
|
||||||
"sourceMap": true,
|
|
||||||
"outDir": "./dist",
|
"outDir": "./dist",
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"skipLibCheck": true
|
"skipLibCheck": true
|
||||||
},
|
}
|
||||||
"include": ["./visions.ts"]
|
|
||||||
}
|
}
|
@ -1,12 +0,0 @@
|
|||||||
[build]
|
|
||||||
target = "thumbv6m-none-eabi"
|
|
||||||
|
|
||||||
[target.thumbv6m-none-eabi]
|
|
||||||
rustflags = [
|
|
||||||
"-C", "link-arg=--nmagic",
|
|
||||||
"-C", "link-arg=-Tlink.x",
|
|
||||||
"-C", "llvm-args=--inline-threshold=5",
|
|
||||||
"-C", "no-vectorize-loops",
|
|
||||||
]
|
|
||||||
|
|
||||||
runner = "elf2uf2-rs -d"
|
|
@ -1,11 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "halloween-leds"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
cortex-m-rt = "0.7.3"
|
|
||||||
embedded-hal = "1.0.0"
|
|
||||||
embedded-io = "0.6.1"
|
|
||||||
panic-halt = "1.0.0"
|
|
||||||
rp-pico = "0.9.0"
|
|
@ -1,125 +0,0 @@
|
|||||||
#![no_main]
|
|
||||||
#![no_std]
|
|
||||||
|
|
||||||
/// This application demonstrates using a Raspberry Pi Pico to control an individual SK9822 module.
|
|
||||||
/// Keep in mind that the Pico, though it accepts 5V for power, it runs on 3.3V logic. The GPIO
|
|
||||||
/// pins will emit only 3.3 volts, and the SK9822 needs 5V logic. So, make sure that the GPIO pins
|
|
||||||
/// run through a transistor or a logic level lhifter to go from 3.3V logic to 5V logic.
|
|
||||||
use embedded_hal::{delay::DelayNs, spi::SpiBus};
|
|
||||||
use panic_halt as _;
|
|
||||||
use rp_pico::{
|
|
||||||
entry,
|
|
||||||
hal::{
|
|
||||||
clocks::init_clocks_and_plls,
|
|
||||||
fugit::RateExtU32,
|
|
||||||
gpio::{
|
|
||||||
bank0::{Gpio10, Gpio11},
|
|
||||||
FunctionSpi, Pin, PullDown,
|
|
||||||
},
|
|
||||||
spi::Spi,
|
|
||||||
Clock, Sio, Timer, Watchdog,
|
|
||||||
},
|
|
||||||
pac, Pins,
|
|
||||||
};
|
|
||||||
|
|
||||||
const FPS: u32 = 60;
|
|
||||||
const MS_PER_FRAME: u32 = 1000 / FPS;
|
|
||||||
const XOSC_CRYSTAL_FREQ: u32 = 12_000_000; // MHz, https://forums.raspberrypi.com/viewtopic.php?t=356764
|
|
||||||
|
|
||||||
#[entry]
|
|
||||||
unsafe fn main() -> ! {
|
|
||||||
// rp_pico::pac::Peripherals is a reference to physical hardware defined on the Pico.
|
|
||||||
let mut peripherals = pac::Peripherals::take().unwrap();
|
|
||||||
|
|
||||||
// SIO inidcates "Single Cycle IO". I don't know what this means, but it could mean that this
|
|
||||||
// is a class of IO operations that can be run in a single clock cycle, such as switching a
|
|
||||||
// GPIO pin on or off.
|
|
||||||
let sio = Sio::new(peripherals.SIO);
|
|
||||||
|
|
||||||
// Many of the following systems require a watchdog. I do not know what this does, either, but
|
|
||||||
// it may be some failsafe software that will reset operations if the watchdog detects a lack
|
|
||||||
// of activity.
|
|
||||||
let mut watchdog = Watchdog::new(peripherals.WATCHDOG);
|
|
||||||
|
|
||||||
// Here we grab the GPIO pins in bank 0.
|
|
||||||
let pins = Pins::new(
|
|
||||||
peripherals.IO_BANK0,
|
|
||||||
peripherals.PADS_BANK0,
|
|
||||||
sio.gpio_bank0,
|
|
||||||
&mut peripherals.RESETS,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Initialize an abstraction of the clock system with a batch of standard hardware clocks.
|
|
||||||
let clocks = init_clocks_and_plls(
|
|
||||||
XOSC_CRYSTAL_FREQ,
|
|
||||||
peripherals.XOSC,
|
|
||||||
peripherals.CLOCKS,
|
|
||||||
peripherals.PLL_SYS,
|
|
||||||
peripherals.PLL_USB,
|
|
||||||
&mut peripherals.RESETS,
|
|
||||||
&mut watchdog,
|
|
||||||
)
|
|
||||||
.ok()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// An abstraction for a timer which we can use to delay the code.
|
|
||||||
let mut timer = Timer::new(peripherals.TIMER, &mut peripherals.RESETS, &clocks);
|
|
||||||
|
|
||||||
// Grab the clock and data pins for SPI1. For Clock pins and for Data pins, there are only two
|
|
||||||
// pins each on the Pico which can function for SPI1.
|
|
||||||
let spi_clk: Pin<Gpio10, FunctionSpi, PullDown> = pins.gpio10.into_function();
|
|
||||||
let spi_sdo: Pin<Gpio11, FunctionSpi, PullDown> = pins.gpio11.into_function();
|
|
||||||
|
|
||||||
// Now, create the SPI function abstraction for SPI1 with spi_clk and spi_sdo.
|
|
||||||
let mut spi = Spi::<_, _, _, 8>::new(peripherals.SPI1, (spi_sdo, spi_clk)).init(
|
|
||||||
&mut peripherals.RESETS,
|
|
||||||
// The SPI system uses the peripheral clock
|
|
||||||
clocks.peripheral_clock.freq(),
|
|
||||||
// Transmit data at a rate of 1Mbit.
|
|
||||||
1_u32.MHz(),
|
|
||||||
// Run with SPI Mode 1. This means that the clock line should start high and that data will
|
|
||||||
// be sampled starting at the first falling edge.
|
|
||||||
embedded_hal::spi::MODE_1,
|
|
||||||
);
|
|
||||||
|
|
||||||
// byte count: 4 for the start frame
|
|
||||||
// 1 * 4 for three lights with 4 bytes per light
|
|
||||||
// 4 for the end frame
|
|
||||||
// = 20 bytes
|
|
||||||
let mut lights: [u8; 12] = [0; 12];
|
|
||||||
// We just skip the first four bytes, because the start frame is four bytes of 0.
|
|
||||||
|
|
||||||
// Set the first byte of the one and only lamp. The first byte follows the pattern of three 1
|
|
||||||
// bits followed by five additional bits that indicate an overall brightness level of the
|
|
||||||
// pixel. The datasheet for the SK9822 doesn't specify the exact effect, but it does mean that
|
|
||||||
// the higher this number is, the brighter 255 means for an given LED in the array. 1 is the
|
|
||||||
// lowest brightness that emits light, and 31 is the highest supported brightness.
|
|
||||||
lights[4] = 0xe0 + 1;
|
|
||||||
// Set the Blue light of the dotstar to 255, assuming the dotstar frame format is RBG. Note
|
|
||||||
// that the standard SK9822 datasheed indicates that the format is BGR. Your mileage may vary.
|
|
||||||
lights[6] = 255;
|
|
||||||
|
|
||||||
// The end frame is four bytes of 255.
|
|
||||||
lights[8] = 0xff;
|
|
||||||
lights[9] = 0xff;
|
|
||||||
lights[10] = 0xff;
|
|
||||||
lights[11] = 0xff;
|
|
||||||
|
|
||||||
|
|
||||||
// The rest of this is just a stock pulsating animation which is slightly brightening and
|
|
||||||
// dimming the *blue* LED (on my set of dotstars).
|
|
||||||
let mut brightness = 1;
|
|
||||||
let mut step = 1;
|
|
||||||
loop {
|
|
||||||
if brightness == 64 && step == 1 {
|
|
||||||
step = -1;
|
|
||||||
} else if brightness == 1 && step == -1 {
|
|
||||||
step = 1;
|
|
||||||
};
|
|
||||||
lights[5] = brightness as u8;
|
|
||||||
brightness = brightness + step;
|
|
||||||
|
|
||||||
let _ = spi.write(lights.as_slice());
|
|
||||||
timer.delay_ms(MS_PER_FRAME);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
[build]
|
|
||||||
target = "thumbv6m-none-eabi"
|
|
||||||
|
|
||||||
[target.thumbv6m-none-eabi]
|
|
||||||
rustflags = [
|
|
||||||
"-C", "link-arg=--nmagic",
|
|
||||||
"-C", "link-arg=-Tlink.x",
|
|
||||||
"-C", "no-vectorize-loops",
|
|
||||||
]
|
|
||||||
|
|
||||||
runner = "elf2uf2-rs -d"
|
|
@ -1,13 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "pico-st7789"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
bitflags = "2.9.0"
|
|
||||||
cortex-m-rt = "0.7.3"
|
|
||||||
embedded-alloc = "0.6.0"
|
|
||||||
embedded-hal = "1.0.0"
|
|
||||||
fugit = "0.3.7"
|
|
||||||
panic-halt = "1.0.0"
|
|
||||||
rp-pico = "0.9.0"
|
|
@ -1,62 +0,0 @@
|
|||||||
// a a a
|
|
||||||
// f b
|
|
||||||
// f b
|
|
||||||
// f b
|
|
||||||
// g g g
|
|
||||||
// e c
|
|
||||||
// e c
|
|
||||||
// e c
|
|
||||||
// d d d
|
|
||||||
|
|
||||||
use crate::font::{Font, Glyph};
|
|
||||||
|
|
||||||
pub struct RGB {
|
|
||||||
pub r: u8,
|
|
||||||
pub g: u8,
|
|
||||||
pub b: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Canvas {
|
|
||||||
fn set_pixel(&mut self, x: usize, y: usize, color: &RGB);
|
|
||||||
|
|
||||||
fn fill(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, color: &RGB) {
|
|
||||||
for x in x1..x2 + 1 {
|
|
||||||
for y in y1..y2 + 1 {
|
|
||||||
self.set_pixel(x, y, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn square(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, color: &RGB) {
|
|
||||||
for x in x1..x2 + 1 {
|
|
||||||
self.set_pixel(x, y1, color);
|
|
||||||
}
|
|
||||||
for x in x1..x2 + 1 {
|
|
||||||
self.set_pixel(x, y2, color);
|
|
||||||
}
|
|
||||||
for y in y1..y2 + 1 {
|
|
||||||
self.set_pixel(x1, y, color);
|
|
||||||
}
|
|
||||||
for y in y1..y2 + 1 {
|
|
||||||
self.set_pixel(x2, y, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn print<A>(
|
|
||||||
canvas: &mut impl Canvas,
|
|
||||||
font: &impl Font<A>,
|
|
||||||
sx: usize,
|
|
||||||
sy: usize,
|
|
||||||
text: &str,
|
|
||||||
color: &RGB,
|
|
||||||
) where
|
|
||||||
A: Glyph,
|
|
||||||
{
|
|
||||||
let mut x = sx;
|
|
||||||
for c in text.chars().map(|c| font.glyph(c)) {
|
|
||||||
c.draw(canvas, x, sy, color);
|
|
||||||
let (dx, _) = c.extents();
|
|
||||||
x = x + dx + 1;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,513 +0,0 @@
|
|||||||
use alloc::collections::btree_map::BTreeMap;
|
|
||||||
|
|
||||||
use crate::canvas::{Canvas, RGB};
|
|
||||||
|
|
||||||
use super::{Font, Glyph};
|
|
||||||
|
|
||||||
pub struct BitmapGlyph([u8; 7]);
|
|
||||||
|
|
||||||
pub struct BitmapFont(BTreeMap<char, BitmapGlyph>);
|
|
||||||
|
|
||||||
impl BitmapFont {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
let mut font = BTreeMap::new();
|
|
||||||
font.insert(' ', BitmapGlyph([
|
|
||||||
0b00000,
|
|
||||||
0b00000,
|
|
||||||
0b00000,
|
|
||||||
0b00000,
|
|
||||||
0b00000,
|
|
||||||
0b00000,
|
|
||||||
0b00000,
|
|
||||||
]));
|
|
||||||
font.insert(
|
|
||||||
':',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b00000,
|
|
||||||
0b00100,
|
|
||||||
0b00100,
|
|
||||||
0b00000,
|
|
||||||
0b00100,
|
|
||||||
0b00100,
|
|
||||||
0b00000,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'/',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b00001,
|
|
||||||
0b00010,
|
|
||||||
0b00010,
|
|
||||||
0b00100,
|
|
||||||
0b01000,
|
|
||||||
0b01000,
|
|
||||||
0b10000,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'0',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b01110,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10101,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b01110,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'1',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b00001,
|
|
||||||
0b00011,
|
|
||||||
0b00101,
|
|
||||||
0b00001,
|
|
||||||
0b00001,
|
|
||||||
0b00001,
|
|
||||||
0b00001,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'2',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b01110,
|
|
||||||
0b10001,
|
|
||||||
0b00001,
|
|
||||||
0b00010,
|
|
||||||
0b00100,
|
|
||||||
0b01000,
|
|
||||||
0b11111,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'3',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b01110,
|
|
||||||
0b10001,
|
|
||||||
0b00001,
|
|
||||||
0b01110,
|
|
||||||
0b00001,
|
|
||||||
0b10001,
|
|
||||||
0b01110,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'4',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b11111,
|
|
||||||
0b00001,
|
|
||||||
0b00001,
|
|
||||||
0b00001,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'5',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b11111,
|
|
||||||
0b10000,
|
|
||||||
0b10000,
|
|
||||||
0b11111,
|
|
||||||
0b00001,
|
|
||||||
0b10001,
|
|
||||||
0b01110,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'6',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b01110,
|
|
||||||
0b10001,
|
|
||||||
0b10000,
|
|
||||||
0b11110,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b01110,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'7',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b11111,
|
|
||||||
0b00001,
|
|
||||||
0b00010,
|
|
||||||
0b00110,
|
|
||||||
0b00100,
|
|
||||||
0b01000,
|
|
||||||
0b01000,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'8',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b01110,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b01110,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b01110,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'9',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b01110,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b01111,
|
|
||||||
0b00001,
|
|
||||||
0b00001,
|
|
||||||
0b01110,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'A',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b00100,
|
|
||||||
0b01010,
|
|
||||||
0b01010,
|
|
||||||
0b10001,
|
|
||||||
0b11111,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'B',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b11110,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b1111 ,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b11110,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'C',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b01110,
|
|
||||||
0b10001,
|
|
||||||
0b10000,
|
|
||||||
0b10000,
|
|
||||||
0b10000,
|
|
||||||
0b10001,
|
|
||||||
0b01110,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'D',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b11110,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b11110,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'E',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b11111,
|
|
||||||
0b10000,
|
|
||||||
0b10000,
|
|
||||||
0b11111,
|
|
||||||
0b10000,
|
|
||||||
0b10000,
|
|
||||||
0b11111,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'F',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b11111,
|
|
||||||
0b10000,
|
|
||||||
0b10000,
|
|
||||||
0b11110,
|
|
||||||
0b10000,
|
|
||||||
0b10000,
|
|
||||||
0b10000,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'G',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b01110,
|
|
||||||
0b10001,
|
|
||||||
0b10000,
|
|
||||||
0b10011,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b01110,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'H',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b11111,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'I',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b11111,
|
|
||||||
0b00100,
|
|
||||||
0b00100,
|
|
||||||
0b00100,
|
|
||||||
0b00100,
|
|
||||||
0b00100,
|
|
||||||
0b11111,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'J',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b00111,
|
|
||||||
0b00001,
|
|
||||||
0b00001,
|
|
||||||
0b00001,
|
|
||||||
0b00001,
|
|
||||||
0b10001,
|
|
||||||
0b01110,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'K',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b10001,
|
|
||||||
0b10010,
|
|
||||||
0b10100,
|
|
||||||
0b11000,
|
|
||||||
0b10100,
|
|
||||||
0b10010,
|
|
||||||
0b10001,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'L',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b10000,
|
|
||||||
0b10000,
|
|
||||||
0b10000,
|
|
||||||
0b10000,
|
|
||||||
0b10000,
|
|
||||||
0b10000,
|
|
||||||
0b11111,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'M',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b10001,
|
|
||||||
0b11011,
|
|
||||||
0b10101,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'N',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b10001,
|
|
||||||
0b11001,
|
|
||||||
0b11001,
|
|
||||||
0b10101,
|
|
||||||
0b10011,
|
|
||||||
0b10011,
|
|
||||||
0b10001,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'O',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b01110,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b01110,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'P',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b11110,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b11110,
|
|
||||||
0b10000,
|
|
||||||
0b10000,
|
|
||||||
0b10000,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'Q',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b01110,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10101,
|
|
||||||
0b10011,
|
|
||||||
0b01110,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'R',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b11110,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b11110,
|
|
||||||
0b10100,
|
|
||||||
0b10010,
|
|
||||||
0b10001,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'S',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b01110,
|
|
||||||
0b10001,
|
|
||||||
0b10000,
|
|
||||||
0b01110,
|
|
||||||
0b00001,
|
|
||||||
0b10001,
|
|
||||||
0b01110,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'T',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b11111,
|
|
||||||
0b00100,
|
|
||||||
0b00100,
|
|
||||||
0b00100,
|
|
||||||
0b00100,
|
|
||||||
0b00100,
|
|
||||||
0b00100,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'U',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b01110,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'V',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b01010,
|
|
||||||
0b01010,
|
|
||||||
0b00100,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'W',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b10101,
|
|
||||||
0b10101,
|
|
||||||
0b01010,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'X',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b01010,
|
|
||||||
0b00100,
|
|
||||||
0b01010,
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'Y',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b10001,
|
|
||||||
0b10001,
|
|
||||||
0b01010,
|
|
||||||
0b00100,
|
|
||||||
0b00100,
|
|
||||||
0b00100,
|
|
||||||
0b00100,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'Z',
|
|
||||||
BitmapGlyph([
|
|
||||||
0b11111,
|
|
||||||
0b00001,
|
|
||||||
0b00010,
|
|
||||||
0b00100,
|
|
||||||
0b01000,
|
|
||||||
0b10000,
|
|
||||||
0b11111,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
Self(font)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Font<BitmapGlyph> for BitmapFont {
|
|
||||||
fn glyph(&self, c: char) -> &BitmapGlyph {
|
|
||||||
self.0.get(&c).unwrap_or(self.0.get(&' ').unwrap())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Glyph for BitmapGlyph {
|
|
||||||
fn draw(&self, canvas: &mut impl Canvas, x: usize, y: usize, color: &RGB) {
|
|
||||||
for row in 0..7 {
|
|
||||||
if self.0[row] & (1 << 4) > 0 {
|
|
||||||
canvas.set_pixel(x, y + row, color);
|
|
||||||
}
|
|
||||||
if self.0[row] & (1 << 3) > 0 {
|
|
||||||
canvas.set_pixel(x + 1, y + row, color);
|
|
||||||
}
|
|
||||||
if self.0[row] & (1 << 2) > 0 {
|
|
||||||
canvas.set_pixel(x + 2, y + row, color);
|
|
||||||
}
|
|
||||||
if self.0[row] & (1 << 1) > 0 {
|
|
||||||
canvas.set_pixel(x + 3, y + row, color);
|
|
||||||
}
|
|
||||||
if self.0[row] & 1 > 0 {
|
|
||||||
canvas.set_pixel(x + 4, y + row, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn extents(&self) -> (usize, usize) {
|
|
||||||
(5, 7)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
use crate::canvas::{Canvas, RGB};
|
|
||||||
|
|
||||||
mod bits_5_8;
|
|
||||||
pub use bits_5_8::BitmapFont;
|
|
||||||
|
|
||||||
mod seven_segment;
|
|
||||||
pub use seven_segment::SevenSegmentFont;
|
|
||||||
|
|
||||||
mod sixteen_segment;
|
|
||||||
pub use sixteen_segment::SixteenSegmentFont;
|
|
||||||
|
|
||||||
pub trait Font<A> {
|
|
||||||
fn glyph(&self, c: char) -> &A;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Glyph {
|
|
||||||
fn draw(&self, canvas: &mut impl Canvas, x: usize, y: usize, color: &RGB);
|
|
||||||
fn extents(&self) -> (usize, usize);
|
|
||||||
}
|
|
||||||
|
|
@ -1,211 +0,0 @@
|
|||||||
use alloc::collections::btree_map::BTreeMap;
|
|
||||||
use bitflags::bitflags;
|
|
||||||
|
|
||||||
use crate::canvas::{Canvas, RGB};
|
|
||||||
|
|
||||||
use super::{Font, Glyph};
|
|
||||||
|
|
||||||
// Seven Segments
|
|
||||||
//
|
|
||||||
// a a a
|
|
||||||
// f b
|
|
||||||
// f b
|
|
||||||
// f b
|
|
||||||
// g g g
|
|
||||||
// e c
|
|
||||||
// e c
|
|
||||||
// e c
|
|
||||||
// d d d
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
pub struct SevenSegmentGlyph: u8 {
|
|
||||||
const NONE = 0;
|
|
||||||
const A = 0x01;
|
|
||||||
const B = 0x01 << 1;
|
|
||||||
const C = 0x01 << 2;
|
|
||||||
const D = 0x01 << 3;
|
|
||||||
const E = 0x01 << 4;
|
|
||||||
const F = 0x01 << 5;
|
|
||||||
const G = 0x01 << 6;
|
|
||||||
const DOT = 0x01 << 7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SevenSegmentFont(BTreeMap<char, SevenSegmentGlyph>);
|
|
||||||
|
|
||||||
impl SevenSegmentFont {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
let mut font = BTreeMap::new();
|
|
||||||
font.insert(' ', SevenSegmentGlyph::NONE);
|
|
||||||
font.insert(
|
|
||||||
'0',
|
|
||||||
SevenSegmentGlyph::A
|
|
||||||
| SevenSegmentGlyph::B
|
|
||||||
| SevenSegmentGlyph::C
|
|
||||||
| SevenSegmentGlyph::D
|
|
||||||
| SevenSegmentGlyph::E
|
|
||||||
| SevenSegmentGlyph::F,
|
|
||||||
);
|
|
||||||
font.insert('1', SevenSegmentGlyph::B | SevenSegmentGlyph::C);
|
|
||||||
font.insert(
|
|
||||||
'2',
|
|
||||||
SevenSegmentGlyph::A
|
|
||||||
| SevenSegmentGlyph::B
|
|
||||||
| SevenSegmentGlyph::D
|
|
||||||
| SevenSegmentGlyph::E
|
|
||||||
| SevenSegmentGlyph::G,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'3',
|
|
||||||
SevenSegmentGlyph::A
|
|
||||||
| SevenSegmentGlyph::B
|
|
||||||
| SevenSegmentGlyph::C
|
|
||||||
| SevenSegmentGlyph::G
|
|
||||||
| SevenSegmentGlyph::D,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'4',
|
|
||||||
SevenSegmentGlyph::B
|
|
||||||
| SevenSegmentGlyph::C
|
|
||||||
| SevenSegmentGlyph::F
|
|
||||||
| SevenSegmentGlyph::G,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'5',
|
|
||||||
SevenSegmentGlyph::A
|
|
||||||
| SevenSegmentGlyph::C
|
|
||||||
| SevenSegmentGlyph::D
|
|
||||||
| SevenSegmentGlyph::F
|
|
||||||
| SevenSegmentGlyph::G,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'6',
|
|
||||||
SevenSegmentGlyph::A
|
|
||||||
| SevenSegmentGlyph::E
|
|
||||||
| SevenSegmentGlyph::F
|
|
||||||
| SevenSegmentGlyph::G
|
|
||||||
| SevenSegmentGlyph::C
|
|
||||||
| SevenSegmentGlyph::D,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'7',
|
|
||||||
SevenSegmentGlyph::A | SevenSegmentGlyph::B | SevenSegmentGlyph::C,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'8',
|
|
||||||
SevenSegmentGlyph::A
|
|
||||||
| SevenSegmentGlyph::B
|
|
||||||
| SevenSegmentGlyph::C
|
|
||||||
| SevenSegmentGlyph::D
|
|
||||||
| SevenSegmentGlyph::E
|
|
||||||
| SevenSegmentGlyph::F
|
|
||||||
| SevenSegmentGlyph::G,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'9',
|
|
||||||
SevenSegmentGlyph::A
|
|
||||||
| SevenSegmentGlyph::B
|
|
||||||
| SevenSegmentGlyph::C
|
|
||||||
| SevenSegmentGlyph::F
|
|
||||||
| SevenSegmentGlyph::G,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'A',
|
|
||||||
SevenSegmentGlyph::A
|
|
||||||
| SevenSegmentGlyph::B
|
|
||||||
| SevenSegmentGlyph::C
|
|
||||||
| SevenSegmentGlyph::E
|
|
||||||
| SevenSegmentGlyph::F
|
|
||||||
| SevenSegmentGlyph::G,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'B',
|
|
||||||
SevenSegmentGlyph::C
|
|
||||||
| SevenSegmentGlyph::D
|
|
||||||
| SevenSegmentGlyph::E
|
|
||||||
| SevenSegmentGlyph::F
|
|
||||||
| SevenSegmentGlyph::G,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'C',
|
|
||||||
SevenSegmentGlyph::A
|
|
||||||
| SevenSegmentGlyph::D
|
|
||||||
| SevenSegmentGlyph::E
|
|
||||||
| SevenSegmentGlyph::F,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'D',
|
|
||||||
SevenSegmentGlyph::B
|
|
||||||
| SevenSegmentGlyph::C
|
|
||||||
| SevenSegmentGlyph::D
|
|
||||||
| SevenSegmentGlyph::E
|
|
||||||
| SevenSegmentGlyph::G,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'E',
|
|
||||||
SevenSegmentGlyph::A
|
|
||||||
| SevenSegmentGlyph::D
|
|
||||||
| SevenSegmentGlyph::E
|
|
||||||
| SevenSegmentGlyph::F
|
|
||||||
| SevenSegmentGlyph::G,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'F',
|
|
||||||
SevenSegmentGlyph::A
|
|
||||||
| SevenSegmentGlyph::E
|
|
||||||
| SevenSegmentGlyph::F
|
|
||||||
| SevenSegmentGlyph::G,
|
|
||||||
);
|
|
||||||
Self(font)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Font<SevenSegmentGlyph> for SevenSegmentFont {
|
|
||||||
fn glyph(&self, c: char) -> &SevenSegmentGlyph {
|
|
||||||
self.0.get(&c).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Glyph for SevenSegmentGlyph {
|
|
||||||
fn draw(&self, canvas: &mut impl Canvas, x: usize, y: usize, color: &RGB) {
|
|
||||||
if self.contains(SevenSegmentGlyph::A) {
|
|
||||||
canvas.set_pixel(x + 1, y, color);
|
|
||||||
canvas.set_pixel(x + 2, y, color);
|
|
||||||
canvas.set_pixel(x + 3, y, color);
|
|
||||||
}
|
|
||||||
if self.contains(SevenSegmentGlyph::B) {
|
|
||||||
canvas.set_pixel(x + 4, y + 1, color);
|
|
||||||
canvas.set_pixel(x + 4, y + 2, color);
|
|
||||||
canvas.set_pixel(x + 4, y + 3, color);
|
|
||||||
}
|
|
||||||
if self.contains(SevenSegmentGlyph::C) {
|
|
||||||
canvas.set_pixel(x + 4, y + 5, color);
|
|
||||||
canvas.set_pixel(x + 4, y + 6, color);
|
|
||||||
canvas.set_pixel(x + 4, y + 7, color);
|
|
||||||
}
|
|
||||||
if self.contains(SevenSegmentGlyph::D) {
|
|
||||||
canvas.set_pixel(x + 1, y + 8, color);
|
|
||||||
canvas.set_pixel(x + 2, y + 8, color);
|
|
||||||
canvas.set_pixel(x + 3, y + 8, color);
|
|
||||||
}
|
|
||||||
if self.contains(SevenSegmentGlyph::E) {
|
|
||||||
canvas.set_pixel(x, y + 5, color);
|
|
||||||
canvas.set_pixel(x, y + 6, color);
|
|
||||||
canvas.set_pixel(x, y + 7, color);
|
|
||||||
}
|
|
||||||
if self.contains(SevenSegmentGlyph::F) {
|
|
||||||
canvas.set_pixel(x, y + 1, color);
|
|
||||||
canvas.set_pixel(x, y + 2, color);
|
|
||||||
canvas.set_pixel(x, y + 3, color);
|
|
||||||
}
|
|
||||||
if self.contains(SevenSegmentGlyph::G) {
|
|
||||||
canvas.set_pixel(x + 1, y + 4, color);
|
|
||||||
canvas.set_pixel(x + 2, y + 4, color);
|
|
||||||
canvas.set_pixel(x + 3, y + 4, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn extents(&self) -> (usize, usize) {
|
|
||||||
(5, 8)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,689 +0,0 @@
|
|||||||
use alloc::collections::btree_map::BTreeMap;
|
|
||||||
use bitflags::bitflags;
|
|
||||||
|
|
||||||
use crate::canvas::{Canvas, RGB};
|
|
||||||
|
|
||||||
use super::{Font, Glyph};
|
|
||||||
|
|
||||||
// Sixteen Segments
|
|
||||||
// https://www.partsnotincluded.com/segmented-led-display-ascii-library/
|
|
||||||
//
|
|
||||||
// a1 a2
|
|
||||||
// f h i jb
|
|
||||||
// f i j b
|
|
||||||
// f hij b
|
|
||||||
// g1 g2
|
|
||||||
// e klm c
|
|
||||||
// e k l m c
|
|
||||||
// ek l mc
|
|
||||||
// d1 d2
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
pub struct SixteenSegmentGlyph: u32 {
|
|
||||||
const NONE = 0;
|
|
||||||
const A1 = 0x0001;
|
|
||||||
const A2 = 0x0001 << 1;
|
|
||||||
const B = 0x0001 << 2;
|
|
||||||
const C = 0x0001 << 3;
|
|
||||||
const D1 = 0x0001 << 4;
|
|
||||||
const D2 = 0x0001 << 5;
|
|
||||||
const E = 0x0001 << 6;
|
|
||||||
const F = 0x0001 << 7;
|
|
||||||
const G1 = 0x0001 << 8;
|
|
||||||
const G2 = 0x0001 << 9;
|
|
||||||
const H = 0x0001 << 10;
|
|
||||||
const I = 0x0001 << 11;
|
|
||||||
const J = 0x0001 << 12;
|
|
||||||
const K = 0x0001 << 13;
|
|
||||||
const L = 0x0001 << 14;
|
|
||||||
const M = 0x0001 << 15;
|
|
||||||
const DOT = 0x0001 << 16;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SixteenSegmentFont(BTreeMap<char, SixteenSegmentGlyph>);
|
|
||||||
|
|
||||||
impl SixteenSegmentFont {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
let mut font = BTreeMap::new();
|
|
||||||
font.insert(' ', SixteenSegmentGlyph::NONE);
|
|
||||||
font.insert(
|
|
||||||
'!',
|
|
||||||
SixteenSegmentGlyph::B | SixteenSegmentGlyph::C | SixteenSegmentGlyph::DOT,
|
|
||||||
);
|
|
||||||
font.insert('"', SixteenSegmentGlyph::B | SixteenSegmentGlyph::I);
|
|
||||||
font.insert(
|
|
||||||
'0',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::J
|
|
||||||
| SixteenSegmentGlyph::K,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'1',
|
|
||||||
SixteenSegmentGlyph::B | SixteenSegmentGlyph::C | SixteenSegmentGlyph::J,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'2',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::G2,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'3',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::G2,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'4',
|
|
||||||
SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::G2,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'5',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::M,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'6',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::G2,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'7',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::C,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'8',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::G2,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'9',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::G2,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'A',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::G2,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'B',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::G2
|
|
||||||
| SixteenSegmentGlyph::I
|
|
||||||
| SixteenSegmentGlyph::L,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'C',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'D',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::I
|
|
||||||
| SixteenSegmentGlyph::L,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'E',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G1,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'F',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G1,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'G',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G2,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'H',
|
|
||||||
SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::G2,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'I',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::I
|
|
||||||
| SixteenSegmentGlyph::L,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'J',
|
|
||||||
SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::E,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'K',
|
|
||||||
SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::J
|
|
||||||
| SixteenSegmentGlyph::M,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'L',
|
|
||||||
SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'M',
|
|
||||||
SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::H
|
|
||||||
| SixteenSegmentGlyph::J,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'N',
|
|
||||||
SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::H
|
|
||||||
| SixteenSegmentGlyph::M,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'O',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'P',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::G2,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'Q',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::M,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'R',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::G2
|
|
||||||
| SixteenSegmentGlyph::M,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'S',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::G2,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'T',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::I
|
|
||||||
| SixteenSegmentGlyph::L,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'U',
|
|
||||||
SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'V',
|
|
||||||
SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::J
|
|
||||||
| SixteenSegmentGlyph::K,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'W',
|
|
||||||
SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::K
|
|
||||||
| SixteenSegmentGlyph::M,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'X',
|
|
||||||
SixteenSegmentGlyph::H
|
|
||||||
| SixteenSegmentGlyph::J
|
|
||||||
| SixteenSegmentGlyph::K
|
|
||||||
| SixteenSegmentGlyph::M,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'Y',
|
|
||||||
SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::G2,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'Z',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::J
|
|
||||||
| SixteenSegmentGlyph::K,
|
|
||||||
);
|
|
||||||
|
|
||||||
font.insert(
|
|
||||||
'a',
|
|
||||||
SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::L,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'b',
|
|
||||||
SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::L,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'c',
|
|
||||||
SixteenSegmentGlyph::D1 | SixteenSegmentGlyph::E | SixteenSegmentGlyph::G1,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'd',
|
|
||||||
SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::G2
|
|
||||||
| SixteenSegmentGlyph::L,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'e',
|
|
||||||
SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::K,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'f',
|
|
||||||
SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::G2
|
|
||||||
| SixteenSegmentGlyph::I
|
|
||||||
| SixteenSegmentGlyph::L,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'g',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::I
|
|
||||||
| SixteenSegmentGlyph::L,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'h',
|
|
||||||
SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::L,
|
|
||||||
);
|
|
||||||
font.insert('i', SixteenSegmentGlyph::L);
|
|
||||||
font.insert(
|
|
||||||
'j',
|
|
||||||
SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::I
|
|
||||||
| SixteenSegmentGlyph::L,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'k',
|
|
||||||
SixteenSegmentGlyph::I
|
|
||||||
| SixteenSegmentGlyph::J
|
|
||||||
| SixteenSegmentGlyph::L
|
|
||||||
| SixteenSegmentGlyph::M,
|
|
||||||
);
|
|
||||||
font.insert('l', SixteenSegmentGlyph::E | SixteenSegmentGlyph::F);
|
|
||||||
font.insert(
|
|
||||||
'm',
|
|
||||||
SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::L
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::G2,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'n',
|
|
||||||
SixteenSegmentGlyph::E | SixteenSegmentGlyph::L | SixteenSegmentGlyph::G1,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'o',
|
|
||||||
SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::L,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'p',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::I,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'q',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::I
|
|
||||||
| SixteenSegmentGlyph::L,
|
|
||||||
);
|
|
||||||
font.insert('r', SixteenSegmentGlyph::E | SixteenSegmentGlyph::G1);
|
|
||||||
font.insert(
|
|
||||||
's',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G1
|
|
||||||
| SixteenSegmentGlyph::L,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
't',
|
|
||||||
SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G1,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'u',
|
|
||||||
SixteenSegmentGlyph::D1 | SixteenSegmentGlyph::E | SixteenSegmentGlyph::L,
|
|
||||||
);
|
|
||||||
font.insert('v', SixteenSegmentGlyph::E | SixteenSegmentGlyph::K);
|
|
||||||
font.insert(
|
|
||||||
'w',
|
|
||||||
SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::K
|
|
||||||
| SixteenSegmentGlyph::M,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'x',
|
|
||||||
SixteenSegmentGlyph::H
|
|
||||||
| SixteenSegmentGlyph::J
|
|
||||||
| SixteenSegmentGlyph::K
|
|
||||||
| SixteenSegmentGlyph::M,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'y',
|
|
||||||
SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::C
|
|
||||||
| SixteenSegmentGlyph::I
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::G2,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'z',
|
|
||||||
SixteenSegmentGlyph::D1 | SixteenSegmentGlyph::G1 | SixteenSegmentGlyph::K,
|
|
||||||
);
|
|
||||||
font.insert(
|
|
||||||
'@',
|
|
||||||
SixteenSegmentGlyph::A1
|
|
||||||
| SixteenSegmentGlyph::A2
|
|
||||||
| SixteenSegmentGlyph::B
|
|
||||||
| SixteenSegmentGlyph::D1
|
|
||||||
| SixteenSegmentGlyph::D2
|
|
||||||
| SixteenSegmentGlyph::E
|
|
||||||
| SixteenSegmentGlyph::F
|
|
||||||
| SixteenSegmentGlyph::G2,
|
|
||||||
);
|
|
||||||
Self(font)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Font<SixteenSegmentGlyph> for SixteenSegmentFont {
|
|
||||||
fn glyph(&self, c: char) -> &SixteenSegmentGlyph {
|
|
||||||
self.0.get(&c).unwrap_or(&SixteenSegmentGlyph::NONE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Glyph for SixteenSegmentGlyph {
|
|
||||||
fn draw(&self, canvas: &mut impl Canvas, x: usize, y: usize, color: &RGB) {
|
|
||||||
if self.contains(SixteenSegmentGlyph::A1) {
|
|
||||||
canvas.set_pixel(x + 1, y, color);
|
|
||||||
canvas.set_pixel(x + 2, y, color);
|
|
||||||
canvas.set_pixel(x + 3, y, color);
|
|
||||||
}
|
|
||||||
if self.contains(SixteenSegmentGlyph::A2) {
|
|
||||||
canvas.set_pixel(x + 5, y, color);
|
|
||||||
canvas.set_pixel(x + 6, y, color);
|
|
||||||
canvas.set_pixel(x + 7, y, color);
|
|
||||||
}
|
|
||||||
if self.contains(SixteenSegmentGlyph::B) {
|
|
||||||
canvas.set_pixel(x + 8, y + 1, color);
|
|
||||||
canvas.set_pixel(x + 8, y + 2, color);
|
|
||||||
canvas.set_pixel(x + 8, y + 3, color);
|
|
||||||
canvas.set_pixel(x + 8, y + 4, color);
|
|
||||||
canvas.set_pixel(x + 8, y + 5, color);
|
|
||||||
}
|
|
||||||
if self.contains(SixteenSegmentGlyph::C) {
|
|
||||||
canvas.set_pixel(x + 8, y + 7, color);
|
|
||||||
canvas.set_pixel(x + 8, y + 8, color);
|
|
||||||
canvas.set_pixel(x + 8, y + 9, color);
|
|
||||||
canvas.set_pixel(x + 8, y + 10, color);
|
|
||||||
canvas.set_pixel(x + 8, y + 11, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.contains(SixteenSegmentGlyph::D1) {
|
|
||||||
canvas.set_pixel(x + 1, y + 12, color);
|
|
||||||
canvas.set_pixel(x + 2, y + 12, color);
|
|
||||||
canvas.set_pixel(x + 3, y + 12, color);
|
|
||||||
}
|
|
||||||
if self.contains(SixteenSegmentGlyph::D2) {
|
|
||||||
canvas.set_pixel(x + 5, y + 12, color);
|
|
||||||
canvas.set_pixel(x + 6, y + 12, color);
|
|
||||||
canvas.set_pixel(x + 7, y + 12, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.contains(SixteenSegmentGlyph::E) {
|
|
||||||
canvas.set_pixel(x, y + 7, color);
|
|
||||||
canvas.set_pixel(x, y + 8, color);
|
|
||||||
canvas.set_pixel(x, y + 9, color);
|
|
||||||
canvas.set_pixel(x, y + 10, color);
|
|
||||||
canvas.set_pixel(x, y + 11, color);
|
|
||||||
}
|
|
||||||
if self.contains(SixteenSegmentGlyph::F) {
|
|
||||||
canvas.set_pixel(x, y + 1, color);
|
|
||||||
canvas.set_pixel(x, y + 2, color);
|
|
||||||
canvas.set_pixel(x, y + 3, color);
|
|
||||||
canvas.set_pixel(x, y + 4, color);
|
|
||||||
canvas.set_pixel(x, y + 5, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.contains(SixteenSegmentGlyph::G1) {
|
|
||||||
canvas.set_pixel(x + 1, y + 6, color);
|
|
||||||
canvas.set_pixel(x + 2, y + 6, color);
|
|
||||||
canvas.set_pixel(x + 3, y + 6, color);
|
|
||||||
}
|
|
||||||
if self.contains(SixteenSegmentGlyph::G2) {
|
|
||||||
canvas.set_pixel(x + 5, y + 6, color);
|
|
||||||
canvas.set_pixel(x + 6, y + 6, color);
|
|
||||||
canvas.set_pixel(x + 7, y + 6, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.contains(SixteenSegmentGlyph::H) {
|
|
||||||
canvas.set_pixel(x + 1, y + 1, color);
|
|
||||||
canvas.set_pixel(x + 1, y + 2, color);
|
|
||||||
canvas.set_pixel(x + 2, y + 3, color);
|
|
||||||
canvas.set_pixel(x + 3, y + 4, color);
|
|
||||||
canvas.set_pixel(x + 3, y + 5, color);
|
|
||||||
}
|
|
||||||
if self.contains(SixteenSegmentGlyph::I) {
|
|
||||||
canvas.set_pixel(x + 4, y + 1, color);
|
|
||||||
canvas.set_pixel(x + 4, y + 2, color);
|
|
||||||
canvas.set_pixel(x + 4, y + 3, color);
|
|
||||||
canvas.set_pixel(x + 4, y + 4, color);
|
|
||||||
canvas.set_pixel(x + 4, y + 5, color);
|
|
||||||
}
|
|
||||||
if self.contains(SixteenSegmentGlyph::J) {
|
|
||||||
canvas.set_pixel(x + 7, y + 1, color);
|
|
||||||
canvas.set_pixel(x + 7, y + 2, color);
|
|
||||||
canvas.set_pixel(x + 6, y + 3, color);
|
|
||||||
canvas.set_pixel(x + 5, y + 4, color);
|
|
||||||
canvas.set_pixel(x + 5, y + 5, color);
|
|
||||||
}
|
|
||||||
if self.contains(SixteenSegmentGlyph::K) {
|
|
||||||
canvas.set_pixel(x + 3, y + 7, color);
|
|
||||||
canvas.set_pixel(x + 3, y + 8, color);
|
|
||||||
canvas.set_pixel(x + 2, y + 9, color);
|
|
||||||
canvas.set_pixel(x + 1, y + 10, color);
|
|
||||||
canvas.set_pixel(x + 1, y + 11, color);
|
|
||||||
}
|
|
||||||
if self.contains(SixteenSegmentGlyph::L) {
|
|
||||||
canvas.set_pixel(x + 4, y + 7, color);
|
|
||||||
canvas.set_pixel(x + 4, y + 8, color);
|
|
||||||
canvas.set_pixel(x + 4, y + 9, color);
|
|
||||||
canvas.set_pixel(x + 4, y + 10, color);
|
|
||||||
canvas.set_pixel(x + 4, y + 11, color);
|
|
||||||
}
|
|
||||||
if self.contains(SixteenSegmentGlyph::M) {
|
|
||||||
canvas.set_pixel(x + 5, y + 7, color);
|
|
||||||
canvas.set_pixel(x + 5, y + 8, color);
|
|
||||||
canvas.set_pixel(x + 6, y + 9, color);
|
|
||||||
canvas.set_pixel(x + 7, y + 10, color);
|
|
||||||
canvas.set_pixel(x + 7, y + 11, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn extents(&self) -> (usize, usize) {
|
|
||||||
(9, 13)
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user