Render the chat element #34

Merged
savanni merged 2 commits from feature/kifu-render-chat into main 2023-03-23 03:11:56 +00:00
7 changed files with 127 additions and 49 deletions

View File

@ -1,4 +1,4 @@
pub mod playing_field; pub mod playing_field;
mod types; mod types;
pub use types::PlayerCardElement; pub use types::{ChatElement, PlayerCardElement};

View File

@ -12,3 +12,7 @@ gtk = { version = "0.6", package = "gtk4" }
kifu-core = { path = "../kifu-core" } kifu-core = { path = "../kifu-core" }
tokio = { version = "1.26", features = [ "full" ] } tokio = { version = "1.26", features = [ "full" ] }
screenplay = { path = "../../screenplay" } screenplay = { path = "../../screenplay" }
[[bin]]
name = "kifu-gtk"
path = "src/main.rs"

View File

@ -1,52 +1,18 @@
use glib::Object; use glib::Object;
use gtk::{prelude::*, subclass::prelude::*}; use gtk::{prelude::*, subclass::prelude::*};
use kifu_core::{ui::PlayerCardElement, Color}; use kifu_core::{ui::ChatElement, ui::PlayerCardElement, Color};
use kifu_gtk::ui::{Chat, PlayerCard};
use screenplay::{Screen, Screenplay}; use screenplay::{Screen, Screenplay};
use std::{cell::RefCell, rc::Rc}; use std::{cell::RefCell, rc::Rc};
#[derive(Default)]
pub struct PlayerCardPrivate {
player_name: gtk::Label,
clock: gtk::Label,
}
#[glib::object_subclass]
impl ObjectSubclass for PlayerCardPrivate {
const NAME: &'static str = "PlayerCard";
type Type = PlayerCard;
type ParentType = gtk::Box;
}
impl ObjectImpl for PlayerCardPrivate {}
impl WidgetImpl for PlayerCardPrivate {}
impl BoxImpl for PlayerCardPrivate {}
glib::wrapper! {
pub struct PlayerCard(ObjectSubclass<PlayerCardPrivate>) @extends gtk::Box, gtk::Widget, @implements gtk::Orientable;
}
impl PlayerCard {
pub fn new(element: PlayerCardElement) -> PlayerCard {
let s: Self = Object::builder().build();
s.set_orientation(gtk::Orientation::Vertical);
s.imp()
.player_name
.set_text(&format!("{} ({})", element.name, element.rank));
s.imp().clock.set_text(&element.clock);
s.append(&s.imp().player_name);
s.append(&s.imp().clock);
s
}
}
fn main() { fn main() {
let app = gtk::Application::builder() let app = gtk::Application::builder()
.application_id("com.luminescent-dreams.kifu-gtk.screenplay") .application_id("com.luminescent-dreams.kifu-gtk.screenplay")
.build(); .build();
app.connect_activate(|app| { app.connect_activate(|app| {
let screens = vec![Screen { let screens = vec![
Screen {
title: "PlayerCard".to_owned(), title: "PlayerCard".to_owned(),
widget: PlayerCard::new(PlayerCardElement { widget: PlayerCard::new(PlayerCardElement {
color: Color::Black, color: Color::Black,
@ -56,7 +22,20 @@ fn main() {
}) })
.upcast::<gtk::Widget>(), .upcast::<gtk::Widget>(),
adjustments: vec![], adjustments: vec![],
}]; },
Screen {
title: "ChatArea".to_owned(),
widget: Chat::new(ChatElement {
messages: vec![
"message 1".to_owned(),
"message 2".to_owned(),
"message 3".to_owned(),
],
})
.upcast::<gtk::Widget>(),
adjustments: vec![],
},
];
let screenplay = Screenplay::new(&app, screens).unwrap(); let screenplay = Screenplay::new(&app, screens).unwrap();
}); });

1
kifu/kifu-gtk/src/lib.rs Normal file
View File

@ -0,0 +1 @@
pub mod ui;

View File

@ -0,0 +1,50 @@
use glib::Object;
use gtk::{prelude::*, subclass::prelude::*};
use kifu_core::ui::ChatElement;
#[derive(Default)]
pub struct ChatPrivate {
chat_history: gtk::Box,
entry: gtk::Entry,
}
#[glib::object_subclass]
impl ObjectSubclass for ChatPrivate {
const NAME: &'static str = "Chat";
type Type = Chat;
type ParentType = gtk::Box;
}
impl ObjectImpl for ChatPrivate {
fn constructed(&self) {
self.chat_history
.set_orientation(gtk::Orientation::Vertical);
}
}
impl WidgetImpl for ChatPrivate {}
impl BoxImpl for ChatPrivate {}
glib::wrapper! {
pub struct Chat(ObjectSubclass<ChatPrivate>) @extends gtk::Box, gtk::Widget, @implements gtk::Orientable;
}
impl Chat {
pub fn new(element: ChatElement) -> Chat {
let s: Self = Object::builder().build();
s.set_orientation(gtk::Orientation::Vertical);
s.append(&s.imp().chat_history);
s.append(&s.imp().entry);
element.messages.into_iter().for_each(|msg| {
s.imp().chat_history.append(
&gtk::Label::builder()
.label(&msg)
.halign(gtk::Align::Start)
.build(),
)
});
s
}
}

View File

@ -0,0 +1,5 @@
mod player_card;
pub use player_card::PlayerCard;
mod chat;
pub use chat::Chat;

View File

@ -0,0 +1,39 @@
use glib::Object;
use gtk::{prelude::*, subclass::prelude::*};
use kifu_core::{ui::PlayerCardElement, Color};
#[derive(Default)]
pub struct PlayerCardPrivate {
player_name: gtk::Label,
clock: gtk::Label,
}
#[glib::object_subclass]
impl ObjectSubclass for PlayerCardPrivate {
const NAME: &'static str = "PlayerCard";
type Type = PlayerCard;
type ParentType = gtk::Box;
}
impl ObjectImpl for PlayerCardPrivate {}
impl WidgetImpl for PlayerCardPrivate {}
impl BoxImpl for PlayerCardPrivate {}
glib::wrapper! {
pub struct PlayerCard(ObjectSubclass<PlayerCardPrivate>) @extends gtk::Box, gtk::Widget, @implements gtk::Orientable;
}
impl PlayerCard {
pub fn new(element: PlayerCardElement) -> PlayerCard {
let s: Self = Object::builder().build();
s.set_orientation(gtk::Orientation::Vertical);
s.imp()
.player_name
.set_text(&format!("{} ({})", element.name, element.rank));
s.imp().clock.set_text(&element.clock);
s.append(&s.imp().player_name);
s.append(&s.imp().clock);
s
}
}