Skip to content

Commit

Permalink
Merge pull request #31 from robgonnella/ui-redesign
Browse files Browse the repository at this point in the history
ui redesign
  • Loading branch information
robgonnella authored Feb 24, 2025
2 parents 73a064b + 8e8323d commit e8190eb
Show file tree
Hide file tree
Showing 12 changed files with 352 additions and 226 deletions.
29 changes: 19 additions & 10 deletions r-lanui/src/ui/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use log::*;
use ratatui::{
backend::Backend,
crossterm::{
event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode},
event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyModifiers},
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
},
Expand All @@ -14,20 +14,27 @@ use ratatui::{
use std::{io, sync::Arc};

use super::{
store::dispatcher::Dispatcher,
store::{dispatcher::Dispatcher, state::State},
views::{main::MainView, View},
};

struct App {
dispatcher: Arc<Dispatcher>,
main_view: Box<dyn View>,
}

impl App {
fn new(dispatcher: Arc<Dispatcher>) -> Self {
let dispatcher_clone = Arc::clone(&dispatcher);
Self {
main_view: Box::new(MainView::new(dispatcher)),
dispatcher,
main_view: Box::new(MainView::new(dispatcher_clone)),
}
}

pub fn get_state(&self) -> State {
self.dispatcher.get_state()
}
}

pub fn launch(dispatcher: Arc<Dispatcher>) -> Result<(), Report> {
Expand Down Expand Up @@ -68,19 +75,21 @@ fn run_app<B: Backend>(terminal: &mut Terminal<B>, app: &mut App) -> io::Result<
if let Ok(has_event) = event::poll(time::Duration::from_millis(60)) {
if has_event {
let evt = event::read()?;
let handled = app.main_view.process_event(&evt);
let state = app.get_state();
let handled = app.main_view.process_event(&evt, &state);

if !handled {
match evt {
Event::Key(key) => match key.code {
KeyCode::Char('q') | KeyCode::Esc => return Ok(()),
KeyCode::Char('q') => return Ok(()),
KeyCode::Char('c') => {
if key.modifiers == KeyModifiers::CONTROL {
return Ok(());
}
}
_ => {}
},
Event::FocusGained => {}
Event::FocusLost => {}
Event::Mouse(_m) => {}
Event::Paste(_p) => {}
Event::Resize(_x, _y) => {}
_ => {}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion r-lanui/src/ui/components/footer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl CustomWidget for InfoFooter {
.block(
Block::bordered()
.border_type(BorderType::Double)
.border_style(Style::new().fg(state.colors.border_focused_color)),
.border_style(Style::new().fg(state.colors.border_color)),
);

info_footer.render(area, buf)
Expand Down
24 changes: 13 additions & 11 deletions r-lanui/src/ui/components/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub struct Table {
headers: Option<Vec<String>>,
items: Vec<Vec<String>>,
item_height: usize,
column_size: usize,
column_sizes: Vec<usize>,
table_state: RefCell<TableState>,
scroll_state: RefCell<ScrollbarState>,
}
Expand All @@ -35,7 +35,7 @@ impl Table {
pub fn new(
items: Vec<Vec<String>>,
headers: Option<Vec<String>>,
column_size: usize,
column_sizes: Vec<usize>,
item_height: usize,
) -> Self {
let mut scroll_height = item_height;
Expand All @@ -46,7 +46,7 @@ impl Table {

Self {
headers,
column_size,
column_sizes,
items,
item_height,
table_state: RefCell::new(TableState::new()),
Expand Down Expand Up @@ -123,6 +123,7 @@ impl Table {

impl CustomWidgetRef for Table {
fn render_ref(&self, area: Rect, buf: &mut ratatui::prelude::Buffer, state: &State) {
// main table view + right aligned scrollbar
let table_rects =
Layout::horizontal([Constraint::Min(5), Constraint::Length(3)]).split(area);

Expand All @@ -148,10 +149,9 @@ impl CustomWidgetRef for Table {
.fg(state.colors.selected_row_fg);

let rows = self.items.iter().enumerate().map(|(_i, data)| {
let col_width = table_rects[0].width / self.column_size as u16;
let item = fit_to_width(data, col_width as usize);
let item = fit_to_width(data, self.column_sizes.clone());

// line breaks is my hacky way of centering the text
// line break - hacky way of centering the text
let mut line_break_count = self.item_height / 2;
let mut line_breaks = String::from("");

Expand All @@ -172,7 +172,7 @@ impl CustomWidgetRef for Table {

let mut widths: Vec<Constraint> = Vec::new();

for _ in 0..self.column_size {
for _ in self.column_sizes.iter() {
widths.push(Constraint::Max(COLUMN_MAX_WIDTH));
}

Expand All @@ -193,11 +193,13 @@ impl CustomWidgetRef for Table {
}
}

fn fit_to_width(item: &Vec<String>, col_width: usize) -> Vec<String> {
fn fit_to_width(item: &Vec<String>, col_widths: Vec<usize>) -> Vec<String> {
item.iter()
.map(|i| {
let width = i.width();
let mut value = i.clone();
.enumerate()
.map(|(i, v)| {
let width = v.width();
let mut value = v.clone();
let col_width = col_widths[i];
if width >= col_width {
value.truncate(col_width - ELLIPSIS.width());
value.push_str(ELLIPSIS);
Expand Down
7 changes: 2 additions & 5 deletions r-lanui/src/ui/store/action.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
use std::collections::HashMap;

use r_lanlib::scanners::DeviceWithPorts;
use ratatui::layout::{Position, Rect};

use crate::config::Config;

use super::state::{Theme, ViewID};

#[derive(Debug)]
pub enum Action<'conf_id, 'theme, 'devices, 'device, 'selected, 'config> {
UpdateLayout(Option<HashMap<ViewID, Rect>>),
ToggleViewSelect,
UpdateView(ViewID),
UpdateMessage(Option<String>),
Click(Position),
UpdateTheme((&'conf_id str, &'theme Theme)),
UpdateAllDevices(&'devices Vec<DeviceWithPorts>),
AddDevice(&'device DeviceWithPorts),
Expand Down
16 changes: 5 additions & 11 deletions r-lanui/src/ui/store/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ use core::fmt;
use std::collections::HashMap;

use r_lanlib::scanners::DeviceWithPorts;
use ratatui::{
layout::Rect,
style::{palette::tailwind, Color},
};
use ratatui::style::{palette::tailwind, Color};

use crate::config::Config;

Expand All @@ -15,6 +12,7 @@ pub enum ViewID {
Device,
Devices,
Config,
ViewSelect,
}

impl fmt::Display for ViewID {
Expand All @@ -32,10 +30,8 @@ pub struct Colors {
pub row_fg: Color,
pub row_bg: Color,
pub border_color: Color,
pub border_focused_color: Color,
pub scroll_bar_fg: Color,
pub label: Color,
pub placeholder: Color,
}

impl Colors {
Expand All @@ -47,25 +43,23 @@ impl Colors {
selected_row_fg: color.c400,
row_fg: tailwind::SLATE.c200,
row_bg: tailwind::SLATE.c950,
border_color: color.c950,
border_focused_color: color.c400,
border_color: color.c400,
scroll_bar_fg: tailwind::SLATE.c800,
placeholder: tailwind::SLATE.c800,
label: color.c400,
}
}
}

#[derive(Clone, Debug)]
pub struct State {
pub focused: ViewID,
pub render_view_select: bool,
pub view_id: ViewID,
pub config: Config,
pub devices: Vec<DeviceWithPorts>,
pub device_map: HashMap<String, DeviceWithPorts>,
pub selected_device: Option<String>,
pub colors: Colors,
pub message: Option<String>,
pub layout: Option<HashMap<ViewID, Rect>>,
}

#[derive(Debug, Eq, PartialEq, Clone)]
Expand Down
27 changes: 10 additions & 17 deletions r-lanui/src/ui/store/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ impl Store {
Self {
config_manager,
state: State {
focused: ViewID::Devices,
config: config,
render_view_select: false,
view_id: ViewID::Devices,
config,
devices: Vec::new(),
device_map: HashMap::new(),
selected_device: None,
colors: colors,
colors,
message: None,
layout: None,
},
}
}
Expand All @@ -52,26 +52,19 @@ impl Store {

pub fn update(&mut self, action: Action) {
let new_state = match action {
Action::UpdateLayout(layout) => {
Action::ToggleViewSelect => {
let mut state = self.state.clone();
state.layout = layout;
state.render_view_select = !state.render_view_select;
state
}
Action::UpdateMessage(message) => {
Action::UpdateView(id) => {
let mut state = self.state.clone();
state.message = message;
state.view_id = id;
state
}
Action::Click(position) => {
Action::UpdateMessage(message) => {
let mut state = self.state.clone();
let layout = state.layout.clone();
if let Some(layout) = layout {
layout.iter().for_each(|(id, area)| {
if area.contains(position) {
state.focused = id.clone();
}
});
}
state.message = message;
state
}
Action::UpdateTheme((config_id, theme)) => {
Expand Down
15 changes: 2 additions & 13 deletions r-lanui/src/ui/views.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ pub mod config;
pub mod device;
pub mod devices;
pub mod main;
pub mod view_select;

pub trait EventHandler {
fn process_event(&mut self, evt: &Event) -> bool;
fn process_event(&mut self, evt: &Event, state: &State) -> bool;
}

pub trait CustomWidget {
Expand All @@ -31,18 +32,6 @@ pub trait CustomStatefulWidget {
);
}

// pub trait CustomStatefulWidgetRef {
// type State;

// fn render_ref(
// &self,
// area: Rect,
// buf: &mut ratatui::prelude::Buffer,
// state: &mut Self::State,
// custom_state: &State,
// );
// }

pub trait View: EventHandler + WidgetRef {
fn id(&self) -> ViewID;
fn legend(&self) -> &str {
Expand Down
6 changes: 5 additions & 1 deletion r-lanui/src/ui/views/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,11 @@ impl WidgetRef for ConfigView {
}

impl EventHandler for ConfigView {
fn process_event(&mut self, evt: &Event) -> bool {
fn process_event(&mut self, evt: &Event, state: &State) -> bool {
if state.render_view_select {
return false;
}

let mut handled = false;
match evt {
Event::FocusGained => {}
Expand Down
21 changes: 17 additions & 4 deletions r-lanui/src/ui/views/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ use crate::{
ui::{
components::{device_info::DeviceInfo, header::Header},
store::{
action::Action,
dispatcher::Dispatcher,
state::{State, ViewID},
},
},
};
use r_lanlib::scanners::DeviceWithPorts;
use ratatui::{
crossterm::event::Event,
crossterm::event::{Event, KeyCode},
layout::{Constraint, Layout, Rect},
widgets::WidgetRef,
};
Expand Down Expand Up @@ -104,15 +105,27 @@ impl WidgetRef for DeviceView {
}

impl EventHandler for DeviceView {
fn process_event(&mut self, evt: &Event) -> bool {
let handled = false;
fn process_event(&mut self, evt: &Event, state: &State) -> bool {
if state.render_view_select {
return false;
}

let mut handled = false;

match evt {
Event::FocusGained => {}
Event::FocusLost => {}
Event::Mouse(_m) => {}
Event::Paste(_s) => {}
Event::Resize(_x, _y) => {}
Event::Key(_key) => {}
Event::Key(key) => match key.code {
KeyCode::Esc => {
handled = true;
self.dispatcher
.dispatch(Action::UpdateView(ViewID::Devices));
}
_ => {}
},
}

handled
Expand Down
Loading

0 comments on commit e8190eb

Please sign in to comment.