complete cards/game
This commit is contained in:
parent
24acb4ecd1
commit
857613a01d
|
@ -1,18 +1,16 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<interface>
|
<interface>
|
||||||
<template class="MemoryCardsSetupScene" parent="GtkApplicationWindow">
|
<template class="MemoryCardsGameScene" parent="GtkApplicationWindow">
|
||||||
<property name="title">Memory cards setup</property>
|
<property name="title">Memory cards game</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox" id="content">
|
<object class="GtkBox" id="content">
|
||||||
<property name="orientation">horizontal</property>
|
<property name="orientation">vertical</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkButton" id="edit_button">
|
<object class="CardDisplay" id="card_display"></object>
|
||||||
<property name="label">Edit cards</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkButton" id="start_button">
|
<object class="GtkLabel" id="stats_label">
|
||||||
<property name="label">start game</property>
|
<property name="label">Correct|Incorrect: 0|0</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
|
|
@ -6,14 +6,15 @@
|
||||||
<file compressed="true" preprocess="xml-stripblanks">cards/edit/ui.xml</file>
|
<file compressed="true" preprocess="xml-stripblanks">cards/edit/ui.xml</file>
|
||||||
<file compressed="true" preprocess="xml-stripblanks">cards/setup/ui.xml</file>
|
<file compressed="true" preprocess="xml-stripblanks">cards/setup/ui.xml</file>
|
||||||
<file compressed="true" preprocess="xml-stripblanks">cards/new/ui.xml</file>
|
<file compressed="true" preprocess="xml-stripblanks">cards/new/ui.xml</file>
|
||||||
|
<file compressed="true" preprocess="xml-stripblanks">cards/game/ui.xml</file>
|
||||||
|
|
||||||
|
|
||||||
<file compressed="true" preprocess="xml-stripblanks">guessing/game/ui.xml</file>
|
<file compressed="true" preprocess="xml-stripblanks">guessing/game/ui.xml</file>
|
||||||
<file compressed="true" preprocess="xml-stripblanks">guessing/setup/ui.xml</file>
|
<file compressed="true" preprocess="xml-stripblanks">guessing/setup/ui.xml</file>
|
||||||
|
|
||||||
<!-- <file compressed="true" preprocess="xml-stripblanks">cards/game/ui.xml</file> -->
|
|
||||||
|
|
||||||
<file compressed="true" preprocess="xml-stripblanks">widgets/labled_switch/template.ui.xml</file>
|
<file compressed="true" preprocess="xml-stripblanks">widgets/labled_switch/template.ui.xml</file>
|
||||||
<file compressed="true" preprocess="xml-stripblanks">widgets/card_entry/template.ui.xml</file>
|
<file compressed="true" preprocess="xml-stripblanks">widgets/card_entry/template.ui.xml</file>
|
||||||
|
<file compressed="true" preprocess="xml-stripblanks">widgets/card_display/template.ui.xml</file>
|
||||||
</gresource>
|
</gresource>
|
||||||
</gresources>
|
</gresources>
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<template class="CardDisplay" parent="GtkWidget">
|
||||||
|
<child>
|
||||||
|
<object class="GtkPicture" id="picture">
|
||||||
|
<property name="halign">GTK_ALIGN_CENTER</property>
|
||||||
|
<property name="valign">GTK_ALIGN_CENTER</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="answer_entry">
|
||||||
|
<property name="halign">GTK_ALIGN_CENTER</property>
|
||||||
|
<property name="valign">GTK_ALIGN_START</property>
|
||||||
|
<property name="placeholder-text">Type kana that picture means</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</template>
|
||||||
|
</interface>
|
|
@ -82,7 +82,7 @@ impl MemoryCardsEditScene {
|
||||||
let cards_iter = stmt
|
let cards_iter = stmt
|
||||||
.query_map([], |row| {
|
.query_map([], |row| {
|
||||||
let image_path: String = row.get(0).unwrap();
|
let image_path: String = row.get(0).unwrap();
|
||||||
let image_path = get_images_store_path() + &image_path;
|
let image_path: String = get_images_store_path() + &image_path;
|
||||||
let hieroglyph: String = row.get(1).unwrap();
|
let hieroglyph: String = row.get(1).unwrap();
|
||||||
let reading: String = row.get(2).unwrap();
|
let reading: String = row.get(2).unwrap();
|
||||||
let entry = CardEntry::new(&image_path, &hieroglyph, &reading);
|
let entry = CardEntry::new(&image_path, &hieroglyph, &reading);
|
||||||
|
@ -94,9 +94,6 @@ impl MemoryCardsEditScene {
|
||||||
let card_binding = card.unwrap();
|
let card_binding = card.unwrap();
|
||||||
let self_binding = self.obj();
|
let self_binding = self.obj();
|
||||||
c.append(&card_binding);
|
c.append(&card_binding);
|
||||||
card_binding.connect_closure("created", false, closure_local!(move | | {
|
|
||||||
println!("New card created");
|
|
||||||
}));
|
|
||||||
|
|
||||||
card_binding.get_delete_button_widget().connect_closure("clicked", false, closure_local!(@strong card_binding, @strong self_binding => move |_b: &Button| {
|
card_binding.get_delete_button_widget().connect_closure("clicked", false, closure_local!(@strong card_binding, @strong self_binding => move |_b: &Button| {
|
||||||
let connection = Connection::open(get_db_path()).unwrap();
|
let connection = Connection::open(get_db_path()).unwrap();
|
||||||
|
|
|
@ -1 +1,65 @@
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
use crate::widgets::card_display::*;
|
||||||
|
|
||||||
|
use glib::subclass::InitializingObject;
|
||||||
|
use gtk::glib::clone;
|
||||||
|
use gtk::subclass::prelude::*;
|
||||||
|
use gtk::{prelude::*, Entry};
|
||||||
|
use gtk::{glib, CompositeTemplate, Label};
|
||||||
|
|
||||||
|
#[derive(CompositeTemplate, Default)]
|
||||||
|
#[template(resource = "/org/foxarmy/learn-hieroglyph/cards/game/ui.xml")]
|
||||||
|
pub struct MemoryCardsGameScene {
|
||||||
|
#[template_child]
|
||||||
|
pub card_display: TemplateChild<CardDisplay>,
|
||||||
|
#[template_child]
|
||||||
|
pub stats_label: TemplateChild<Label>,
|
||||||
|
|
||||||
|
pub correct: RefCell<usize>,
|
||||||
|
pub incorrect: RefCell<usize>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[glib::object_subclass]
|
||||||
|
impl ObjectSubclass for MemoryCardsGameScene {
|
||||||
|
const NAME: &'static str = "MemoryCardsGameScene";
|
||||||
|
type Type = super::MemoryCardsGameScene;
|
||||||
|
type ParentType = gtk::ApplicationWindow;
|
||||||
|
|
||||||
|
fn class_init(klass: &mut Self::Class) {
|
||||||
|
klass.bind_template();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn instance_init(obj: &InitializingObject<Self>) {
|
||||||
|
obj.init_template();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ObjectImpl for MemoryCardsGameScene {
|
||||||
|
fn constructed(&self) {
|
||||||
|
self.parent_constructed();
|
||||||
|
|
||||||
|
let card_display_binding = self.card_display.imp().obj();
|
||||||
|
let self_binding = self.obj();
|
||||||
|
|
||||||
|
card_display_binding.generate_card();
|
||||||
|
card_display_binding.get_answer_entry().connect_activate(clone!(@strong card_display_binding, @strong self_binding => move |e: &Entry| {
|
||||||
|
println!("{}", e.text());
|
||||||
|
println!("{} = {}? -> {}", e.text(), card_display_binding.get_hieroglyph(), e.text().to_string() == *card_display_binding.get_hieroglyph());
|
||||||
|
if e.text() == *card_display_binding.get_hieroglyph() {
|
||||||
|
*self_binding.imp().correct.borrow_mut() += 1;
|
||||||
|
} else {
|
||||||
|
*self_binding.imp().incorrect.borrow_mut() +=1;
|
||||||
|
}
|
||||||
|
self_binding.update_stats();
|
||||||
|
card_display_binding.generate_card();
|
||||||
|
e.set_text("");
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WidgetImpl for MemoryCardsGameScene {}
|
||||||
|
|
||||||
|
impl WindowImpl for MemoryCardsGameScene {}
|
||||||
|
|
||||||
|
impl ApplicationWindowImpl for MemoryCardsGameScene {}
|
||||||
|
|
|
@ -1 +1,35 @@
|
||||||
|
|
||||||
|
mod imp;
|
||||||
|
|
||||||
|
use glib::Object;
|
||||||
|
use gtk::{gio, glib::{self, subclass::types::ObjectSubclassIsExt}, Application};
|
||||||
|
|
||||||
|
glib::wrapper! {
|
||||||
|
pub struct MemoryCardsGameScene(ObjectSubclass<imp::MemoryCardsGameScene>)
|
||||||
|
@extends gtk::ApplicationWindow, gtk::Window, gtk::Widget,
|
||||||
|
@implements gio::ActionGroup, gio::ActionMap, gtk::Accessible, gtk::Buildable,
|
||||||
|
gtk::ConstraintTarget, gtk::Native, gtk::Root, gtk::ShortcutManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MemoryCardsGameScene {
|
||||||
|
pub fn new(app: &Application) -> Self {
|
||||||
|
Object::builder().property("application", app).build()
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub fn set_stats(&self, correct: usize, incorrect: usize) {
|
||||||
|
// self.imp().stats_label.set_text(&format!("Correct|Incorrect: {correct}|{incorrect}"));
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn update_stats(&self) {
|
||||||
|
self.imp().stats_label.set_text(&format!("Correct|Incorrect: {}|{}", self.imp().correct.borrow(), self.imp().incorrect.borrow()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub fn get_stats(&self) -> (usize, usize) {
|
||||||
|
// (self.imp().correct, self.imp().incorrect)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn set_stats(&self, correct: usize, incorrect: usize) {
|
||||||
|
// self.imp().correct = correct;
|
||||||
|
// self.imp().incorrect = incorrect;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::ui::cards::edit::*;
|
use crate::ui::cards::{edit::MemoryCardsEditScene, game::MemoryCardsGameScene};
|
||||||
|
|
||||||
use glib::subclass::InitializingObject;
|
use glib::subclass::InitializingObject;
|
||||||
use gtk::glib::closure_local;
|
use gtk::glib::closure_local;
|
||||||
|
@ -35,13 +35,17 @@ impl ObjectImpl for MemoryCardsSetupScene {
|
||||||
|
|
||||||
let binding = self.obj();
|
let binding = self.obj();
|
||||||
|
|
||||||
self.edit_button.connect_closure("clicked",
|
self.edit_button.connect_closure("clicked",false, closure_local!(@strong binding => move |_b: &Button| {
|
||||||
false,
|
|
||||||
closure_local!(@strong binding => move |_b: &Button| {
|
|
||||||
let new_win: MemoryCardsEditScene = MemoryCardsEditScene::new(&binding.application().unwrap());
|
let new_win: MemoryCardsEditScene = MemoryCardsEditScene::new(&binding.application().unwrap());
|
||||||
new_win.present();
|
new_win.present();
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
self.start_button.connect_closure("clicked", false, closure_local!(@strong binding => move |_b: &Button| {
|
||||||
|
let new_win: MemoryCardsGameScene = MemoryCardsGameScene::new(&binding.application().unwrap());
|
||||||
|
new_win.present();
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
use glib::subclass::InitializingObject;
|
||||||
|
use glib::Properties;
|
||||||
|
use gtk::subclass::prelude::*;
|
||||||
|
use gtk::{glib, prelude::*, BoxLayout, CompositeTemplate, Entry, Picture};
|
||||||
|
|
||||||
|
#[derive(CompositeTemplate, Properties, Default)]
|
||||||
|
#[properties(wrapper_type = super::CardDisplay)]
|
||||||
|
#[template(resource = "/org/foxarmy/learn-hieroglyph/widgets/card_display/template.ui.xml")]
|
||||||
|
pub struct CardDisplay {
|
||||||
|
#[template_child]
|
||||||
|
pub picture: TemplateChild<Picture>,
|
||||||
|
#[template_child]
|
||||||
|
pub answer_entry: TemplateChild<Entry>,
|
||||||
|
#[property(get, set)]
|
||||||
|
pub imagepath: RefCell<String>,
|
||||||
|
#[property(get, set)]
|
||||||
|
pub hieroglyph: RefCell<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[glib::object_subclass]
|
||||||
|
impl ObjectSubclass for CardDisplay {
|
||||||
|
const NAME: &'static str = "CardDisplay";
|
||||||
|
type Type = super::CardDisplay;
|
||||||
|
type ParentType = gtk::Widget;
|
||||||
|
|
||||||
|
fn class_init(klass: &mut Self::Class) {
|
||||||
|
klass.bind_template();
|
||||||
|
klass.set_layout_manager_type::<gtk::BoxLayout>();
|
||||||
|
// klass.set_layout_manager_type(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn instance_init(obj: &InitializingObject<Self>) {
|
||||||
|
obj.init_template();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[glib::derived_properties]
|
||||||
|
impl ObjectImpl for CardDisplay {
|
||||||
|
fn constructed(&self) {
|
||||||
|
self.parent_constructed();
|
||||||
|
let layout_manager: BoxLayout = BoxLayout::new(gtk::Orientation::Vertical);
|
||||||
|
|
||||||
|
self.obj().set_layout_manager(Some(layout_manager));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dispose(&self) {
|
||||||
|
self.dispose_template();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WidgetImpl for CardDisplay {}
|
|
@ -0,0 +1,72 @@
|
||||||
|
mod imp;
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
use glib::Object;
|
||||||
|
use gtk::{gio, glib::{self, subclass::types::ObjectSubclassIsExt}, Entry, Picture};
|
||||||
|
use rusqlite::Connection;
|
||||||
|
|
||||||
|
use crate::db::{get_db_path, get_images_store_path};
|
||||||
|
|
||||||
|
glib::wrapper! {
|
||||||
|
pub struct CardDisplay(ObjectSubclass<imp::CardDisplay>)
|
||||||
|
@extends gtk::Widget,
|
||||||
|
@implements gio::ActionGroup, gio::ActionMap, gtk::Accessible, gtk::Buildable,
|
||||||
|
gtk::ConstraintTarget, gtk::Native, gtk::Root, gtk::ShortcutManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Card {
|
||||||
|
imagename: String,
|
||||||
|
hieroglyph: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CardDisplay {
|
||||||
|
pub fn new(image_path: &String, hieroglyph: &String) -> Self {
|
||||||
|
Object::builder()
|
||||||
|
.property("imagepath", image_path)
|
||||||
|
.property("hieroglyph", hieroglyph)
|
||||||
|
// .property("reading", reading)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_file_for_picture(&self) {
|
||||||
|
let picture_binding: &Picture = self.imp().picture.as_ref();
|
||||||
|
let path: &str = &*self.imp().imagepath.borrow().clone().to_string();
|
||||||
|
picture_binding.set_file(Some(&gio::File::for_path(path)));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_card(&self) -> (&RefCell<String>, &RefCell<String>) {
|
||||||
|
let connection = Connection::open(get_db_path()).unwrap();
|
||||||
|
|
||||||
|
let mut stmt = connection.prepare("SELECT imagename, hieroglyph FROM cards ORDER BY RANDOM() LIMIT 1").unwrap();
|
||||||
|
let random_card_iter = stmt.query_map((), |row| {
|
||||||
|
Ok(
|
||||||
|
Card {
|
||||||
|
imagename: row.get(0).unwrap(),
|
||||||
|
hieroglyph: row.get(1).unwrap()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
|
let mut random_card = None;
|
||||||
|
for i in random_card_iter {
|
||||||
|
random_card = Some(i.unwrap());
|
||||||
|
}
|
||||||
|
let random_card: Card = random_card.unwrap();
|
||||||
|
|
||||||
|
*self.imp().imagepath.borrow_mut() = get_images_store_path() + "/" + random_card.imagename.as_str();
|
||||||
|
*self.imp().hieroglyph.borrow_mut() = random_card.hieroglyph;
|
||||||
|
|
||||||
|
self.update_file_for_picture();
|
||||||
|
|
||||||
|
(&self.imp().imagepath, &self.imp().hieroglyph)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_answer_entry(&self) -> &Entry {
|
||||||
|
self.imp().answer_entry.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_hieroglyph(&self) -> String {
|
||||||
|
self.imp().hieroglyph.borrow().clone()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,7 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::sync::OnceLock;
|
|
||||||
|
|
||||||
use glib::subclass::InitializingObject;
|
use glib::subclass::InitializingObject;
|
||||||
use glib::Properties;
|
use glib::Properties;
|
||||||
use gtk::glib::subclass::Signal;
|
|
||||||
use gtk::subclass::prelude::*;
|
use gtk::subclass::prelude::*;
|
||||||
use gtk::{glib, prelude::*, Button, CompositeTemplate, Label, Picture};
|
use gtk::{glib, prelude::*, Button, CompositeTemplate, Label, Picture};
|
||||||
|
|
||||||
|
@ -44,19 +42,9 @@ impl ObjectSubclass for CardEntry {
|
||||||
}
|
}
|
||||||
#[glib::derived_properties]
|
#[glib::derived_properties]
|
||||||
impl ObjectImpl for CardEntry {
|
impl ObjectImpl for CardEntry {
|
||||||
|
|
||||||
fn signals() -> &'static [Signal] {
|
|
||||||
static SIGNALS: OnceLock<Vec<Signal>> = OnceLock::new();
|
|
||||||
SIGNALS.get_or_init(|| {
|
|
||||||
vec![Signal::builder("created")
|
|
||||||
.build()]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn constructed(&self) {
|
fn constructed(&self) {
|
||||||
self.parent_constructed();
|
self.parent_constructed();
|
||||||
|
|
||||||
|
|
||||||
let hieroglyph_label_binding: &Label = self.hieroglyph_label.as_ref();
|
let hieroglyph_label_binding: &Label = self.hieroglyph_label.as_ref();
|
||||||
self.obj()
|
self.obj()
|
||||||
.bind_property("hieroglyph", hieroglyph_label_binding, "label")
|
.bind_property("hieroglyph", hieroglyph_label_binding, "label")
|
||||||
|
|
Loading…
Reference in New Issue