Compare commits

..

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

6 changed files with 72 additions and 88 deletions

View File

@ -1,45 +1,36 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sgf::go::Game; use sgf::{
go::{Game, Rank},
Date,
};
use typeshare::typeshare; use typeshare::typeshare;
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
#[typeshare] #[typeshare]
pub struct GamePreviewElement { pub struct GamePreviewElement {
pub date: Vec<String>, pub date: Vec<Date>,
pub black_player: String, pub black_player: String,
pub black_rank: Option<Rank>,
pub white_player: String, pub white_player: String,
pub white_rank: Option<Rank>,
} }
impl GamePreviewElement { impl GamePreviewElement {
pub fn new(game: &Game) -> GamePreviewElement { pub fn new(game: &Game) -> GamePreviewElement {
let black_player = match game.info.black_player {
Some(ref black_player) => black_player.clone(),
None => "unknown".to_owned(),
};
let white_player = match game.info.white_player {
Some(ref white_player) => white_player.clone(),
None => "unknown".to_owned(),
};
let black_player = match game.info.black_rank {
Some(rank) => format!("{} ({})", black_player, rank.to_string()),
None => black_player,
};
let white_player = match game.info.white_rank {
Some(rank) => format!("{} ({})", white_player, rank.to_string()),
None => white_player,
};
GamePreviewElement { GamePreviewElement {
date: game date: game.info.date.clone(),
black_player: game
.info .info
.date .black_player
.iter() .clone()
.map(|dt| dt.to_string()) .unwrap_or("black_player".to_owned()),
.collect::<Vec<String>>(), black_rank: game.info.black_rank.clone(),
black_player, white_player: game
white_player, .info
.white_player
.clone()
.unwrap_or("white_player".to_owned()),
white_rank: game.info.white_rank.clone(),
} }
} }
} }

View File

@ -1,4 +1,3 @@
use crate::ui::GamePreview;
use glib::Object; use glib::Object;
use gtk::{glib, prelude::*, subclass::prelude::*}; use gtk::{glib, prelude::*, subclass::prelude::*};
use kifu_core::ui::GamePreviewElement; use kifu_core::ui::GamePreviewElement;
@ -33,12 +32,12 @@ impl GameObject {
} }
} }
pub struct LibraryPrivate { pub struct GameDatabasePrivate {
model: gio::ListStore, model: gio::ListStore,
list_view: gtk::ListView, list_view: gtk::ListView,
} }
impl Default for LibraryPrivate { impl Default for GameDatabasePrivate {
fn default() -> Self { fn default() -> Self {
let vector: Vec<GameObject> = vec![]; let vector: Vec<GameObject> = vec![];
let model = gio::ListStore::new(glib::types::Type::OBJECT); let model = gio::ListStore::new(glib::types::Type::OBJECT);
@ -46,59 +45,69 @@ impl Default for LibraryPrivate {
let factory = gtk::SignalListItemFactory::new(); let factory = gtk::SignalListItemFactory::new();
factory.connect_setup(move |_, list_item| { factory.connect_setup(move |_, list_item| {
let preview = GamePreview::new(); let label = gtk::Label::new(Some("some kind of text"));
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(&preview)); .set_child(Some(&label));
}); });
factory.connect_bind(move |_, list_item| { factory.connect_bind(move |_, list_item| {
let game_element = list_item let game_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::<GameObject>()
.expect("The item has to be a GameObject."); .expect("The item has to be an IntegerObject.");
let preview = list_item let label = list_item
.downcast_ref::<gtk::ListItem>() .downcast_ref::<gtk::ListItem>()
.expect("Needs to be ListItem") .expect("Needs to be ListItem")
.child() .child()
.and_downcast::<GamePreview>() .and_downcast::<gtk::Label>()
.expect("The child has to be a GamePreview object."); .expect("The child has to be an Label.");
match game_element.game() { label.set_label(
Some(game) => preview.set_game(game), format!(
None => (), "{} 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::NoSelection::new(Some(model.clone()));
let list_view = gtk::ListView::new(Some(selection_model), Some(factory)); let list_view = gtk::ListView::new(Some(selection_model), Some(factory));
list_view.set_hexpand(true);
Self { model, list_view } Self { model, list_view }
} }
} }
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for LibraryPrivate { impl ObjectSubclass for GameDatabasePrivate {
const NAME: &'static str = "Library"; const NAME: &'static str = "GameDatabase";
type Type = Library; type Type = GameDatabase;
type ParentType = gtk::Box; type ParentType = gtk::Box;
} }
impl ObjectImpl for LibraryPrivate {} impl ObjectImpl for GameDatabasePrivate {}
impl WidgetImpl for LibraryPrivate {} impl WidgetImpl for GameDatabasePrivate {}
impl BoxImpl for LibraryPrivate {} impl BoxImpl for GameDatabasePrivate {}
glib::wrapper! { glib::wrapper! {
pub struct Library(ObjectSubclass<LibraryPrivate>) @extends gtk::Widget, gtk::Box; pub struct GameDatabase(ObjectSubclass<GameDatabasePrivate>) @extends gtk::Widget, gtk::Box;
} }
impl Library { impl GameDatabase {
pub fn new() -> Self { pub fn new() -> Self {
let s: Self = Object::builder().build(); let s: Self = Object::builder().build();
s.set_hexpand(true); s.set_width_request(200);
s.set_height_request(200);
s.append(&s.imp().list_view); s.append(&s.imp().list_view);
s s
} }

View File

@ -3,12 +3,7 @@ use gtk::{glib, prelude::*, subclass::prelude::*};
use kifu_core::ui::GamePreviewElement; use kifu_core::ui::GamePreviewElement;
#[derive(Default)] #[derive(Default)]
pub struct GamePreviewPrivate { pub struct GamePreviewPrivate;
title: gtk::Label,
black_player: gtk::Label,
white_player: gtk::Label,
date: gtk::Label,
}
#[glib::object_subclass] #[glib::object_subclass]
impl ObjectSubclass for GamePreviewPrivate { impl ObjectSubclass for GamePreviewPrivate {
@ -26,25 +21,22 @@ glib::wrapper! {
} }
impl GamePreview { impl GamePreview {
pub fn new() -> GamePreview { pub fn new(element: GamePreviewElement) -> GamePreview {
let s: Self = Object::builder().build(); let s: Self = Object::builder().build();
s.set_orientation(gtk::Orientation::Horizontal); s.set_orientation(gtk::Orientation::Horizontal);
s.set_homogeneous(true);
s.set_hexpand(true);
s.append(&s.imp().date); println!("game_preview: {:?}", element);
s.append(&s.imp().title); let black_player = match element.black_rank {
s.append(&s.imp().black_player); Some(rank) => format!("{} ({})", element.black_player, rank.to_string()),
s.append(&s.imp().white_player); None => element.black_player,
};
let white_player = match element.white_rank {
Some(rank) => format!("{} ({})", element.white_player, rank.to_string()),
None => element.white_player,
};
s.append(&gtk::Label::new(Some(&black_player)));
s.append(&gtk::Label::new(Some(&white_player)));
s s
} }
pub fn set_game(&self, element: GamePreviewElement) {
self.imp().black_player.set_text(&element.black_player);
self.imp().white_player.set_text(&element.white_player);
if let Some(date) = element.date.first() {
self.imp().date.set_text(&date);
}
}
} }

View File

@ -1,4 +1,4 @@
use crate::{ui::Library, CoreApi}; use crate::CoreApi;
use glib::Object; use glib::Object;
use gtk::{glib, prelude::*, subclass::prelude::*}; use gtk::{glib, prelude::*, subclass::prelude::*};
use kifu_core::{ use kifu_core::{
@ -7,6 +7,8 @@ use kifu_core::{
}; };
use std::{cell::RefCell, rc::Rc}; use std::{cell::RefCell, rc::Rc};
use super::GameDatabase;
struct PlayerDataEntryPrivate { struct PlayerDataEntryPrivate {
name: gtk::Text, name: gtk::Text,
rank: gtk::DropDown, rank: gtk::DropDown,
@ -134,7 +136,7 @@ impl Home {
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.append(&new_game_button);
let library = Library::new(); let library = GameDatabase::new();
let library_view = gtk::ScrolledWindow::builder() let library_view = gtk::ScrolledWindow::builder()
.hscrollbar_policy(gtk::PolicyType::Never) .hscrollbar_policy(gtk::PolicyType::Never)
.min_content_width(360) .min_content_width(360)

View File

@ -1,12 +1,12 @@
mod chat; mod chat;
pub use chat::Chat; pub use chat::Chat;
mod game_database;
pub use game_database::GameDatabase;
mod game_preview; mod game_preview;
pub use game_preview::GamePreview; pub use game_preview::GamePreview;
mod library;
pub use library::Library;
mod player_card; mod player_card;
pub use player_card::PlayerCard; pub use player_card::PlayerCard;

View File

@ -24,16 +24,6 @@ pub enum Date {
Date(chrono::NaiveDate), Date(chrono::NaiveDate),
} }
impl Date {
pub fn to_string(&self) -> String {
match self {
Date::Year(y) => format!("{}", y),
Date::YearMonth(y, m) => format!("{}-{}", y, m),
Date::Date(date) => format!("{}-{}-{}", date.year(), date.month(), date.day()),
}
}
}
/* /*
impl TryFrom<&str> for Date { impl TryFrom<&str> for Date {
type Error = String; type Error = String;