/* Copyright 2024, Savanni D'Gerinel 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 . */ use crate::{components::Library, CoreApi}; use glib::Object; use gtk::{glib, prelude::*, subclass::prelude::*}; use otg_core::{ library::{LibraryRequest, LibraryResponse}, CoreRequest, CoreResponse, }; use sgf::GameRecord; /* struct PlayerDataEntryPrivate { name: gtk::Text, rank: gtk::DropDown, } impl Default for PlayerDataEntryPrivate { fn default() -> Self { let rank = gtk::DropDown::builder().build(); Self { name: gtk::Text::builder().build(), rank, } } } #[glib::object_subclass] impl ObjectSubclass for PlayerDataEntryPrivate { const NAME: &'static str = "PlayerDataEntry"; type Type = PlayerDataEntry; type ParentType = gtk::Box; } impl ObjectImpl for PlayerDataEntryPrivate {} impl WidgetImpl for PlayerDataEntryPrivate {} impl BoxImpl for PlayerDataEntryPrivate {} glib::wrapper! { struct PlayerDataEntry(ObjectSubclass) @extends gtk::Box, gtk::Widget; } impl PlayerDataEntry { pub fn new(element: PlayerElement) -> PlayerDataEntry { let s: Self = Object::builder().build(); let rank_model = gio::ListStore::new::(); s.imp().rank.set_model(Some(&rank_model)); match element { PlayerElement::Hotseat(player) => { if let Some(placeholder) = player.placeholder { s.imp().name.set_placeholder_text(Some(&placeholder)); } player.ranks.iter().for_each(|rank| rank_model.append(>k::StringObject::new(rank))); } // PlayerElement::Remote(_) => s.imp().placeholder.set_text("remote player"), // PlayerElement::Bot(_) => s.imp().placeholder.set_text("bot player"), } s.append(&s.imp().name); s.append(&s.imp().rank); s } pub fn text(&self) -> String { let name = self.imp().name.buffer().text().to_string(); if name.is_empty() { self.imp() .name .placeholder_text() .map(|s| s.to_string()) .unwrap_or("".to_owned()) } else { name } } pub fn rank(&self) -> Option { self.imp().rank.selected_item().and_then(|obj| { let str_obj = obj.downcast::().ok()?; Some(str_obj.string().clone().to_string()) }) } } */ #[derive(Default)] pub struct HomePrivate { // black_player: Rc>>, // white_player: Rc>>, } #[glib::object_subclass] impl ObjectSubclass for HomePrivate { const NAME: &'static str = "Home"; type Type = HomeView; type ParentType = gtk::Box; } impl ObjectImpl for HomePrivate {} impl WidgetImpl for HomePrivate {} impl BoxImpl for HomePrivate {} glib::wrapper! { pub struct HomeView(ObjectSubclass) @extends gtk::Box, gtk::Widget, @implements gtk::Orientable, gtk::Accessible; } impl HomeView { pub fn new(api: CoreApi, on_select_game: impl Fn(GameRecord) + 'static) -> Self { let s: Self = Object::builder().build(); s.set_spacing(4); s.set_homogeneous(false); s.set_orientation(gtk::Orientation::Vertical); /* let players = gtk::Box::builder() .spacing(4) .orientation(gtk::Orientation::Horizontal) .build(); s.append(&players); let black_player = PlayerDataEntry::new(view.black_player); players.append(&black_player); *s.imp().black_player.borrow_mut() = Some(black_player.clone()); let white_player = PlayerDataEntry::new(view.white_player); players.append(&white_player); *s.imp().white_player.borrow_mut() = Some(white_player.clone()); let new_game_button = gtk::Button::builder() .css_classes(vec!["suggested-action"]) .label(&view.start_game.label) .build(); s.append(&new_game_button); */ let library = Library::new(on_select_game); let library_view = gtk::ScrolledWindow::builder() .hscrollbar_policy(gtk::PolicyType::Never) .min_content_width(360) .vexpand(true) .hexpand(true) .child(&library) .build(); s.append(&library_view); glib::spawn_future_local({ let library = library.clone(); let api = api.clone(); async move { if let CoreResponse::Library(LibraryResponse::Games(games)) = api .dispatch(CoreRequest::Library(LibraryRequest::ListGames)) .await { library.set_games(games); } } }); /* new_game_button.connect_clicked({ move |_| { let black_player = black_player.clone(); let white_player = white_player.clone(); api.dispatch(CoreRequest::CreateGame(CreateGameRequest { black_player: player_info(black_player.clone()), white_player: player_info(white_player.clone()), })); } }); */ s } } /* fn player_info(player: PlayerDataEntry) -> PlayerInfoRequest { PlayerInfoRequest::Hotseat(HotseatPlayerRequest { name: player.text(), rank: player.rank(), }) } */