87 lines
2.9 KiB
Rust
87 lines
2.9 KiB
Rust
|
/*
|
||
|
Copyright 2024, Savanni D'Gerinel <savanni@luminescent-dreams.com>
|
||
|
|
||
|
This file is part of Kifu.
|
||
|
|
||
|
Kifu is free software: you can redistribute it and/or modify it under the terms of the GNU
|
||
|
General Public License as published by the Free Software Foundation, either version 3 of the
|
||
|
License, or (at your option) any later version.
|
||
|
|
||
|
Kifu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||
|
even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License along with Kifu. If not, see <https://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
use async_channel::Receiver;
|
||
|
use async_std::task::{spawn, yield_now, JoinHandle};
|
||
|
use kifu_core::{Color, Core, CoreNotification, Goban, Player};
|
||
|
use std::{
|
||
|
sync::{Arc, RwLock},
|
||
|
time::Duration,
|
||
|
};
|
||
|
|
||
|
struct GameViewModelPrivate {
|
||
|
white: Player, /* Maybe this should be PlayerState, instead, combining the player info, current clock, and current captures. */
|
||
|
black: Player,
|
||
|
current: Color,
|
||
|
goban: Goban, /* Or perhaps clocks, captures, and the board should be bound into GameState. */
|
||
|
white_clock: Duration,
|
||
|
black_clock: Duration,
|
||
|
}
|
||
|
|
||
|
/// The Game View Model manages the current state of the game. It shows the two player cards, the board, the current capture count, the current player, and it maintains the UI for the clock (bearing in mind that the real clock is managed in the core). This view model should only be created once the details of the game, whether a game in progress or a new game (this view model won't know the difference) is known.
|
||
|
pub struct GameViewModel {
|
||
|
core: Core,
|
||
|
notification_handler: JoinHandle<()>,
|
||
|
widget: gtk::Box,
|
||
|
data: Arc<RwLock<GameViewModelPrivate>>,
|
||
|
}
|
||
|
|
||
|
impl GameViewModelPrivate {
|
||
|
fn handle(&mut self, message: CoreNotification) {}
|
||
|
}
|
||
|
|
||
|
impl GameViewModel {
|
||
|
pub fn new(
|
||
|
white: Player,
|
||
|
black: Player,
|
||
|
current: Color,
|
||
|
goban: Goban,
|
||
|
white_clock: Duration,
|
||
|
black_clock: Duration,
|
||
|
core: Core,
|
||
|
notifications: Receiver<CoreNotification>,
|
||
|
) -> Self {
|
||
|
let data = Arc::new(RwLock::new(GameViewModelPrivate {
|
||
|
white,
|
||
|
black,
|
||
|
current,
|
||
|
goban,
|
||
|
white_clock,
|
||
|
black_clock,
|
||
|
}));
|
||
|
|
||
|
let handler = spawn({
|
||
|
let data = data.clone();
|
||
|
async move {
|
||
|
loop {
|
||
|
match notifications.recv().await {
|
||
|
Ok(msg) => data.write().unwrap().handle(msg),
|
||
|
Err(err) => unimplemented!("Should display an error message in the UI"),
|
||
|
}
|
||
|
yield_now().await;
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
Self {
|
||
|
core,
|
||
|
notification_handler: handler,
|
||
|
widget: gtk::Box::new(gtk::Orientation::Horizontal, 0),
|
||
|
data,
|
||
|
}
|
||
|
}
|
||
|
}
|