Compare commits
No commits in common. "a584fb4de374dcedaebac22fa0fa4b3927b9aad9" and "07b73515013ec92eab3bdd57b8a9d330ad722600" have entirely different histories.
a584fb4de3
...
07b7351501
|
@ -1348,7 +1348,7 @@ dependencies = [
|
||||||
"gtk4",
|
"gtk4",
|
||||||
"image",
|
"image",
|
||||||
"kifu-core",
|
"kifu-core",
|
||||||
"sgf",
|
"screenplay",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -69,11 +69,17 @@ pub struct CoreApp {
|
||||||
|
|
||||||
impl CoreApp {
|
impl CoreApp {
|
||||||
pub fn new(config_path: std::path::PathBuf) -> Self {
|
pub fn new(config_path: std::path::PathBuf) -> Self {
|
||||||
|
println!("config_path: {:?}", config_path);
|
||||||
let config = Config::from_path(config_path).expect("configuration to open");
|
let config = Config::from_path(config_path).expect("configuration to open");
|
||||||
|
println!("config: {:?}", config);
|
||||||
|
|
||||||
let db_path: DatabasePath = config.get().unwrap();
|
let db_path: DatabasePath = config.get().unwrap();
|
||||||
|
println!("db_path: {:?}", db_path);
|
||||||
let state = Arc::new(RwLock::new(AppState::new(db_path)));
|
let state = Arc::new(RwLock::new(AppState::new(db_path)));
|
||||||
|
|
||||||
|
println!("config: {:?}", config);
|
||||||
|
println!("games database: {:?}", state.read().unwrap().database.len());
|
||||||
|
|
||||||
Self { config, state }
|
Self { config, state }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,7 @@ gtk = { version = "0.6", package = "gtk4", features = ["v4_8"] }
|
||||||
image = { version = "0.24" }
|
image = { version = "0.24" }
|
||||||
kifu-core = { path = "../core" }
|
kifu-core = { path = "../core" }
|
||||||
tokio = { version = "1.26", features = [ "full" ] }
|
tokio = { version = "1.26", features = [ "full" ] }
|
||||||
# screenplay = { path = "../../screenplay" }
|
screenplay = { path = "../../screenplay" }
|
||||||
sgf = { path = "../../sgf" }
|
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
glib-build-tools = "0.17"
|
glib-build-tools = "0.17"
|
||||||
|
|
|
@ -13,8 +13,8 @@ fn handle_response(api: CoreApi, window: gtk::ApplicationWindow, message: CoreRe
|
||||||
CoreResponse::HomeView(view) => perftrace("HomeView", || {
|
CoreResponse::HomeView(view) => perftrace("HomeView", || {
|
||||||
let api = api.clone();
|
let api = api.clone();
|
||||||
|
|
||||||
let home = Home::new(api, view);
|
let new_game = Home::new(api, view);
|
||||||
window.set_child(Some(&home));
|
window.set_child(Some(&new_game));
|
||||||
}),
|
}),
|
||||||
CoreResponse::PlayingFieldView(view) => perftrace("PlayingFieldView", || {
|
CoreResponse::PlayingFieldView(view) => perftrace("PlayingFieldView", || {
|
||||||
let api = api.clone();
|
let api = api.clone();
|
||||||
|
|
|
@ -1,62 +1,59 @@
|
||||||
use glib::Object;
|
use glib::{Object, Properties};
|
||||||
use gtk::{glib, prelude::*, subclass::prelude::*};
|
use gtk::{glib, prelude::*, subclass::prelude::*};
|
||||||
use kifu_core::ui::GamePreviewElement;
|
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct GameObjectPrivate {
|
pub struct IntegerObjectPrivate {
|
||||||
game: Rc<RefCell<Option<GamePreviewElement>>>,
|
number: Rc<RefCell<i32>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[glib::object_subclass]
|
#[glib::object_subclass]
|
||||||
impl ObjectSubclass for GameObjectPrivate {
|
impl ObjectSubclass for IntegerObjectPrivate {
|
||||||
const NAME: &'static str = "GameObject";
|
const NAME: &'static str = "IntegerObject";
|
||||||
type Type = GameObject;
|
type Type = IntegerObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ObjectImpl for GameObjectPrivate {}
|
impl ObjectImpl for IntegerObjectPrivate {}
|
||||||
|
|
||||||
glib::wrapper! {
|
glib::wrapper! {
|
||||||
pub struct GameObject(ObjectSubclass<GameObjectPrivate>);
|
pub struct IntegerObject(ObjectSubclass<IntegerObjectPrivate>);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GameObject {
|
impl IntegerObject {
|
||||||
pub fn new(game: GamePreviewElement) -> Self {
|
pub fn new(number: i32) -> Self {
|
||||||
let s: Self = Object::builder().build();
|
let s: Self = Object::builder().build();
|
||||||
*s.imp().game.borrow_mut() = Some(game);
|
*s.imp().number.borrow_mut() = number;
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn game(&self) -> Option<GamePreviewElement> {
|
pub fn number(&self) -> i32 {
|
||||||
self.imp().game.borrow().clone()
|
self.imp().number.borrow().clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GameDatabasePrivate {
|
pub struct GameDatabasePrivate {
|
||||||
model: gio::ListStore,
|
|
||||||
list_view: gtk::ListView,
|
list_view: gtk::ListView,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for GameDatabasePrivate {
|
impl Default for GameDatabasePrivate {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let vector: Vec<GameObject> = vec![];
|
let vector: Vec<IntegerObject> = (0..=500).map(IntegerObject::new).collect();
|
||||||
let model = gio::ListStore::new(glib::types::Type::OBJECT);
|
let model = gio::ListStore::new(glib::types::Type::OBJECT);
|
||||||
model.extend_from_slice(&vector);
|
model.extend_from_slice(&vector);
|
||||||
let factory = gtk::SignalListItemFactory::new();
|
let factory = gtk::SignalListItemFactory::new();
|
||||||
|
|
||||||
factory.connect_setup(move |_, list_item| {
|
factory.connect_setup(move |_, list_item| {
|
||||||
let label = gtk::Label::new(Some("some kind of text"));
|
let label = gtk::Label::new(None);
|
||||||
list_item
|
list_item
|
||||||
.downcast_ref::<gtk::ListItem>()
|
.downcast_ref::<gtk::ListItem>()
|
||||||
.expect("Needs to be a ListItem")
|
.expect("Needs to be a ListItem")
|
||||||
.set_child(Some(&label));
|
.set_child(Some(&label));
|
||||||
});
|
});
|
||||||
factory.connect_bind(move |_, list_item| {
|
factory.connect_bind(move |_, list_item| {
|
||||||
let game_object = list_item
|
let integer_object = list_item
|
||||||
.downcast_ref::<gtk::ListItem>()
|
.downcast_ref::<gtk::ListItem>()
|
||||||
.expect("Needs to be ListItem")
|
.expect("Needs to be ListItem")
|
||||||
.item()
|
.item()
|
||||||
.and_downcast::<GameObject>()
|
.and_downcast::<IntegerObject>()
|
||||||
.expect("The item has to be an IntegerObject.");
|
.expect("The item has to be an IntegerObject.");
|
||||||
|
|
||||||
let label = list_item
|
let label = list_item
|
||||||
|
@ -66,25 +63,12 @@ impl Default for GameDatabasePrivate {
|
||||||
.and_downcast::<gtk::Label>()
|
.and_downcast::<gtk::Label>()
|
||||||
.expect("The child has to be an Label.");
|
.expect("The child has to be an Label.");
|
||||||
|
|
||||||
label.set_label(
|
label.set_label(&integer_object.number().to_string());
|
||||||
format!(
|
|
||||||
"{} vs. {}",
|
|
||||||
game_object
|
|
||||||
.game()
|
|
||||||
.map(|g| g.black_player)
|
|
||||||
.unwrap_or("black".to_owned()),
|
|
||||||
game_object
|
|
||||||
.game()
|
|
||||||
.map(|g| g.white_player)
|
|
||||||
.unwrap_or("white".to_owned())
|
|
||||||
)
|
|
||||||
.as_ref(),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let selection_model = gtk::NoSelection::new(Some(model.clone()));
|
let selection_model = gtk::SingleSelection::new(Some(model));
|
||||||
let list_view = gtk::ListView::new(Some(selection_model), Some(factory));
|
let list_view = gtk::ListView::new(Some(selection_model), Some(factory));
|
||||||
Self { model, list_view }
|
Self { list_view }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,17 +90,7 @@ glib::wrapper! {
|
||||||
impl GameDatabase {
|
impl GameDatabase {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let s: Self = Object::builder().build();
|
let s: Self = Object::builder().build();
|
||||||
s.set_width_request(200);
|
|
||||||
s.set_height_request(200);
|
|
||||||
s.append(&s.imp().list_view);
|
s.append(&s.imp().list_view);
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_games(&self, games: Vec<GamePreviewElement>) {
|
|
||||||
let games = games
|
|
||||||
.into_iter()
|
|
||||||
.map(|g| GameObject::new(g))
|
|
||||||
.collect::<Vec<GameObject>>();
|
|
||||||
self.imp().model.extend_from_slice(&games);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
use crate::CoreApi;
|
use crate::{ui::GamePreview, CoreApi};
|
||||||
use glib::Object;
|
use glib::{Object, Properties};
|
||||||
use gtk::{glib, prelude::*, subclass::prelude::*};
|
use gtk::{glib, prelude::*, subclass::prelude::*};
|
||||||
use kifu_core::{
|
use kifu_core::{
|
||||||
ui::{HomeView, PlayerElement},
|
ui::{GamePreviewElement, HomeView, PlayerElement},
|
||||||
CoreRequest, CreateGameRequest, HotseatPlayerRequest, PlayerInfoRequest,
|
CoreRequest, CreateGameRequest, HotseatPlayerRequest, PlayerInfoRequest,
|
||||||
};
|
};
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use std::{
|
||||||
|
cell::{Cell, RefCell},
|
||||||
|
rc::Rc,
|
||||||
|
};
|
||||||
|
|
||||||
use super::GameDatabase;
|
use super::GameDatabase;
|
||||||
|
|
||||||
|
@ -84,6 +87,44 @@ impl PlayerDataEntry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct DatabaseGamePrivate {
|
||||||
|
game: Rc<RefCell<GamePreviewElement>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DatabaseGamePrivate {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
game: Rc::new(RefCell::new(GamePreviewElement {
|
||||||
|
date: vec![],
|
||||||
|
black_player: "".to_owned(),
|
||||||
|
black_rank: None,
|
||||||
|
white_player: "".to_owned(),
|
||||||
|
white_rank: None,
|
||||||
|
})),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[glib::object_subclass]
|
||||||
|
impl ObjectSubclass for DatabaseGamePrivate {
|
||||||
|
const NAME: &'static str = "DatabaseGame";
|
||||||
|
type Type = DatabaseGame;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ObjectImpl for DatabaseGamePrivate {}
|
||||||
|
|
||||||
|
glib::wrapper! {
|
||||||
|
pub struct DatabaseGame(ObjectSubclass<DatabaseGamePrivate>);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DatabaseGame {
|
||||||
|
pub fn new(preview: GamePreviewElement) -> Self {
|
||||||
|
let s: Self = Object::builder().build();
|
||||||
|
*s.imp().game.borrow_mut() = preview;
|
||||||
|
s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct HomePrivate {
|
pub struct HomePrivate {
|
||||||
black_player: Rc<RefCell<Option<PlayerDataEntry>>>,
|
black_player: Rc<RefCell<Option<PlayerDataEntry>>>,
|
||||||
white_player: Rc<RefCell<Option<PlayerDataEntry>>>,
|
white_player: Rc<RefCell<Option<PlayerDataEntry>>>,
|
||||||
|
@ -102,51 +143,34 @@ impl Default for HomePrivate {
|
||||||
impl ObjectSubclass for HomePrivate {
|
impl ObjectSubclass for HomePrivate {
|
||||||
const NAME: &'static str = "Home";
|
const NAME: &'static str = "Home";
|
||||||
type Type = Home;
|
type Type = Home;
|
||||||
type ParentType = gtk::Box;
|
type ParentType = gtk::Grid;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ObjectImpl for HomePrivate {}
|
impl ObjectImpl for HomePrivate {}
|
||||||
impl WidgetImpl for HomePrivate {}
|
impl WidgetImpl for HomePrivate {}
|
||||||
impl BoxImpl for HomePrivate {}
|
impl GridImpl for HomePrivate {}
|
||||||
|
|
||||||
glib::wrapper! {
|
glib::wrapper! {
|
||||||
pub struct Home(ObjectSubclass<HomePrivate>) @extends gtk::Box, gtk::Widget, @implements gtk::Orientable;
|
pub struct Home(ObjectSubclass<HomePrivate>) @extends gtk::Grid, gtk::Widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Home {
|
impl Home {
|
||||||
pub fn new(api: CoreApi, view: HomeView) -> Home {
|
pub fn new(api: CoreApi, view: HomeView) -> Home {
|
||||||
let s: Self = Object::builder().build();
|
let s: Self = Object::builder().build();
|
||||||
s.set_spacing(4);
|
|
||||||
s.set_homogeneous(false);
|
|
||||||
s.set_orientation(gtk::Orientation::Vertical);
|
|
||||||
|
|
||||||
let players = gtk::Box::builder()
|
|
||||||
.spacing(4)
|
|
||||||
.orientation(gtk::Orientation::Horizontal)
|
|
||||||
.build();
|
|
||||||
s.append(&players);
|
|
||||||
|
|
||||||
let black_player = PlayerDataEntry::new(view.black_player);
|
let black_player = PlayerDataEntry::new(view.black_player);
|
||||||
players.append(&black_player);
|
s.attach(&black_player, 1, 1, 1, 1);
|
||||||
*s.imp().black_player.borrow_mut() = Some(black_player.clone());
|
*s.imp().black_player.borrow_mut() = Some(black_player.clone());
|
||||||
|
|
||||||
let white_player = PlayerDataEntry::new(view.white_player);
|
let white_player = PlayerDataEntry::new(view.white_player);
|
||||||
players.append(&white_player);
|
s.attach(&white_player, 2, 1, 1, 1);
|
||||||
*s.imp().white_player.borrow_mut() = Some(white_player.clone());
|
*s.imp().white_player.borrow_mut() = Some(white_player.clone());
|
||||||
|
|
||||||
let new_game_button = gtk::Button::builder().label(&view.start_game.label).build();
|
let new_game_button = gtk::Button::builder().label(&view.start_game.label).build();
|
||||||
s.append(&new_game_button);
|
s.attach(&new_game_button, 2, 2, 1, 1);
|
||||||
|
|
||||||
let library = GameDatabase::new();
|
let database = GameDatabase::new();
|
||||||
let library_view = gtk::ScrolledWindow::builder()
|
s.attach(&database, 0, 3, 2, 2);
|
||||||
.hscrollbar_policy(gtk::PolicyType::Never)
|
|
||||||
.min_content_width(360)
|
|
||||||
.vexpand(true)
|
|
||||||
.hexpand(true)
|
|
||||||
.child(&library)
|
|
||||||
.build();
|
|
||||||
s.append(&library_view);
|
|
||||||
|
|
||||||
library.set_games(view.games);
|
|
||||||
|
|
||||||
new_game_button.connect_clicked({
|
new_game_button.connect_clicked({
|
||||||
move |_| {
|
move |_| {
|
||||||
|
|
Loading…
Reference in New Issue