adds basics of pawn's placement
This commit is contained in:
62
src/grid.rs
62
src/grid.rs
@@ -4,18 +4,21 @@ pub struct Grid {
|
|||||||
inner: gtk::Grid,
|
inner: gtk::Grid,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug,Copy,Clone)]
|
||||||
pub struct CellPosition(i32, i32);
|
pub struct CellPosition(i32, i32);
|
||||||
|
|
||||||
impl Grid {
|
impl Grid {
|
||||||
// Initialize a grid, populating its cells
|
/// Initialize a grid, populating its cells
|
||||||
// Only square grid for now
|
/// Only square grid for now
|
||||||
pub fn init(inner: gtk::Grid, size: i32) -> Self {
|
pub(crate) fn init(inner: gtk::Grid, size: i32, app_state: AppState) -> Self {
|
||||||
for i in 0..(size * size) {
|
for i in 0..(size * size) {
|
||||||
let x = i % size;
|
let x = i % size;
|
||||||
let y = i / size;
|
let y = i / size;
|
||||||
let cell = grid::Cell::new(CellPosition(x,y));
|
let cell = grid::Cell::new(
|
||||||
|
CellPosition(x,y)
|
||||||
|
);
|
||||||
|
cell.connect_clicked(app_state.clone());
|
||||||
inner.attach(cell.as_ref(), x, y, 1, 1);
|
inner.attach(cell.as_ref(), x, y, 1, 1);
|
||||||
// Signals
|
|
||||||
}
|
}
|
||||||
Grid { inner }
|
Grid { inner }
|
||||||
}
|
}
|
||||||
@@ -26,6 +29,7 @@ struct CellWidget {
|
|||||||
eventbox: gtk::EventBox,
|
eventbox: gtk::EventBox,
|
||||||
position: gtk::Label,
|
position: gtk::Label,
|
||||||
header : gtk::Label,
|
header : gtk::Label,
|
||||||
|
content: gtk::Label,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CellWidget {
|
impl CellWidget {
|
||||||
@@ -68,25 +72,28 @@ impl CellWidget {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
position.set_text(&format!("{}x{}", pos.0, pos.1));
|
position.set_text(&format!("{}x{}", pos.0, pos.1));
|
||||||
|
|
||||||
let header_clone = header.clone();
|
let cell = CellWidget {
|
||||||
eventbox.connect_button_press_event(Self::on_click(header_clone));
|
|
||||||
|
|
||||||
CellWidget {
|
|
||||||
eventbox,
|
eventbox,
|
||||||
position,
|
position,
|
||||||
header,
|
header,
|
||||||
}
|
content: builder.get_object("content").unwrap(),
|
||||||
|
};
|
||||||
|
cell
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler for button press events
|
pub fn connect_clicked(&self, state: AppState) {
|
||||||
fn on_click(
|
let header = self.header.clone();
|
||||||
data: gtk::Label
|
let content = self.content.clone();
|
||||||
) -> impl Fn(>k::EventBox, &gdk::EventButton) -> gtk::Inhibit
|
self.eventbox
|
||||||
{
|
.connect_button_press_event(move |_,_| {
|
||||||
move |_,_| {
|
let mut state = state.borrow_mut();
|
||||||
data.set_text("Clicked.");
|
if let Some(data) = state.pending.take() {
|
||||||
gtk::Inhibit(true)
|
println!("{:?}", data);
|
||||||
}
|
content.set_text(&data.name);
|
||||||
|
};
|
||||||
|
header.set_text("Is Clicked.");
|
||||||
|
gtk::Inhibit(true)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,21 +104,22 @@ impl AsRef<gtk::EventBox> for CellWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Cell {
|
struct Cell {
|
||||||
inner: CellWidget,
|
inner: CellWidget,
|
||||||
is_active: bool,
|
position: CellPosition,
|
||||||
is_occupied: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cell {
|
impl Cell {
|
||||||
pub fn new(pos: CellPosition) -> Self {
|
fn new(position: CellPosition) -> Self {
|
||||||
let inner = CellWidget::new(pos, "Empty cell");
|
|
||||||
Cell {
|
Cell {
|
||||||
inner,
|
inner: CellWidget::new(position, ""),
|
||||||
is_active: false,
|
position
|
||||||
is_occupied: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn connect_clicked(&self, state: AppState) {
|
||||||
|
self.inner.connect_clicked(state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRef<gtk::EventBox> for Cell {
|
impl AsRef<gtk::EventBox> for Cell {
|
||||||
|
|||||||
202
src/main.rs
202
src/main.rs
@@ -3,109 +3,44 @@ extern crate gio;
|
|||||||
extern crate gdk;
|
extern crate gdk;
|
||||||
extern crate glib;
|
extern crate glib;
|
||||||
|
|
||||||
use gtk::BoxExt;
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gio::prelude::*;
|
use gio::prelude::*;
|
||||||
use std::env::args;
|
use std::env::args;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
mod grid;
|
mod grid;
|
||||||
|
mod pawn;
|
||||||
|
|
||||||
mod pawn {
|
/// Content of the Application state
|
||||||
use super::*;
|
///
|
||||||
|
#[derive(Debug,Clone,Default)]
|
||||||
#[derive(Debug,Clone)]
|
pub struct AppData {
|
||||||
pub struct PawnList {
|
/// A slot for any pawn waiting for placement
|
||||||
inner: gtk::ListBox,
|
pending: Option<pawn::PawnData>,
|
||||||
}
|
/// Owned list of pawns
|
||||||
|
pawns: Vec<pawn::Pawn>,
|
||||||
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<S: Into<String>>(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<gtk::Box> for Pawn {
|
|
||||||
fn as_ref(&self) -> >k::Box {
|
|
||||||
&self.widget
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pawn_factory() -> Vec<Pawn> {
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A sharable state for the whole application
|
||||||
|
#[derive(Debug,Clone,Default)]
|
||||||
|
pub struct AppState(Rc<RefCell<AppData>>);
|
||||||
|
|
||||||
|
impl std::ops::Deref for AppState {
|
||||||
|
type Target = Rc<RefCell<AppData>>;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct App {
|
struct App {
|
||||||
inner: gtk::Application,
|
inner: gtk::Application,
|
||||||
pawns: Vec<pawn::Pawn>,
|
state: AppState,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
fn new<'a>() -> Result<Self, &'a str> {
|
fn new<'a>() -> Result<Self, &'a str> {
|
||||||
let app =
|
let app =
|
||||||
@@ -114,55 +49,63 @@ impl App {
|
|||||||
"home.local.PlayMat",
|
"home.local.PlayMat",
|
||||||
gio::ApplicationFlags::FLAGS_NONE
|
gio::ApplicationFlags::FLAGS_NONE
|
||||||
).expect("Failed to build Application"),
|
).expect("Failed to build Application"),
|
||||||
pawns: Vec::new(),
|
state: Default::default(),
|
||||||
};
|
};
|
||||||
app.inner.connect_startup(|_| {});
|
app.connect_all();
|
||||||
app.inner.connect_activate(Self::on_activate);
|
|
||||||
Ok(app)
|
Ok(app)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_activate(app: >k::Application) {
|
fn connect_all(&self) {
|
||||||
println!("Activate App");
|
let app_state = self.state.clone();
|
||||||
let main_src = include_str!("../res/main.glade");
|
self.inner.connect_startup(|_| {});
|
||||||
let builder = gtk::Builder::new_from_string(main_src);
|
self.inner.connect_activate(
|
||||||
let win: gtk::ApplicationWindow =
|
move |app| {
|
||||||
builder
|
println!("Activate App");
|
||||||
.get_object("app")
|
let main_src = include_str!("../res/main.glade");
|
||||||
.unwrap();
|
let builder = gtk::Builder::new_from_string(main_src);
|
||||||
win.set_application(app);
|
let win: gtk::ApplicationWindow =
|
||||||
|
builder
|
||||||
|
.get_object("app")
|
||||||
|
.unwrap();
|
||||||
|
win.set_application(app);
|
||||||
|
|
||||||
// Set up a simple switch for the Pawn list panel
|
// Set up a simple switch for the Pawn list panel
|
||||||
let panel: gtk::Paned = builder.get_object("panel").unwrap();
|
let panel: gtk::Paned = builder.get_object("panel").unwrap();
|
||||||
Self::new_action(app, "panel_switch", move |_,_| {
|
Self::new_action(app, "panel_switch", move |_,_| {
|
||||||
if panel.get_position() == 0 {
|
if panel.get_position() == 0 {
|
||||||
panel.set_position(360);
|
panel.set_position(360);
|
||||||
} else {
|
} else {
|
||||||
panel.set_position(0);
|
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, app_state.clone());
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
pawn.connect_place(app_state.clone());
|
||||||
|
pawn.connect_stats();
|
||||||
|
app_state.borrow_mut().pawns.push(pawn);
|
||||||
|
}
|
||||||
|
win.show_all();
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
|
||||||
// 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.
|
/// Creates a simple action and connects the given handler to its activate signal.
|
||||||
pub fn new_action<F: Fn(&gio::SimpleAction, &Option<glib::Variant>) + 'static>(
|
fn new_action<F: Fn(&gio::SimpleAction, &Option<glib::Variant>) + 'static>(
|
||||||
app: >k::Application,
|
app: >k::Application,
|
||||||
name: &str,
|
name: &str,
|
||||||
f: F,
|
f: F,
|
||||||
@@ -173,6 +116,7 @@ impl App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run(&self, args: &[String]) -> i32 {
|
fn run(&self, args: &[String]) -> i32 {
|
||||||
|
println!("{:#?}", &self.state);
|
||||||
self.inner.run(args)
|
self.inner.run(args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
99
src/pawn.rs
Normal file
99
src/pawn.rs
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug,Clone)]
|
||||||
|
pub struct PawnData {
|
||||||
|
pub name: String,
|
||||||
|
pub position: Option<String>, // Content of label from CellWidget
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Pawn {
|
||||||
|
data: PawnData,
|
||||||
|
widget: gtk::Box,
|
||||||
|
place_btn: gtk::Button,
|
||||||
|
stats_btn: gtk::Button,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pawn {
|
||||||
|
pub fn new<S: Into<String>>(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 widget: gtk::Box = builder.get_object("pawn").unwrap();
|
||||||
|
Pawn {
|
||||||
|
data: PawnData{ name, position: None, },
|
||||||
|
widget,
|
||||||
|
place_btn: builder.get_object("place_btn").unwrap(),
|
||||||
|
stats_btn: builder.get_object("stats_btn").unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn connect_place(&self, state: AppState) {
|
||||||
|
let name = self.data.name.clone();
|
||||||
|
let data = self.data.clone();
|
||||||
|
self.place_btn
|
||||||
|
.connect_clicked(
|
||||||
|
move |_| {
|
||||||
|
println!("Placing {}...", name);
|
||||||
|
let mut state = state.0.borrow_mut();
|
||||||
|
state.pending = Some(data.clone()); // ???
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn connect_stats(&self) {
|
||||||
|
self.stats_btn
|
||||||
|
.connect_clicked(
|
||||||
|
move |_| {
|
||||||
|
println!("Showing stats...");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<gtk::Box> for Pawn {
|
||||||
|
fn as_ref(&self) -> >k::Box {
|
||||||
|
&self.widget
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pawn_factory() -> Vec<Pawn> {
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user