adds basics of pawn's placement
This commit is contained in:
60
src/grid.rs
60
src/grid.rs
@@ -4,18 +4,21 @@ pub struct Grid {
|
||||
inner: gtk::Grid,
|
||||
}
|
||||
|
||||
#[derive(Debug,Copy,Clone)]
|
||||
pub struct CellPosition(i32, i32);
|
||||
|
||||
impl Grid {
|
||||
// Initialize a grid, populating its cells
|
||||
// Only square grid for now
|
||||
pub fn init(inner: gtk::Grid, size: i32) -> Self {
|
||||
/// Initialize a grid, populating its cells
|
||||
/// Only square grid for now
|
||||
pub(crate) fn init(inner: gtk::Grid, size: i32, app_state: AppState) -> Self {
|
||||
for i in 0..(size * size) {
|
||||
let x = 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);
|
||||
// Signals
|
||||
}
|
||||
Grid { inner }
|
||||
}
|
||||
@@ -26,6 +29,7 @@ struct CellWidget {
|
||||
eventbox: gtk::EventBox,
|
||||
position: gtk::Label,
|
||||
header : gtk::Label,
|
||||
content: gtk::Label,
|
||||
}
|
||||
|
||||
impl CellWidget {
|
||||
@@ -68,25 +72,28 @@ impl CellWidget {
|
||||
.unwrap();
|
||||
position.set_text(&format!("{}x{}", pos.0, pos.1));
|
||||
|
||||
let header_clone = header.clone();
|
||||
eventbox.connect_button_press_event(Self::on_click(header_clone));
|
||||
|
||||
CellWidget {
|
||||
let cell = CellWidget {
|
||||
eventbox,
|
||||
position,
|
||||
header,
|
||||
}
|
||||
content: builder.get_object("content").unwrap(),
|
||||
};
|
||||
cell
|
||||
}
|
||||
|
||||
// Handler for button press events
|
||||
fn on_click(
|
||||
data: gtk::Label
|
||||
) -> impl Fn(>k::EventBox, &gdk::EventButton) -> gtk::Inhibit
|
||||
{
|
||||
move |_,_| {
|
||||
data.set_text("Clicked.");
|
||||
pub fn connect_clicked(&self, state: AppState) {
|
||||
let header = self.header.clone();
|
||||
let content = self.content.clone();
|
||||
self.eventbox
|
||||
.connect_button_press_event(move |_,_| {
|
||||
let mut state = state.borrow_mut();
|
||||
if let Some(data) = state.pending.take() {
|
||||
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,
|
||||
is_active: bool,
|
||||
is_occupied: bool,
|
||||
position: CellPosition,
|
||||
}
|
||||
|
||||
impl Cell {
|
||||
pub fn new(pos: CellPosition) -> Self {
|
||||
let inner = CellWidget::new(pos, "Empty cell");
|
||||
fn new(position: CellPosition) -> Self {
|
||||
Cell {
|
||||
inner,
|
||||
is_active: false,
|
||||
is_occupied: false,
|
||||
inner: CellWidget::new(position, ""),
|
||||
position
|
||||
}
|
||||
}
|
||||
|
||||
fn connect_clicked(&self, state: AppState) {
|
||||
self.inner.connect_clicked(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<gtk::EventBox> for Cell {
|
||||
|
||||
138
src/main.rs
138
src/main.rs
@@ -3,109 +3,44 @@ extern crate gio;
|
||||
extern crate gdk;
|
||||
extern crate glib;
|
||||
|
||||
use gtk::BoxExt;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use gtk::prelude::*;
|
||||
use gio::prelude::*;
|
||||
use std::env::args;
|
||||
use std::process;
|
||||
|
||||
mod grid;
|
||||
mod pawn;
|
||||
|
||||
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<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");
|
||||
}
|
||||
}
|
||||
/// Content of the Application state
|
||||
///
|
||||
#[derive(Debug,Clone,Default)]
|
||||
pub struct AppData {
|
||||
/// A slot for any pawn waiting for placement
|
||||
pending: Option<pawn::PawnData>,
|
||||
/// Owned list of pawns
|
||||
pawns: Vec<pawn::Pawn>,
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
inner: gtk::Application,
|
||||
pawns: Vec<pawn::Pawn>,
|
||||
state: AppState,
|
||||
}
|
||||
|
||||
|
||||
impl App {
|
||||
fn new<'a>() -> Result<Self, &'a str> {
|
||||
let app =
|
||||
@@ -114,14 +49,17 @@ impl App {
|
||||
"home.local.PlayMat",
|
||||
gio::ApplicationFlags::FLAGS_NONE
|
||||
).expect("Failed to build Application"),
|
||||
pawns: Vec::new(),
|
||||
state: Default::default(),
|
||||
};
|
||||
app.inner.connect_startup(|_| {});
|
||||
app.inner.connect_activate(Self::on_activate);
|
||||
app.connect_all();
|
||||
Ok(app)
|
||||
}
|
||||
|
||||
fn on_activate(app: >k::Application) {
|
||||
fn connect_all(&self) {
|
||||
let app_state = self.state.clone();
|
||||
self.inner.connect_startup(|_| {});
|
||||
self.inner.connect_activate(
|
||||
move |app| {
|
||||
println!("Activate App");
|
||||
let main_src = include_str!("../res/main.glade");
|
||||
let builder = gtk::Builder::new_from_string(main_src);
|
||||
@@ -146,7 +84,7 @@ impl App {
|
||||
// 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);
|
||||
let _grid = grid::Grid::init(grid, 10, app_state.clone());
|
||||
|
||||
// TODO:
|
||||
// * Display creature description when hovering over its position (cell)
|
||||
@@ -155,14 +93,19 @@ impl App {
|
||||
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);
|
||||
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();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/// 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,
|
||||
name: &str,
|
||||
f: F,
|
||||
@@ -173,6 +116,7 @@ impl App {
|
||||
}
|
||||
|
||||
fn run(&self, args: &[String]) -> i32 {
|
||||
println!("{:#?}", &self.state);
|
||||
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