extern crate gtk; extern crate gio; extern crate gdk; extern crate glib; use gtk::BoxExt; use gtk::prelude::*; use gio::prelude::*; use std::env::args; use std::process; mod grid; mod pawn { use super::*; #[derive(Debug,Clone)] pub struct PawnList { inner: gtk::ListBox, } impl PawnList { pub fn init(inner: gtk::ListBox) -> Self { PawnList{ inner } } pub fn add(&self, pawn: &Pawn) { let row = gtk::ListBoxRow::new(); row.add(pawn.as_ref()); self.inner.add(&row); } } struct PawnData { name: String, } pub struct Pawn { data: PawnData, widget: gtk::Box, } impl Pawn { pub fn new>(name: S) -> Self { let pawn_src = include_str!("../res/pawn.glade"); let builder = gtk::Builder::new_from_string(pawn_src); let name = name.into(); let label: gtk::Label = builder .get_object("name") .unwrap(); label.set_text(&name); let place_btn: gtk::Button = builder .get_object("place_btn") .unwrap(); place_btn.connect_clicked(|_| { println!("Placing..."); }); let stats_btn: gtk::Button = builder .get_object("stats_btn") .unwrap(); stats_btn.connect_clicked(|_| { println!("Showing stats..."); }); let widget: gtk::Box = builder.get_object("pawn").unwrap(); Pawn { data: PawnData{ name }, widget, } } } impl AsRef for Pawn { fn as_ref(&self) -> >k::Box { &self.widget } } pub fn pawn_factory() -> Vec { let mut pawns = Vec::with_capacity(3); for name in &["Lomion", "Oilosse", "Fefi"] { pawns.push(Pawn::new(*name)); } pawns } #[cfg(test)] mod tests { #[test] fn test_pawn_factory() { let pawns = pawn_factory(); assert_eq!(pawns.len(), 3); assert_eq!(pawns.get(2).unwrap(), "Fefi"); } } } struct App { inner: gtk::Application, pawns: Vec, } impl App { fn new<'a>() -> Result { let app = App { inner: gtk::Application::new( "home.local.PlayMat", gio::ApplicationFlags::FLAGS_NONE ).expect("Failed to build Application"), pawns: Vec::new(), }; app.inner.connect_startup(|_| {}); app.inner.connect_activate(Self::on_activate); Ok(app) } fn on_activate(app: >k::Application) { println!("Activate App"); let main_src = include_str!("../res/main.glade"); let builder = gtk::Builder::new_from_string(main_src); let win: gtk::ApplicationWindow = builder .get_object("app") .unwrap(); win.set_application(app); // Set up a simple switch for the Pawn list panel let panel: gtk::Paned = builder.get_object("panel").unwrap(); Self::new_action(app, "panel_switch", move |_,_| { if panel.get_position() == 0 { panel.set_position(360); } else { panel.set_position(0); } }); // Initialize grid let grid: gtk::Grid = builder.get_object("map").unwrap(); // TODO: implement drag-drop events // * From pawn_list to cell : place pawn on dest cell // * From cell to cell : move pawn from source to dest cell let _grid = grid::Grid::init(grid, 10); // TODO: // * Display creature description when hovering over its position (cell) // TODO: Pawn list let pawn_list = builder.get_object("pawn_list").unwrap(); let pawn_list = pawn::PawnList::init(pawn_list); for pawn in &pawn::pawn_factory() { pawn_list.add(pawn); } win.show_all(); } /// Creates a simple action and connects the given handler to its activate signal. pub fn new_action) + 'static>( app: >k::Application, name: &str, f: F, ) { let action = gio::SimpleAction::new(name, None); action.connect_activate(f); app.add_action(&action); } fn run(&self, args: &[String]) -> i32 { self.inner.run(args) } } fn main() { if gtk::init().is_err() { println!("Failed to initialize Gtk"); return } let exit_code = match App::new() { Err(e) => { println!("Error !\n{}", e); 1 }, Ok(app) => app.run(&args().collect::>()), }; process::exit(exit_code); }