use crate::{ perftrace, ui::{Board, Chat, PlayerCard}, CoreApi, }; use glib::Object; use gtk::{prelude::*, subclass::prelude::*}; use kifu_core::{ ui::{ BoardElement, ChatElement, IntersectionElement, PlayerCardElement, PlayingFieldView, StoneElement, TextFieldElement, }, Color, CoreApp, Size, }; use std::{cell::RefCell, rc::Rc}; pub struct PlayingFieldPrivate { board: Rc>>, player_card_white: Rc>>, player_card_black: Rc>>, chat: Rc>>, } impl Default for PlayingFieldPrivate { fn default() -> Self { Self { board: Default::default(), player_card_white: Rc::new(RefCell::new(None)), player_card_black: Rc::new(RefCell::new(None)), chat: Rc::new(RefCell::new(None)), } } } #[glib::object_subclass] impl ObjectSubclass for PlayingFieldPrivate { const NAME: &'static str = "PlayingField"; type Type = PlayingField; type ParentType = gtk::Grid; } impl ObjectImpl for PlayingFieldPrivate {} impl WidgetImpl for PlayingFieldPrivate {} impl GridImpl for PlayingFieldPrivate {} glib::wrapper! { pub struct PlayingField(ObjectSubclass) @extends gtk::Grid, gtk::Widget; } impl PlayingField { pub fn new(api: CoreApi, view: PlayingFieldView) -> PlayingField { let s: Self = Object::builder().build(); let player_card_white = PlayerCard::new(view.player_card_white); let player_card_black = PlayerCard::new(view.player_card_black); let chat = Chat::new(view.chat); *s.imp().board.borrow_mut() = Some(Board::new(api)); s.imp() .board .borrow() .as_ref() .map(|board| s.attach(board, 1, 1, 1, 2)); s.attach(&player_card_black, 2, 1, 1, 1); s.attach(&player_card_white, 3, 1, 1, 1); s.attach(&chat, 2, 2, 2, 1); *s.imp().player_card_white.borrow_mut() = Some(player_card_white); *s.imp().player_card_black.borrow_mut() = Some(player_card_black); *s.imp().chat.borrow_mut() = Some(chat); s.imp().board.borrow().as_ref().map(|board| { board.set_board(view.board); board.set_current_player(view.current_player); }); s } pub fn update_view(&self, view: PlayingFieldView) { perftrace("update_view", || { self.imp().board.borrow().as_ref().map(|board| { board.set_board(view.board); board.set_current_player(view.current_player); }); }) } } #[cfg(feature = "screenplay")] pub fn playing_field_view() -> PlayingFieldView { let mut board = BoardElement::new(Size { width: 19, height: 19, }); *board.stone_mut(4, 4) = IntersectionElement::Filled(StoneElement::new(Color::White, None)); *board.stone_mut(15, 15) = IntersectionElement::Filled(StoneElement::new(Color::Black, None)); *board.stone_mut(18, 18) = IntersectionElement::Unplayable; let player_card_black = PlayerCardElement { color: Color::Black, name: "Savanni".to_owned(), rank: "10k".to_owned(), clock: "24:53".to_owned(), }; let player_card_white = PlayerCardElement { color: Color::White, name: "Opal".to_owned(), rank: "10k".to_owned(), clock: "25:00".to_owned(), }; let chat = ChatElement { messages: vec![ "[22:05] Savanni: oops".to_owned(), "[22:06] Opal: you know I'll take advantage of that, right?".to_owned(), ], }; let message = TextFieldElement {}; PlayingFieldView { board, player_card_black, player_card_white, chat, message, current_player: Color::White, } }