Fix and display metronome
This commit is contained in:
@@ -28,7 +28,7 @@ async fn main() -> Result<()> {
|
||||
|
||||
// Logger
|
||||
simple_logger::SimpleLogger::new()
|
||||
.with_level(log::LevelFilter::Error)
|
||||
.with_level(log::LevelFilter::Info)
|
||||
.with_module_level("gui::osc_client", log::LevelFilter::Off)
|
||||
.init()
|
||||
.expect("Could not initialize logger");
|
||||
|
||||
@@ -11,23 +11,24 @@ impl App {
|
||||
impl eframe::App for App {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
let state = self.state_receiver.borrow_and_update().clone();
|
||||
|
||||
ctx.style_mut(|style| {
|
||||
style.visuals.panel_fill = egui::Color32::from_rgb(17, 17, 17);
|
||||
style.visuals.window_fill = egui::Color32::from_rgb(17, 17, 17);
|
||||
style.spacing.item_spacing = egui::vec2(0.0, 0.0);
|
||||
});
|
||||
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
ui.columns(state.columns, |ui| {
|
||||
for (i, column) in state.cells.iter().enumerate() {
|
||||
let selected_row = if i == state.selected_column {
|
||||
Some(state.selected_row)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
ui[i].add(super::Column::new(column, selected_row));
|
||||
}
|
||||
ui.vertical(|ui| {
|
||||
ui.add(super::Metronome::new(state.metronome_position));
|
||||
ui.add(super::Matrix::new(
|
||||
&state.cells,
|
||||
state.selected_column,
|
||||
state.selected_row,
|
||||
));
|
||||
});
|
||||
});
|
||||
|
||||
ctx.request_repaint();
|
||||
}
|
||||
}
|
||||
|
||||
35
gui/src/ui/matrix.rs
Normal file
35
gui/src/ui/matrix.rs
Normal file
@@ -0,0 +1,35 @@
|
||||
pub struct Matrix<'a> {
|
||||
cells: &'a Vec<Vec<osc::Track>>,
|
||||
selected_column: usize,
|
||||
selected_row: usize,
|
||||
}
|
||||
|
||||
impl<'a> Matrix<'a> {
|
||||
pub fn new(
|
||||
cells: &'a Vec<Vec<osc::Track>>,
|
||||
selected_column: usize,
|
||||
selected_row: usize,
|
||||
) -> Self {
|
||||
Self {
|
||||
cells,
|
||||
selected_column,
|
||||
selected_row,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> egui::Widget for Matrix<'a> {
|
||||
fn ui(self, ui: &mut egui::Ui) -> egui::Response {
|
||||
ui.columns(self.cells.len(), |ui| {
|
||||
for (i, column) in self.cells.iter().enumerate() {
|
||||
let selected_row = if i == self.selected_column {
|
||||
Some(self.selected_row)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
ui[i].add(super::Column::new(column, selected_row));
|
||||
}
|
||||
});
|
||||
ui.response()
|
||||
}
|
||||
}
|
||||
65
gui/src/ui/metronome.rs
Normal file
65
gui/src/ui/metronome.rs
Normal file
@@ -0,0 +1,65 @@
|
||||
pub struct Metronome {
|
||||
position: f32, // 0.0 - 1.0
|
||||
}
|
||||
|
||||
impl Metronome {
|
||||
pub fn new(position: f32) -> Self {
|
||||
Self {
|
||||
position: position.clamp(0.0, 1.0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl egui::Widget for Metronome {
|
||||
fn ui(self, ui: &mut egui::Ui) -> egui::Response {
|
||||
let sf = ui.available_width() / 100.0;
|
||||
|
||||
// Simple scaling values
|
||||
let rail_height = sf * 1.0;
|
||||
let circle_radius = sf * 2.0;
|
||||
let h_padding = sf * 5.0;
|
||||
let v_padding = sf * 3.0;
|
||||
|
||||
// Colors
|
||||
let rail_color = egui::Color32::from_rgb(51, 51, 51); // #333333
|
||||
let circle_color = egui::Color32::from_rgb(0, 255, 136); // #00ff88
|
||||
|
||||
// Calculate widget size
|
||||
let width = ui.available_width();
|
||||
let height = rail_height + 2.0 * v_padding;
|
||||
let size = egui::vec2(width, height);
|
||||
|
||||
// Allocate the space we need
|
||||
let (rect, response) = ui.allocate_exact_size(size, egui::Sense::hover());
|
||||
|
||||
// Calculate rail position (centered)
|
||||
let rail_left = rect.min.x + h_padding;
|
||||
let rail_right = rect.max.x - h_padding;
|
||||
let rail_width = rail_right - rail_left;
|
||||
let rail_center_y = rect.center().y;
|
||||
let rail_top = rail_center_y - rail_height / 2.0;
|
||||
let rail_bottom = rail_center_y + rail_height / 2.0;
|
||||
|
||||
let rail_rect = egui::Rect::from_min_max(
|
||||
egui::pos2(rail_left, rail_top),
|
||||
egui::pos2(rail_right, rail_bottom),
|
||||
);
|
||||
|
||||
// Calculate circle position
|
||||
let circle_x = rail_left + self.position * rail_width;
|
||||
let circle_center = egui::pos2(circle_x, rail_center_y);
|
||||
|
||||
// Draw rail
|
||||
ui.painter().rect_filled(
|
||||
rail_rect,
|
||||
egui::Rounding::same(rail_height / 2.0),
|
||||
rail_color,
|
||||
);
|
||||
|
||||
// Draw circle
|
||||
ui.painter()
|
||||
.circle_filled(circle_center, circle_radius, circle_color);
|
||||
|
||||
response
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
mod app;
|
||||
mod column;
|
||||
mod matrix;
|
||||
mod metronome;
|
||||
mod track;
|
||||
mod ui_rows_ext;
|
||||
|
||||
pub use app::App;
|
||||
use column::Column;
|
||||
use matrix::Matrix;
|
||||
use metronome::Metronome;
|
||||
use track::Track;
|
||||
|
||||
@@ -66,25 +66,22 @@ impl<'a> egui::Widget for Track<'a> {
|
||||
let volume_bar_height = 2.0 * sf;
|
||||
let margin = 4.0 * sf;
|
||||
let frame_rect = frame_response.response.rect;
|
||||
|
||||
|
||||
// Calculate volume bar position (bottom of the frame, inside the margins)
|
||||
let inner_rect = frame_rect.shrink(5.0 * sf); // Match the outer_margin
|
||||
let volume_bar_rect = egui::Rect::from_min_max(
|
||||
egui::pos2(
|
||||
inner_rect.min.x + margin,
|
||||
inner_rect.max.y - volume_bar_height - margin
|
||||
inner_rect.max.y - volume_bar_height - margin,
|
||||
),
|
||||
egui::pos2(
|
||||
inner_rect.max.x - margin,
|
||||
inner_rect.max.y - margin
|
||||
)
|
||||
egui::pos2(inner_rect.max.x - margin, inner_rect.max.y - margin),
|
||||
);
|
||||
|
||||
// Draw volume bar background
|
||||
ui.painter().rect_filled(
|
||||
volume_bar_rect,
|
||||
egui::Rounding::same(1.0 * sf),
|
||||
egui::Color32::from_rgb(51, 51, 51) // #333333
|
||||
egui::Color32::from_rgb(51, 51, 51), // #333333
|
||||
);
|
||||
|
||||
// Draw volume bar fill (only if volume > 0)
|
||||
@@ -93,17 +90,17 @@ impl<'a> egui::Widget for Track<'a> {
|
||||
if fill_width > 0.0 {
|
||||
let fill_rect = egui::Rect::from_min_size(
|
||||
volume_bar_rect.min,
|
||||
egui::vec2(fill_width, volume_bar_rect.height())
|
||||
egui::vec2(fill_width, volume_bar_rect.height()),
|
||||
);
|
||||
|
||||
|
||||
ui.painter().rect_filled(
|
||||
fill_rect,
|
||||
egui::Rounding::same(1.0 * sf),
|
||||
egui::Color32::from_rgb(0, 255, 136) // #00ff88
|
||||
egui::Color32::from_rgb(0, 255, 136), // #00ff88
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
frame_response.response
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user