first steps
This commit is contained in:
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/target
|
||||
**/*.rs.bk
|
||||
|
||||
Cargo.lock
|
||||
|
||||
**/*.glade~
|
||||
14
Cargo.toml
Normal file
14
Cargo.toml
Normal file
@@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "playmat"
|
||||
version = "0.1.0"
|
||||
authors = ["Artus <artus@landoftheunicorn.ovh>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
gio = "*"
|
||||
gdk = "*"
|
||||
glib = "*"
|
||||
|
||||
[dependencies.gtk]
|
||||
version = "^0.6.0"
|
||||
features = ["v3_22"]
|
||||
77
res/cell.glade
Normal file
77
res/cell.glade
Normal file
@@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.22.1 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkEventBox" id="cell">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<signal name="button-press-event" handler="on_press_button" swapped="no"/>
|
||||
<signal name="drag-begin" handler="on_drag_begin" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkFrame">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">3</property>
|
||||
<property name="margin_right">3</property>
|
||||
<property name="margin_bottom">2</property>
|
||||
<property name="label_xalign">0.94999998807907104</property>
|
||||
<property name="label_yalign">0.20000000298023224</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="box">
|
||||
<property name="width_request">128</property>
|
||||
<property name="height_request">128</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="header">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | GDK_BUTTON3_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK | GDK_VISIBILITY_NOTIFY_MASK | GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK | GDK_SUBSTRUCTURE_MASK | GDK_SCROLL_MASK | GDK_TOUCH_MASK | GDK_SMOOTH_SCROLL_MASK | GDK_TOUCHPAD_GESTURE_MASK | GDK_TABLET_PAD_MASK</property>
|
||||
<property name="label" translatable="yes">Cell</property>
|
||||
<property name="justify">right</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
<attribute name="scale" value="1"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="content">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Occupancy
|
||||
Status</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="label">
|
||||
<object class="GtkLabel" id="position">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">_x_</property>
|
||||
<attributes>
|
||||
<attribute name="style" value="italic"/>
|
||||
<attribute name="variant" value="small-caps"/>
|
||||
<attribute name="stretch" value="semi-expanded"/>
|
||||
<attribute name="scale" value="1"/>
|
||||
<attribute name="foreground" value="#88888a8a8585"/>
|
||||
</attributes>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
123
res/main.glade
Normal file
123
res/main.glade
Normal file
@@ -0,0 +1,123 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.22.1 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkApplicationWindow" id="app">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | GDK_BUTTON3_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK | GDK_VISIBILITY_NOTIFY_MASK | GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK | GDK_SUBSTRUCTURE_MASK | GDK_SCROLL_MASK | GDK_TOUCH_MASK | GDK_SMOOTH_SCROLL_MASK | GDK_TOUCHPAD_GESTURE_MASK | GDK_TABLET_PAD_MASK</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header_bar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="title" translatable="yes">Play Mat</property>
|
||||
<property name="subtitle" translatable="yes">version 0.1</property>
|
||||
<property name="show_close_button">True</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Créatures</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="action_name">app.panel_switch</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkPaned" id="panel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="position">80</property>
|
||||
<child>
|
||||
<object class="GtkListBox" id="pawn_list">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkListBoxRow">
|
||||
<property name="width_request">100</property>
|
||||
<property name="height_request">80</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="resize">False</property>
|
||||
<property name="shrink">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | GDK_BUTTON3_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK | GDK_VISIBILITY_NOTIFY_MASK | GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK | GDK_SUBSTRUCTURE_MASK | GDK_SCROLL_MASK | GDK_TOUCH_MASK | GDK_SMOOTH_SCROLL_MASK | GDK_TOUCHPAD_GESTURE_MASK | GDK_TABLET_PAD_MASK</property>
|
||||
<property name="margin_left">10</property>
|
||||
<property name="margin_right">10</property>
|
||||
<property name="margin_top">10</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<property name="shadow_type">out</property>
|
||||
<property name="min_content_width">640</property>
|
||||
<property name="min_content_height">480</property>
|
||||
<property name="max_content_width">800</property>
|
||||
<property name="max_content_height">600</property>
|
||||
<property name="propagate_natural_width">True</property>
|
||||
<property name="propagate_natural_height">True</property>
|
||||
<child>
|
||||
<object class="GtkViewport">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | GDK_BUTTON3_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK | GDK_VISIBILITY_NOTIFY_MASK | GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK | GDK_SUBSTRUCTURE_MASK | GDK_SCROLL_MASK | GDK_TOUCH_MASK | GDK_SMOOTH_SCROLL_MASK | GDK_TOUCHPAD_GESTURE_MASK | GDK_TABLET_PAD_MASK</property>
|
||||
<property name="shadow_type">etched-in</property>
|
||||
<child>
|
||||
<object class="GtkGrid" id="map">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | GDK_BUTTON3_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK | GDK_VISIBILITY_NOTIFY_MASK | GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK | GDK_SUBSTRUCTURE_MASK | GDK_SCROLL_MASK | GDK_TOUCH_MASK | GDK_SMOOTH_SCROLL_MASK | GDK_TOUCHPAD_GESTURE_MASK | GDK_TABLET_PAD_MASK</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="resize">False</property>
|
||||
<property name="shrink">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
104
src/grid.rs
Normal file
104
src/grid.rs
Normal file
@@ -0,0 +1,104 @@
|
||||
use crate::*;
|
||||
|
||||
pub struct Grid {
|
||||
inner: gtk::Grid,
|
||||
}
|
||||
|
||||
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 {
|
||||
for i in 0..(size * size) {
|
||||
let x = i % size;
|
||||
let y = i / size;
|
||||
let cell = grid::Cell::new(CellPosition(x,y));
|
||||
inner.attach(cell.as_ref(), x, y, 1, 1);
|
||||
// Signals
|
||||
}
|
||||
Grid { inner }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct CellWidget {
|
||||
eventbox: gtk::EventBox,
|
||||
position: gtk::Label,
|
||||
header : gtk::Label,
|
||||
}
|
||||
|
||||
impl CellWidget {
|
||||
fn new(pos: CellPosition, header_text: &str) -> Self {
|
||||
let cell_src = include_str!("../res/cell.glade");
|
||||
let builder = gtk::Builder::new_from_string(&cell_src);
|
||||
|
||||
let eventbox: gtk::EventBox =
|
||||
builder
|
||||
.get_object("cell")
|
||||
.unwrap();
|
||||
eventbox.set_events(gdk::EventMask::BUTTON_PRESS_MASK);
|
||||
|
||||
let header: gtk::Label =
|
||||
builder
|
||||
.get_object("header")
|
||||
.unwrap();
|
||||
header.set_text(header_text);
|
||||
let position: gtk::Label =
|
||||
builder
|
||||
.get_object("position")
|
||||
.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 {
|
||||
eventbox,
|
||||
position,
|
||||
header,
|
||||
}
|
||||
}
|
||||
|
||||
// Handler for button press events
|
||||
fn on_click(
|
||||
data: gtk::Label
|
||||
) -> impl Fn(>k::EventBox, &gdk::EventButton) -> gtk::Inhibit
|
||||
{
|
||||
move |_,_| {
|
||||
data.set_text("Clicked.");
|
||||
gtk::Inhibit(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<gtk::EventBox> for CellWidget {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> >k::EventBox {
|
||||
&self.eventbox
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Cell {
|
||||
inner: CellWidget,
|
||||
is_active: bool,
|
||||
is_occupied: bool,
|
||||
}
|
||||
|
||||
impl Cell {
|
||||
pub fn new(pos: CellPosition) -> Self {
|
||||
let inner = CellWidget::new(pos, "Empty cell");
|
||||
Cell {
|
||||
inner,
|
||||
is_active: false,
|
||||
is_occupied: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<gtk::EventBox> for Cell {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> >k::EventBox {
|
||||
self.inner.as_ref()
|
||||
}
|
||||
}
|
||||
119
src/main.rs
Normal file
119
src/main.rs
Normal file
@@ -0,0 +1,119 @@
|
||||
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 {
|
||||
|
||||
pub struct Pawn {
|
||||
name: String
|
||||
}
|
||||
|
||||
fn pawn_factory() -> Vec<Pawn> {
|
||||
let mut pawns = Vec::with_capacity(3);
|
||||
for name in &["Lomion", "Oilosse", "Fefi"] {
|
||||
pawns.push(Pawn{ name: name.to_string() });
|
||||
}
|
||||
pawns
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn test_pawn_factory() {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct App {
|
||||
inner: gtk::Application,
|
||||
pawns: Vec<pawn::Pawn>,
|
||||
}
|
||||
|
||||
impl App {
|
||||
fn new<'a>() -> Result<Self, &'a str> {
|
||||
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
|
||||
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>(
|
||||
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::<Vec<_>>()),
|
||||
};
|
||||
process::exit(exit_code);
|
||||
}
|
||||
Reference in New Issue
Block a user