Set up a configuration UI #66

Merged
savanni merged 7 commits from kifu/configuration into main 2023-08-25 01:08:33 +00:00
7 changed files with 86 additions and 11 deletions
Showing only changes of commit 793cd67218 - Show all commits

View File

@ -39,11 +39,16 @@ impl Database {
.unwrap()
.read_to_string(&mut buffer)
.unwrap();
for sgf in parse_sgf(&buffer).unwrap() {
match sgf {
Game::Go(game) => games.push(game),
Game::Unsupported(_) => {}
match parse_sgf(&buffer) {
Ok(sgfs) => {
for sgf in sgfs {
match sgf {
Game::Go(game) => games.push(game),
Game::Unsupported(_) => {}
}
}
}
Err(err) => println!("Error parsing {:?}: {:?}", entry.path(), err),
}
}
}

View File

@ -50,6 +50,7 @@ impl GamePreviewElement {
Some(GameResult::Draw) => "Draw".to_owned(),
Some(GameResult::Black(ref win)) => format!("Black by {}", format_win(win)),
Some(GameResult::White(ref win)) => format!("White by {}", format_win(win)),
Some(GameResult::Unknown(ref text)) => format!("Unknown: {}", text),
None => "".to_owned(),
};

View File

@ -2,19 +2,19 @@ use adw::prelude::*;
use kifu_core::{CoreApp, CoreRequest, CoreResponse};
use kifu_gtk::{
perftrace,
ui::{Home, PlayingField},
ui::{Home, Layout, PlayingField},
CoreApi,
};
use std::sync::{Arc, RwLock};
fn handle_response(api: CoreApi, window: adw::ApplicationWindow, message: CoreResponse) {
fn handle_response(api: CoreApi, layout: Layout, message: CoreResponse) {
let playing_field = Arc::new(RwLock::new(None));
match message {
CoreResponse::HomeView(view) => perftrace("HomeView", || {
let api = api.clone();
let home = Home::new(api, view);
window.set_content(Some(&home));
layout.set_content(&home);
}),
CoreResponse::PlayingFieldView(view) => perftrace("PlayingFieldView", || {
let api = api.clone();
@ -23,7 +23,7 @@ fn handle_response(api: CoreApi, window: adw::ApplicationWindow, message: CoreRe
if playing_field.is_none() {
perftrace("creating a new playing field", || {
let field = PlayingField::new(api, view);
window.set_content(Some(&field));
layout.set_content(&field);
*playing_field = Some(field);
})
} else {
@ -101,13 +101,17 @@ fn main() {
.width_request(800)
.height_request(500)
.build();
let layout = Layout::new();
window.set_content(Some(&layout));
window.present();
gtk_rx.attach(None, {
let api = api.clone();
move |message| {
perftrace("handle_response", || {
handle_response(api.clone(), window.clone(), message)
handle_response(api.clone(), layout.clone(), message)
});
Continue(true)
}

View File

@ -31,7 +31,7 @@ impl GamePreview {
let s: Self = Object::builder().build();
s.set_orientation(gtk::Orientation::Horizontal);
s.set_homogeneous(true);
s.set_hexpand(true);
s.set_hexpand(false);
s.append(&s.imp().date);
s.append(&s.imp().title);

61
kifu/gtk/src/ui/layout.rs Normal file
View File

@ -0,0 +1,61 @@
use glib::Object;
use gtk::{prelude::*, subclass::prelude::*};
use std::{cell::RefCell, rc::Rc};
// Deprecated even from day 1. We want to use ToolbarView as soon as it's available in the versions
// of Libadwaita available in NixOS.
pub struct LayoutPrivate {
pub header: adw::HeaderBar,
pub content: Rc<RefCell<gtk::Widget>>,
}
impl Default for LayoutPrivate {
fn default() -> Self {
let header = adw::HeaderBar::builder()
.title_widget(&gtk::Label::new(Some("Placeholder Title")))
.show_start_title_buttons(true)
.show_end_title_buttons(true)
.build();
let content = adw::StatusPage::builder().title("Nothing here").build();
Self {
header,
content: Rc::new(RefCell::new(content.into())),
}
}
}
#[glib::object_subclass]
impl ObjectSubclass for LayoutPrivate {
const NAME: &'static str = "Layout";
type Type = Layout;
type ParentType = gtk::Box;
}
impl ObjectImpl for LayoutPrivate {}
impl WidgetImpl for LayoutPrivate {}
impl BoxImpl for LayoutPrivate {}
glib::wrapper! {
pub struct Layout(ObjectSubclass<LayoutPrivate>) @extends gtk::Box, gtk::Widget, @implements gtk::Orientable;
}
impl Layout {
pub fn new() -> Self {
let s: Self = Object::builder().build();
s.set_orientation(gtk::Orientation::Vertical);
s.set_homogeneous(false);
s.append(&s.imp().header);
s.append(&*s.imp().content.borrow());
s
}
pub fn set_content(&self, content: &impl IsA<gtk::Widget>) {
let mut widget = self.imp().content.borrow_mut();
self.remove(&*widget);
*widget = content.clone().upcast::<gtk::Widget>();
self.append(&*widget);
}
}

View File

@ -7,6 +7,9 @@ pub use game_preview::GamePreview;
mod library;
pub use library::Library;
mod layout;
pub use layout::Layout;
mod player_card;
pub use player_card::PlayerCard;

View File

@ -242,6 +242,7 @@ pub enum GameResult {
Draw,
Black(Win),
White(Win),
Unknown(String),
}
impl TryFrom<&str> for GameResult {
@ -256,7 +257,7 @@ impl TryFrom<&str> for GameResult {
let res = match parts[0].to_ascii_lowercase().as_str() {
"b" => GameResult::Black,
"w" => GameResult::White,
_ => panic!("unknown result format"),
_ => return Ok(GameResult::Unknown(parts[0].to_owned())),
};
match parts[1].to_ascii_lowercase().as_str() {
"r" | "resign" => Ok(res(Win::Resignation)),