Start on the game review window
This commit is contained in:
parent
1489121877
commit
56b6c187c7
|
@ -1,6 +1,9 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
types::{AppState, Config, ConfigOption, DatabasePath, GameState, Player, Rank},
|
types::{AppState, Config, ConfigOption, DatabasePath, GameState, Player, Rank},
|
||||||
ui::{configuration, home, playing_field, ConfigurationView, HomeView, PlayingFieldView},
|
ui::{
|
||||||
|
configuration, home, playing_field, review, ConfigurationView, GameReviewView, HomeView,
|
||||||
|
PlayingFieldView,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -17,11 +20,27 @@ pub enum CoreRequest {
|
||||||
CreateGame(CreateGameRequest),
|
CreateGame(CreateGameRequest),
|
||||||
Home,
|
Home,
|
||||||
OpenConfiguration,
|
OpenConfiguration,
|
||||||
|
OpenGameReview,
|
||||||
PlayingField,
|
PlayingField,
|
||||||
PlayStone(PlayStoneRequest),
|
PlayStone(PlayStoneRequest),
|
||||||
StartGame,
|
StartGame,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[typeshare]
|
||||||
|
#[serde(tag = "type", content = "content")]
|
||||||
|
pub enum CoreResponse {
|
||||||
|
ConfigurationView(ConfigurationView),
|
||||||
|
HomeView(HomeView),
|
||||||
|
GameReview(GameReviewView),
|
||||||
|
PlayingFieldView(PlayingFieldView),
|
||||||
|
UpdatedConfigurationView(ConfigurationView),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
#[typeshare]
|
||||||
|
pub struct GameId(String);
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
#[typeshare]
|
#[typeshare]
|
||||||
#[serde(tag = "type", content = "content")]
|
#[serde(tag = "type", content = "content")]
|
||||||
|
@ -65,16 +84,6 @@ impl From<HotseatPlayerRequest> for Player {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
||||||
#[typeshare]
|
|
||||||
#[serde(tag = "type", content = "content")]
|
|
||||||
pub enum CoreResponse {
|
|
||||||
ConfigurationView(ConfigurationView),
|
|
||||||
HomeView(HomeView),
|
|
||||||
PlayingFieldView(PlayingFieldView),
|
|
||||||
UpdatedConfigurationView(ConfigurationView),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct CoreApp {
|
pub struct CoreApp {
|
||||||
config: Arc<RwLock<Config>>,
|
config: Arc<RwLock<Config>>,
|
||||||
|
@ -131,6 +140,7 @@ impl CoreApp {
|
||||||
CoreRequest::OpenConfiguration => {
|
CoreRequest::OpenConfiguration => {
|
||||||
CoreResponse::ConfigurationView(configuration(&self.config.read().unwrap()))
|
CoreResponse::ConfigurationView(configuration(&self.config.read().unwrap()))
|
||||||
}
|
}
|
||||||
|
CoreRequest::OpenGameReview => CoreResponse::GameReview(review()),
|
||||||
CoreRequest::PlayingField => {
|
CoreRequest::PlayingField => {
|
||||||
let app_state = self.state.read().unwrap();
|
let app_state = self.state.read().unwrap();
|
||||||
let game = app_state.game.as_ref().unwrap();
|
let game = app_state.game.as_ref().unwrap();
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
use crate::Color;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use sgf::go::Game;
|
||||||
|
use typeshare::typeshare;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[typeshare]
|
||||||
|
pub struct GameReviewView {
|
||||||
|
pub black_player: String,
|
||||||
|
pub white_player: String,
|
||||||
|
pub tree: Node,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[typeshare]
|
||||||
|
pub struct Position {
|
||||||
|
pub column: u8,
|
||||||
|
pub row: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[typeshare]
|
||||||
|
pub struct Node {
|
||||||
|
pub color: Color,
|
||||||
|
pub position: Position,
|
||||||
|
pub children: Vec<Node>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn review() -> GameReviewView {
|
||||||
|
GameReviewView {
|
||||||
|
black_player: "savanni".to_owned(),
|
||||||
|
white_player: "kat".to_owned(),
|
||||||
|
tree: Node {
|
||||||
|
color: Color::Black,
|
||||||
|
position: Position { column: 3, row: 3 },
|
||||||
|
children: vec![Node {
|
||||||
|
color: Color::White,
|
||||||
|
position: Position {
|
||||||
|
column: 15,
|
||||||
|
row: 15,
|
||||||
|
},
|
||||||
|
children: vec![Node {
|
||||||
|
color: Color::Black,
|
||||||
|
position: Position { column: 15, row: 3 },
|
||||||
|
children: vec![],
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,9 @@ pub use configuration::{configuration, ConfigurationView};
|
||||||
mod elements;
|
mod elements;
|
||||||
pub use elements::{game_preview::GamePreviewElement, menu::Menu, Action, Field, Toggle};
|
pub use elements::{game_preview::GamePreviewElement, menu::Menu, Action, Field, Toggle};
|
||||||
|
|
||||||
|
mod game_review;
|
||||||
|
pub use game_review::{review, GameReviewView};
|
||||||
|
|
||||||
mod playing_field;
|
mod playing_field;
|
||||||
pub use playing_field::{playing_field, PlayingFieldView};
|
pub use playing_field::{playing_field, PlayingFieldView};
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use adw::prelude::*;
|
||||||
use kifu_core::{CoreApp, CoreRequest, CoreResponse};
|
use kifu_core::{CoreApp, CoreRequest, CoreResponse};
|
||||||
use kifu_gtk::{
|
use kifu_gtk::{
|
||||||
perftrace,
|
perftrace,
|
||||||
ui::{AppWindow, ConfigurationPage, Home, PlayingField},
|
ui::{AppWindow, ConfigurationPage, GameReview, Home, PlayingField},
|
||||||
CoreApi,
|
CoreApi,
|
||||||
};
|
};
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
@ -18,6 +18,9 @@ fn handle_response(api: CoreApi, app_window: &AppWindow, message: CoreResponse)
|
||||||
window.set_visible_page(&config_page);
|
window.set_visible_page(&config_page);
|
||||||
window.present();
|
window.present();
|
||||||
}),
|
}),
|
||||||
|
CoreResponse::GameReview(view) => perftrace("GameReview", || {
|
||||||
|
app_window.set_content(&GameReview::new(api, view));
|
||||||
|
}),
|
||||||
CoreResponse::HomeView(view) => perftrace("HomeView", || {
|
CoreResponse::HomeView(view) => perftrace("HomeView", || {
|
||||||
let api = api.clone();
|
let api = api.clone();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
use crate::{ui::Board, CoreApi};
|
||||||
|
use glib::Object;
|
||||||
|
use gtk::{prelude::*, subclass::prelude::*};
|
||||||
|
use kifu_core::ui::GameReviewView;
|
||||||
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct GameReviewPrivate {
|
||||||
|
board: Rc<RefCell<Option<Board>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[glib::object_subclass]
|
||||||
|
impl ObjectSubclass for GameReviewPrivate {
|
||||||
|
const NAME: &'static str = "GameReview";
|
||||||
|
type Type = GameReview;
|
||||||
|
type ParentType = gtk::Box;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ObjectImpl for GameReviewPrivate {}
|
||||||
|
impl WidgetImpl for GameReviewPrivate {}
|
||||||
|
impl BoxImpl for GameReviewPrivate {}
|
||||||
|
|
||||||
|
glib::wrapper! {
|
||||||
|
pub struct GameReview(ObjectSubclass<GameReviewPrivate>)
|
||||||
|
@extends gtk::Box, gtk::Widget,
|
||||||
|
@implements gtk::Orientable;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GameReview {
|
||||||
|
pub fn new(api: CoreApi, view: GameReviewView) -> Self {
|
||||||
|
let s: Self = Object::builder().build();
|
||||||
|
|
||||||
|
s
|
||||||
|
}
|
||||||
|
}
|
|
@ -137,7 +137,7 @@ impl Home {
|
||||||
.build();
|
.build();
|
||||||
s.append(&new_game_button);
|
s.append(&new_game_button);
|
||||||
|
|
||||||
let library = Library::new();
|
let library = Library::new(api.clone());
|
||||||
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)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::ui::GamePreview;
|
use crate::{ui::GamePreview, CoreApi};
|
||||||
use adw::{prelude::*, subclass::prelude::*};
|
use adw::{prelude::*, subclass::prelude::*};
|
||||||
use glib::Object;
|
use glib::Object;
|
||||||
use gtk::{glib, prelude::*, subclass::prelude::*};
|
use gtk::{glib, prelude::*, subclass::prelude::*};
|
||||||
|
@ -45,38 +45,6 @@ impl Default for LibraryPrivate {
|
||||||
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();
|
|
||||||
|
|
||||||
factory.connect_setup(move |_, list_item| {
|
|
||||||
let preview = GamePreview::new();
|
|
||||||
list_item
|
|
||||||
.downcast_ref::<gtk::ListItem>()
|
|
||||||
.expect("Needs to be a ListItem")
|
|
||||||
.set_child(Some(&preview));
|
|
||||||
});
|
|
||||||
factory.connect_bind(move |_, list_item| {
|
|
||||||
let game_element = list_item
|
|
||||||
.downcast_ref::<gtk::ListItem>()
|
|
||||||
.expect("Needs to be ListItem")
|
|
||||||
.item()
|
|
||||||
.and_downcast::<GameObject>()
|
|
||||||
.expect("The item has to be a GameObject.");
|
|
||||||
|
|
||||||
let preview = list_item
|
|
||||||
.downcast_ref::<gtk::ListItem>()
|
|
||||||
.expect("Needs to be ListItem")
|
|
||||||
.child()
|
|
||||||
.and_downcast::<GamePreview>()
|
|
||||||
.expect("The child has to be a GamePreview object.");
|
|
||||||
|
|
||||||
match game_element.game() {
|
|
||||||
Some(game) => preview.set_game(game),
|
|
||||||
None => (),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
let selection_model = gtk::NoSelection::new(Some(model.clone()));
|
let selection_model = gtk::NoSelection::new(Some(model.clone()));
|
||||||
let list_view = gtk::ColumnView::builder().model(&selection_model).build();
|
let list_view = gtk::ColumnView::builder().model(&selection_model).build();
|
||||||
|
|
||||||
|
@ -86,15 +54,15 @@ impl Default for LibraryPrivate {
|
||||||
{
|
{
|
||||||
let factory = gtk::SignalListItemFactory::new();
|
let factory = gtk::SignalListItemFactory::new();
|
||||||
factory.connect_setup(|_, list_item| {
|
factory.connect_setup(|_, list_item| {
|
||||||
list_item
|
let item = list_item.downcast_ref::<gtk::ListItem>().unwrap();
|
||||||
.downcast_ref::<gtk::ListItem>()
|
|
||||||
.unwrap()
|
item.set_activatable(true);
|
||||||
.set_child(Some(
|
item.set_child(Some(
|
||||||
>k::Label::builder()
|
>k::Label::builder()
|
||||||
.halign(gtk::Align::Start)
|
.halign(gtk::Align::Start)
|
||||||
.ellipsize(pango::EllipsizeMode::End)
|
.ellipsize(pango::EllipsizeMode::End)
|
||||||
.build(),
|
.build(),
|
||||||
))
|
))
|
||||||
});
|
});
|
||||||
factory.connect_bind(move |_, list_item| {
|
factory.connect_bind(move |_, list_item| {
|
||||||
let list_item = list_item.downcast_ref::<gtk::ListItem>().unwrap();
|
let list_item = list_item.downcast_ref::<gtk::ListItem>().unwrap();
|
||||||
|
@ -149,10 +117,13 @@ glib::wrapper! {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Library {
|
impl Library {
|
||||||
pub fn new() -> Self {
|
pub fn new(api: CoreApi) -> Self {
|
||||||
let s: Self = Object::builder().build();
|
let s: Self = Object::builder().build();
|
||||||
|
|
||||||
s.set_child(Some(&s.imp().list_view));
|
s.set_child(Some(&s.imp().list_view));
|
||||||
|
s.imp().list_view.connect_activate(move |list, row_id| {
|
||||||
|
api.dispatch(kifu_core::CoreRequest::OpenGameReview);
|
||||||
|
});
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,9 @@ use gio::resources_lookup_data;
|
||||||
use glib::IsA;
|
use glib::IsA;
|
||||||
use gtk::{prelude::*, STYLE_PROVIDER_PRIORITY_USER};
|
use gtk::{prelude::*, STYLE_PROVIDER_PRIORITY_USER};
|
||||||
|
|
||||||
|
mod board;
|
||||||
|
pub use board::Board;
|
||||||
|
|
||||||
mod chat;
|
mod chat;
|
||||||
pub use chat::Chat;
|
pub use chat::Chat;
|
||||||
|
|
||||||
|
@ -12,6 +15,12 @@ pub use config::ConfigurationPage;
|
||||||
mod game_preview;
|
mod game_preview;
|
||||||
pub use game_preview::GamePreview;
|
pub use game_preview::GamePreview;
|
||||||
|
|
||||||
|
mod game_review;
|
||||||
|
pub use game_review::GameReview;
|
||||||
|
|
||||||
|
mod home;
|
||||||
|
pub use home::Home;
|
||||||
|
|
||||||
mod library;
|
mod library;
|
||||||
pub use library::Library;
|
pub use library::Library;
|
||||||
|
|
||||||
|
@ -21,11 +30,8 @@ pub use player_card::PlayerCard;
|
||||||
mod playing_field;
|
mod playing_field;
|
||||||
pub use playing_field::PlayingField;
|
pub use playing_field::PlayingField;
|
||||||
|
|
||||||
mod home;
|
mod review_tree;
|
||||||
pub use home::Home;
|
pub use review_tree::ReviewTree;
|
||||||
|
|
||||||
mod board;
|
|
||||||
pub use board::Board;
|
|
||||||
|
|
||||||
#[cfg(feature = "screenplay")]
|
#[cfg(feature = "screenplay")]
|
||||||
pub use playing_field::playing_field_view;
|
pub use playing_field::playing_field_view;
|
||||||
|
|
|
@ -12,7 +12,7 @@ pub struct PlayingFieldPrivate {
|
||||||
board: Rc<RefCell<Option<Board>>>,
|
board: Rc<RefCell<Option<Board>>>,
|
||||||
player_card_white: Rc<RefCell<Option<PlayerCard>>>,
|
player_card_white: Rc<RefCell<Option<PlayerCard>>>,
|
||||||
player_card_black: Rc<RefCell<Option<PlayerCard>>>,
|
player_card_black: Rc<RefCell<Option<PlayerCard>>>,
|
||||||
chat: Rc<RefCell<Option<Chat>>>,
|
// chat: Rc<RefCell<Option<Chat>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PlayingFieldPrivate {
|
impl Default for PlayingFieldPrivate {
|
||||||
|
@ -21,7 +21,7 @@ impl Default for PlayingFieldPrivate {
|
||||||
board: Default::default(),
|
board: Default::default(),
|
||||||
player_card_white: Rc::new(RefCell::new(None)),
|
player_card_white: Rc::new(RefCell::new(None)),
|
||||||
player_card_black: Rc::new(RefCell::new(None)),
|
player_card_black: Rc::new(RefCell::new(None)),
|
||||||
chat: Rc::new(RefCell::new(None)),
|
// chat: Rc::new(RefCell::new(None)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ impl PlayingField {
|
||||||
|
|
||||||
let player_card_white = PlayerCard::new(view.player_card_white);
|
let player_card_white = PlayerCard::new(view.player_card_white);
|
||||||
let player_card_black = PlayerCard::new(view.player_card_black);
|
let player_card_black = PlayerCard::new(view.player_card_black);
|
||||||
let chat = Chat::new(view.chat);
|
// let chat = Chat::new(view.chat);
|
||||||
|
|
||||||
*s.imp().board.borrow_mut() = Some(Board::new(api));
|
*s.imp().board.borrow_mut() = Some(Board::new(api));
|
||||||
s.imp()
|
s.imp()
|
||||||
|
@ -57,11 +57,11 @@ impl PlayingField {
|
||||||
.map(|board| s.attach(board, 1, 1, 1, 2));
|
.map(|board| s.attach(board, 1, 1, 1, 2));
|
||||||
s.attach(&player_card_black, 2, 1, 1, 1);
|
s.attach(&player_card_black, 2, 1, 1, 1);
|
||||||
s.attach(&player_card_white, 3, 1, 1, 1);
|
s.attach(&player_card_white, 3, 1, 1, 1);
|
||||||
s.attach(&chat, 2, 2, 2, 1);
|
// s.attach(&chat, 2, 2, 2, 1);
|
||||||
|
|
||||||
*s.imp().player_card_white.borrow_mut() = Some(player_card_white);
|
*s.imp().player_card_white.borrow_mut() = Some(player_card_white);
|
||||||
*s.imp().player_card_black.borrow_mut() = Some(player_card_black);
|
*s.imp().player_card_black.borrow_mut() = Some(player_card_black);
|
||||||
*s.imp().chat.borrow_mut() = Some(chat);
|
// *s.imp().chat.borrow_mut() = Some(chat);
|
||||||
|
|
||||||
s.imp().board.borrow().as_ref().map(|board| {
|
s.imp().board.borrow().as_ref().map(|board| {
|
||||||
board.set_board(view.board);
|
board.set_board(view.board);
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
use adw::{prelude::*, subclass::prelude::*};
|
||||||
|
use glib::Object;
|
||||||
|
use std::{cell::Cell, rc::Rc};
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ReviewTreePrivate {}
|
||||||
|
|
||||||
|
#[glib::object_subclass]
|
||||||
|
impl ObjectSubclass for ReviewTreePrivate {
|
||||||
|
const NAME: &'static str = "ReviewTree";
|
||||||
|
type Type = ReviewTree;
|
||||||
|
type ParentType = adw::Bin;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ObjectImpl for ReviewTreePrivate {}
|
||||||
|
impl WidgetImpl for ReviewTreePrivate {}
|
||||||
|
impl BinImpl for ReviewTreePrivate {}
|
||||||
|
|
||||||
|
glib::wrapper! {
|
||||||
|
pub struct ReviewTree(ObjectSubclass<ReviewTreePrivate>)
|
||||||
|
@extends adw::Bin, gtk::Widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReviewTree {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let s: Self = Object::builder().build();
|
||||||
|
|
||||||
|
s
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue