use fltk::{
app, draw, enums, input,
prelude::{GroupExt, InputExt, TableExt, WidgetBase, WidgetExt},
table, window,
};
use std::cell::RefCell;
use std::rc::Rc;
pub type MyData = Vec<Vec<String>>;
#[derive(Default)]
struct CellData {
row: i32, col: i32, x: i32,
y: i32,
w: i32,
h: i32,
}
impl CellData {
pub fn select(&mut self, row: i32, col: i32, x: i32, y: i32, w: i32, h: i32) {
self.row = row;
self.col = col;
self.x = x;
self.y = y;
self.w = w;
self.h = h;
}
}
pub struct MyTable {
table: table::Table,
data: Rc<RefCell<MyData>>,
cell: Rc<RefCell<CellData>>,
}
impl MyTable {
pub fn new(mut inp: input::Input) -> Self {
let mut table = table::Table::default()
.with_size(800 - 10, 600 - 10)
.center_of_parent();
let data = Rc::from(RefCell::from(vec![vec![String::from(""); 26]; 28]));
let cell = Rc::from(RefCell::from(CellData::default()));
table.set_rows(28);
table.set_row_header(true);
table.set_row_resize(true);
table.set_cols(26);
table.set_col_header(true);
table.set_col_width_all(80);
table.set_col_resize(true);
table.end();
let cell_c = cell.clone();
let data_c = data.clone();
table.draw_cell(move |t, ctx, row, col, x, y, w, h| match ctx {
table::TableContext::StartPage => draw::set_font(enums::Font::Helvetica, 14),
table::TableContext::ColHeader => {
Self::draw_header(&format!("{}", (col + 65) as u8 as char), x, y, w, h)
} table::TableContext::RowHeader => {
Self::draw_header(&format!("{}", row + 1), x, y, w, h)
} table::TableContext::Cell => {
if t.is_selected(row, col) {
cell_c.borrow_mut().select(row, col, x, y, w, h); }
Self::draw_data(
&data_c.borrow()[row as usize][col as usize].to_string(),
x,
y,
w,
h,
t.is_selected(row, col),
);
}
_ => (),
});
let cell_c = cell.clone();
let data_c = data.clone();
table.handle(move |_, ev| match ev {
enums::Event::Released => {
let c = cell_c.borrow();
inp.resize(c.x, c.y, c.w, c.h);
inp.set_value(&data_c.borrow_mut()[c.row as usize][c.col as usize]);
inp.show();
inp.take_focus().ok();
inp.redraw();
true
}
_ => false,
});
Self { table, data, cell }
}
pub fn redraw(&mut self) {
self.table.redraw()
}
fn draw_header(txt: &str, x: i32, y: i32, w: i32, h: i32) {
draw::push_clip(x, y, w, h);
draw::draw_box(
enums::FrameType::ThinUpBox,
x,
y,
w,
h,
enums::Color::FrameDefault,
);
draw::set_draw_color(enums::Color::Black);
draw::set_font(enums::Font::Helvetica, 14);
draw::draw_text2(txt, x, y, w, h, enums::Align::Center);
draw::pop_clip();
}
fn draw_data(txt: &str, x: i32, y: i32, w: i32, h: i32, selected: bool) {
draw::push_clip(x, y, w, h);
if selected {
draw::set_draw_color(enums::Color::from_u32(0x00D3_D3D3));
} else {
draw::set_draw_color(enums::Color::White);
}
draw::draw_rectf(x, y, w, h);
draw::set_draw_color(enums::Color::Gray0);
draw::set_font(enums::Font::Helvetica, 14);
draw::draw_text2(txt, x, y, w, h, enums::Align::Center);
draw::draw_rect(x, y, w, h);
draw::pop_clip();
}
}
fn main() {
let app = app::App::default().with_scheme(app::Scheme::Gtk);
let mut wind = window::Window::default().with_size(800, 600);
let mut inp = input::Input::default();
inp.hide();
let mut table = MyTable::new(inp.clone());
wind.make_resizable(true);
wind.end();
wind.show();
wind.handle(move |_, ev| match ev {
enums::Event::KeyDown => {
if app::event_key() == enums::Key::Enter {
let c = table.cell.borrow();
table.data.borrow_mut()[c.row as usize][c.col as usize] = inp.value();
inp.set_value("");
inp.hide();
return true;
}
table.redraw();
false
}
_ => false,
});
wind.set_callback(|_| {
if app::event() == enums::Event::Close {
app::quit();
}
});
app.run().unwrap();
}