Compare commits

..

No commits in common. "a584fb4de374dcedaebac22fa0fa4b3927b9aad9" and "07b73515013ec92eab3bdd57b8a9d330ad722600" have entirely different histories.

6 changed files with 84 additions and 81 deletions

2
Cargo.lock generated
View File

@ -1348,7 +1348,7 @@ dependencies = [
"gtk4", "gtk4",
"image", "image",
"kifu-core", "kifu-core",
"sgf", "screenplay",
"tokio", "tokio",
] ]

View File

@ -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 }
} }

View File

@ -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"

View File

@ -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();

View File

@ -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);
}
} }

View File

@ -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 |_| {