Add build action #2
2
.cargo/config.toml
Normal file
2
.cargo/config.toml
Normal file
@ -0,0 +1,2 @@
|
||||
[profile.dev.package."*"]
|
||||
opt-level = 2
|
25
.gitea/workflows/build.yaml
Normal file
25
.gitea/workflows/build.yaml
Normal file
@ -0,0 +1,25 @@
|
||||
name: Build
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
Build:
|
||||
env:
|
||||
RUNNER_TOOL_CACHE: /toolcache
|
||||
container: rust:alpine
|
||||
steps:
|
||||
- name: Install node
|
||||
run: apk add nodejs gcc libc-dev pkgconf libx11-dev alsa-lib-dev eudev-dev tar
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- name: Restore cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
target/
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
- name: Build
|
||||
run: cargo build --release
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
/target
|
||||
Cargo.lock
|
||||
|
@ -8,4 +8,4 @@ version = "0.15"
|
||||
default-features = false
|
||||
|
||||
[dependencies.bevy_terminal_display]
|
||||
git = "https://git.soaos.dev/bevy_terminal_display"
|
||||
git = "https://git.soaos.dev/soaos/bevy_terminal_display"
|
||||
|
130
src/lib.rs
130
src/lib.rs
@ -1,3 +1,129 @@
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
use std::sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc,
|
||||
};
|
||||
|
||||
use bevy::prelude::*;
|
||||
use bevy_terminal_display::{
|
||||
crossterm::event::{Event, KeyCode, KeyEventKind},
|
||||
input::events::TerminalInputEvent,
|
||||
ratatui::{
|
||||
layout::Rect, style::{Color, Modifier, Style}, widgets::{Block, Borders, Clear, HighlightSpacing, List, ListItem, ListState}
|
||||
},
|
||||
widgets::TerminalWidget,
|
||||
};
|
||||
|
||||
pub struct MenuWidget<E: bevy::prelude::Event> {
|
||||
pub items: Vec<MenuOption<E>>,
|
||||
pub state: ListState,
|
||||
pub enabled_color: Color,
|
||||
pub disabled_color: Color,
|
||||
pub selected_style: Style,
|
||||
pub area_function: Option<Box<dyn Fn(Rect) -> Rect + Send + Sync>>,
|
||||
}
|
||||
|
||||
impl<E: bevy::prelude::Event> Default for MenuWidget<E> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
items: vec![],
|
||||
state: ListState::default().with_selected(Some(0)),
|
||||
enabled_color: Color::White,
|
||||
disabled_color: Color::Gray,
|
||||
selected_style: Style::new()
|
||||
.add_modifier(Modifier::UNDERLINED)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
area_function: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MenuOption<E: bevy::prelude::Event> {
|
||||
pub enabled: Arc<AtomicBool>,
|
||||
pub label: String,
|
||||
pub event: E,
|
||||
}
|
||||
|
||||
impl<E: bevy::prelude::Event + Clone> TerminalWidget for MenuWidget<E> {
|
||||
fn render(
|
||||
&mut self,
|
||||
frame: &mut bevy_terminal_display::ratatui::Frame,
|
||||
rect: bevy_terminal_display::ratatui::prelude::Rect,
|
||||
) {
|
||||
let block = Block::new().borders(Borders::all());
|
||||
let items: Vec<ListItem> = self
|
||||
.items
|
||||
.iter()
|
||||
.map(|item| {
|
||||
ListItem::from(item).style(Style::new().fg(
|
||||
if item.enabled.load(Ordering::Relaxed) {
|
||||
self.enabled_color
|
||||
} else {
|
||||
self.disabled_color
|
||||
},
|
||||
))
|
||||
})
|
||||
.collect();
|
||||
|
||||
let list = List::new(items)
|
||||
.block(block)
|
||||
.highlight_style(self.selected_style)
|
||||
.highlight_symbol(">")
|
||||
.highlight_spacing(HighlightSpacing::Always);
|
||||
|
||||
let area = if let Some(area) = &self.area_function {
|
||||
area(rect)
|
||||
} else {
|
||||
rect
|
||||
};
|
||||
frame.render_widget(Clear, area);
|
||||
frame.render_stateful_widget(list, area, &mut self.state);
|
||||
}
|
||||
|
||||
fn handle_events(
|
||||
&mut self,
|
||||
event: &bevy_terminal_display::input::events::TerminalInputEvent,
|
||||
commands: &mut Commands,
|
||||
) {
|
||||
if let TerminalInputEvent(Event::Key(key_event)) = event {
|
||||
if key_event.kind == KeyEventKind::Press {
|
||||
match key_event.code {
|
||||
KeyCode::Enter => {
|
||||
if let Some(selected) = self.state.selected() {
|
||||
if let Some(item) = self.items.get(selected) {
|
||||
if item.enabled.load(Ordering::Relaxed) {
|
||||
commands.send_event(item.event.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
KeyCode::Up => self.state.select_previous(),
|
||||
KeyCode::Down => self.state.select_next(),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: bevy::prelude::Event> FromIterator<(&'static str, E)> for MenuWidget<E> {
|
||||
fn from_iter<I: IntoIterator<Item = (&'static str, E)>>(iter: I) -> Self {
|
||||
let items = iter
|
||||
.into_iter()
|
||||
.map(|(label, event)| MenuOption {
|
||||
enabled: Arc::new(true.into()),
|
||||
label: label.into(),
|
||||
event,
|
||||
})
|
||||
.collect();
|
||||
Self {
|
||||
items,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: bevy::prelude::Event> From<&MenuOption<E>> for ListItem<'_> {
|
||||
fn from(value: &MenuOption<E>) -> Self {
|
||||
ListItem::new(value.label.clone())
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user