feat(egui): begin development of `egui-actions` crate

The purpose of this new crate is to provide a system for managing
actions that can be bound to a key and to derive `egui` menus to invoke
them.

I haven't moved all relevant code from `topola-egui` (in particular,
`Switch` and `Trigger` structs) to this crate yet.
This commit is contained in:
Mikolaj Wielgus 2025-01-06 18:28:56 +01:00
parent 9bb0d34bc8
commit 658e556a4a
7 changed files with 81 additions and 16 deletions

View File

@ -0,0 +1,17 @@
# SPDX-FileCopyrightText: 2024 Topola contributors
#
# SPDX-License-Identifier: MIT
[package]
name = "egui-actions"
version = "0.1.0"
edition = "2021"
[lib]
proc-macro = true
[dependencies]
egui = "0.29"
proc-macro2 = "1.0"
quote = "1.0"
syn = "2.0"

View File

@ -0,0 +1,47 @@
// SPDX-FileCopyrightText: 2025 Topola contributors
//
// SPDX-License-Identifier: MIT
use proc_macro2::TokenStream;
use quote::quote;
use syn::{Data, DeriveInput, Field, Fields};
pub(super) fn impl_derive_actions(input: &DeriveInput) -> TokenStream {
let name = &input.ident;
let new_body = impl_new_body(&input.data);
quote! {
impl #name {
pub fn new(tr: &Translator) -> Self {
#new_body
}
}
}
}
pub(super) fn impl_new_body(data: &Data) -> TokenStream {
match data {
Data::Struct(data) => match &data.fields {
Fields::Named(fields) => {
let fields = fields.named.iter().map(impl_new_field);
quote! {
Self {
#(#fields)*
}
}
}
_ => unimplemented!(),
},
_ => unimplemented!(),
}
}
pub(super) fn impl_new_field(field: &Field) -> TokenStream {
let name = &field.ident;
let typ = &field.ty;
quote! {
#name: #typ::new(tr),
}
}

View File

@ -0,0 +1,14 @@
// SPDX-FileCopyrightText: 2024 Topola contributors
//
// SPDX-License-Identifier: MIT
use proc_macro::TokenStream;
use syn::DeriveInput;
mod implementation;
#[proc_macro_derive(Actions)]
pub fn derive_actions(input: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(input as DeriveInput);
implementation::impl_derive_actions(&input).into()
}

View File

@ -17,6 +17,7 @@ xdg-portal = ["rfd/async-std", "rfd/xdg-portal"]
[dependencies] [dependencies]
derive-getters.workspace = true derive-getters.workspace = true
egui = "0.29" egui = "0.29"
egui-actions.path = "../egui-actions"
fluent-templates = "0.11" fluent-templates = "0.11"
geo.workspace = true geo.workspace = true
icu_experimental = "0.2" icu_experimental = "0.2"

View File

@ -32,7 +32,6 @@ impl Action {
) )
} }
#[inline]
pub fn into_trigger(self) -> Trigger { pub fn into_trigger(self) -> Trigger {
Trigger { Trigger {
action: self, action: self,
@ -40,7 +39,6 @@ impl Action {
} }
} }
#[inline(always)]
pub fn into_switch(self) -> Switch { pub fn into_switch(self) -> Switch {
Switch { action: self } Switch { action: self }
} }

View File

@ -8,6 +8,7 @@ use crate::{
}; };
use egui::{Context, Ui}; use egui::{Context, Ui};
use egui_actions::Actions;
use topola::autorouter::AutorouterOptions; use topola::autorouter::AutorouterOptions;
pub struct FileActions { pub struct FileActions {
@ -299,6 +300,7 @@ impl HelpActions {
} }
} }
#[derive(Actions)]
pub struct Actions { pub struct Actions {
pub file: FileActions, pub file: FileActions,
pub edit: EditActions, pub edit: EditActions,
@ -307,16 +309,3 @@ pub struct Actions {
pub inspect: InspectActions, pub inspect: InspectActions,
pub help: HelpActions, pub help: HelpActions,
} }
impl Actions {
pub fn new(tr: &Translator) -> Self {
Self {
file: FileActions::new(tr),
edit: EditActions::new(tr),
place: PlaceActions::new(tr),
route: RouteActions::new(tr),
inspect: InspectActions::new(tr),
help: HelpActions::new(tr),
}
}
}

View File

@ -15,7 +15,6 @@ use topola::{
}; };
use crate::{ use crate::{
action::{Action, Switch, Trigger},
actions::Actions, actions::Actions,
app::{execute, handle_file}, app::{execute, handle_file},
translator::Translator, translator::Translator,