monorepo/otg/gtk/src/views/game_review.rs

131 lines
4.5 KiB
Rust
Raw Normal View History

/*
Copyright 2024, Savanni D'Gerinel <savanni@luminescent-dreams.com>
This file is part of On the Grid.
On the Grid 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.
On the Grid 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 On the Grid. If not, see <https://www.gnu.org/licenses/>.
*/
// Game review consists of the board, some information about the players, the game tree, and any
// commentary on the current move. This requires four major components, some of which are easier
// than others. The game board has to be kept in sync with the game tree, so there's a
// communication channel there.
//
// I'll get all of the information about the game from the core, and then render everything in the
// UI. So this will be a heavy lift on the UI side.
use crate::{components::{Goban, PlayerCard, ReviewTree}, ResourceManager};
use gtk::{prelude::*};
use otg_core::{Color, GameReviewViewModel};
/*
2024-03-26 12:53:24 +00:00
#[derive(Default)]
pub struct GameReviewPrivate {
model: Rc<RefCell<Option<GameReviewViewModel>>>,
}
#[glib::object_subclass]
impl ObjectSubclass for GameReviewPrivate {
const NAME: &'static str = "GameReview";
type Type = GameReview;
2024-03-24 01:57:56 +00:00
type ParentType = gtk::Box;
}
impl ObjectImpl for GameReviewPrivate {}
impl WidgetImpl for GameReviewPrivate {}
2024-03-24 01:57:56 +00:00
impl BoxImpl for GameReviewPrivate {}
glib::wrapper! {
2024-03-24 01:57:56 +00:00
pub struct GameReview(ObjectSubclass<GameReviewPrivate>) @extends gtk::Box, gtk::Widget, @implements gtk::Accessible;
}
impl GameReview {
2024-04-05 14:47:16 +00:00
pub fn new(_api: CoreApi, record: GameRecord, resources: ResourceManager) -> Self {
let s: Self = Object::builder().build();
s
}
}
*/
pub struct GameReview {
widget: gtk::Box,
resources: ResourceManager,
view: GameReviewViewModel,
}
impl GameReview {
pub fn new(view: GameReviewViewModel, resources: ResourceManager) -> Self {
let widget = gtk::Box::builder().build();
let s = Self {
widget,
resources,
view,
};
s.render();
s
}
fn render(&self) {
// It's actually really bad to be just throwing away errors. Panics make everyone unhappy.
// This is not a fatal error, so I'll replace this `unwrap` call with something that
// renders the board and notifies the user of a problem that cannot be resolved.
let board_repr = self.view.game_view();
let board = Goban::new(board_repr, self.resources.clone());
2024-03-24 01:57:56 +00:00
/*
s.attach(&board, 0, 0, 2, 2);
s.attach(&gtk::Label::new(Some("white player")), 0, 2, 1, 1);
s.attach(&gtk::Label::new(Some("black player")), 0, 2, 1, 2);
s.attach(&gtk::Label::new(Some("chat")), 1, 2, 2, 2);
2024-03-24 01:57:56 +00:00
*/
let sidebar = gtk::Box::builder()
.orientation(gtk::Orientation::Vertical)
.spacing(4)
.build();
// The review tree needs to know the record for being able to render all of the nodes. Once
// keyboard input is being handled, the tree will have to be updated on each keystroke in
// order to show the user where they are within the game record.
let review_tree = ReviewTree::new(self.view.clone());
// I think most keyboard focus is going to end up being handled here in GameReview, as
// keystrokes need to affect both the goban and the review tree simultanesouly. Possibly
// also the player information, seeing as moving to a new position may mean that the score
// and time remaining can be updated.
let player_information_section = gtk::Box::builder()
.orientation(gtk::Orientation::Horizontal)
.spacing(4)
.build();
player_information_section
.append(&PlayerCard::new(Color::Black, &self.view.black_player()));
player_information_section
.append(&PlayerCard::new(Color::White, &self.view.white_player()));
self.widget.append(&board);
sidebar.append(&player_information_section);
sidebar.append(&review_tree.widget());
self.widget.append(&sidebar);
}
pub fn widget(&self) -> gtk::Widget {
self.widget.clone().upcast::<gtk::Widget>()
}
}