update ui
This commit is contained in:
parent
a4444a9fb1
commit
deaa814423
|
@ -6,6 +6,10 @@ edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
dirs = "5.0.1"
|
||||||
gtk = { version = "0.8.1", package = "gtk4", features = ["v4_12"] }
|
gtk = { version = "0.8.1", package = "gtk4", features = ["v4_12"] }
|
||||||
|
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
glib-build-tools = "0.19.0"
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
fn main() {
|
||||||
|
glib_build_tools::compile_resources(
|
||||||
|
&["resources"],
|
||||||
|
"resources/resources.gresource.xml",
|
||||||
|
"compiled.gresource",
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<template class="GuessingScene" parent="GtkApplicationWindow">
|
||||||
|
<property name="title">Guessing</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="content">
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="question_label">
|
||||||
|
<property name="label">There's a question:</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="answer_entry">
|
||||||
|
<property name="placeholder_text">Answer</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="stats_label">
|
||||||
|
<property name="label">Correct|Incorrect: 0|0</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</template>
|
||||||
|
</interface>
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<template class="MemoryCardsSetupScene" parent="GtkApplicationWindow">
|
||||||
|
<property name="title">Memory cards setup</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="content">
|
||||||
|
<property name="orientation">horizontal</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="edit_button">
|
||||||
|
<property name="label">test</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="start_button">
|
||||||
|
<property name="label">test2</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</template>
|
||||||
|
</interface>
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<template class="MenuScene" parent="GtkApplicationWindow">
|
||||||
|
<property name="title">Menu</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="content">
|
||||||
|
<property name="orientation">horizontal</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="hiragana_and_katakana">
|
||||||
|
<property name="label">Practice hiragana and katakana</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="memory_cards">
|
||||||
|
<property name="label">Practice vocabulary with memory cards</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</template>
|
||||||
|
</interface>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<gresources>
|
||||||
|
<gresource prefix="/org/foxarmy/learn-hieroglyph/">
|
||||||
|
<file compressed="true" preprocess="xml-stripblanks">menu.ui.xml</file>
|
||||||
|
<file compressed="true" preprocess="xml-stripblanks">guessing.ui.xml</file>
|
||||||
|
<file compressed="true" preprocess="xml-stripblanks">settings.gschema.xml</file>
|
||||||
|
<file compressed="true" preprocess="xml-stripblanks">memory_cards_settings.ui.xml</file>
|
||||||
|
</gresource>
|
||||||
|
</gresources>
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<schemalist>
|
||||||
|
<schema id="org.foxarmy.learn-hieroglyph" path="/org/foxarmy/learn-hieroglyph/">
|
||||||
|
<key name="is-rtk-enabled" type="b">
|
||||||
|
<default>false</default>
|
||||||
|
<summary>Enable romaji to kana</summary>
|
||||||
|
</key>
|
||||||
|
<key name="is-ktr-enabled" type="b">
|
||||||
|
<default>true</default>
|
||||||
|
<summary>Enable kana to romaji</summary>
|
||||||
|
</key>
|
||||||
|
<key name="is-hiragana-enabled" type="b">
|
||||||
|
<default>true</default>
|
||||||
|
<summary>Enable hiragana</summary>
|
||||||
|
</key>
|
||||||
|
<key name="is-katakana-enabled" type="b">
|
||||||
|
<default>false</default>
|
||||||
|
<summary>Enable katakana</summary>
|
||||||
|
</key>
|
||||||
|
</schema>
|
||||||
|
</schemalist>
|
66
src/game.rs
66
src/game.rs
|
@ -32,12 +32,8 @@ pub struct Hieroglyph {
|
||||||
column: usize,
|
column: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Useful {
|
impl Hieroglyph {
|
||||||
fn get_kana(&self) -> Kanas;
|
pub fn get_kana(&self) -> Kanas {
|
||||||
}
|
|
||||||
|
|
||||||
impl Useful for Hieroglyph {
|
|
||||||
fn get_kana(&self) -> Kanas {
|
|
||||||
for row in ROMAJI {
|
for row in ROMAJI {
|
||||||
if row.contains(&(self.syllable).as_str()) {
|
if row.contains(&(self.syllable).as_str()) {
|
||||||
return Kanas::Romaji;
|
return Kanas::Romaji;
|
||||||
|
@ -146,3 +142,61 @@ pub fn generate_random_hieroglyph(k: Kanas) -> Hieroglyph {
|
||||||
column,
|
column,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn random_kana(hiragana: bool, katakana: bool) -> Hieroglyph {
|
||||||
|
if hiragana && katakana {
|
||||||
|
generate_random_hieroglyph(if rand::thread_rng().gen_bool(0.5) {
|
||||||
|
Kanas::Katakana
|
||||||
|
} else {
|
||||||
|
Kanas::Hiragana
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
generate_random_hieroglyph(if hiragana {
|
||||||
|
Kanas::Hiragana
|
||||||
|
} else {
|
||||||
|
Kanas::Katakana
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ask(ktr: bool, rtk: bool, hiragana: bool, katakana: bool) -> Hieroglyph {
|
||||||
|
if ktr && rtk {
|
||||||
|
return if rand::thread_rng().gen_bool(0.5) {
|
||||||
|
random_kana(hiragana, katakana)
|
||||||
|
} else {
|
||||||
|
generate_random_hieroglyph(Kanas::Romaji)
|
||||||
|
};
|
||||||
|
} else if ktr {
|
||||||
|
return random_kana(hiragana, katakana);
|
||||||
|
} else {
|
||||||
|
return generate_random_hieroglyph(Kanas::Romaji);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_question_text(question: &Hieroglyph, exact_kana: &Kanas) -> String {
|
||||||
|
return String::from(match question.get_kana() {
|
||||||
|
Kanas::Romaji => match exact_kana {
|
||||||
|
Kanas::Hiragana => {
|
||||||
|
format!("Name corresponding hiragana for {}", question.to_string())
|
||||||
|
}
|
||||||
|
Kanas::Katakana => {
|
||||||
|
format!("Name corresponding katakana for {}", question.to_string())
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
panic!("HOW DID YOU GET HERE!?");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Kanas::Hiragana => {
|
||||||
|
format!(
|
||||||
|
"Name corresponding romaji for hiragana {}",
|
||||||
|
question.to_string()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Kanas::Katakana => {
|
||||||
|
format!(
|
||||||
|
"Name corresponding romaji for katakana {}",
|
||||||
|
question.to_string()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
use gtk::glib;
|
||||||
|
use gtk::subclass::prelude::*;
|
||||||
|
|
||||||
|
// Object holding the state
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct LabledSwitch;
|
||||||
|
|
||||||
|
// The central trait for subclassing a GObject
|
||||||
|
#[glib::object_subclass]
|
||||||
|
impl ObjectSubclass for LabledSwitch {
|
||||||
|
const NAME: &'static str = "LabledSwitch";
|
||||||
|
type Type = super::LabledSwitch;
|
||||||
|
type ParentType = gtk::Widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ObjectImpl for LabledSwitch {}
|
||||||
|
|
||||||
|
impl WidgetImpl for LabledSwitch {}
|
||||||
|
|
||||||
|
impl ButtonImpl for LabledSwitch {}
|
||||||
|
|
||||||
|
// impl IsSubclassable for LabledSwitch {}
|
|
@ -1,23 +1,45 @@
|
||||||
use gtk::{prelude::*, Box, Label, Switch};
|
// mod imp;
|
||||||
|
|
||||||
pub fn build(text: &str) -> (Box, Switch, Label) {
|
// use glib::Object;
|
||||||
let switch: Switch = Switch::builder()
|
// use gtk::glib;
|
||||||
.valign(gtk::Align::Start)
|
|
||||||
.halign(gtk::Align::Center)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let label: Label = Label::builder()
|
// glib::wrapper! {
|
||||||
.valign(gtk::Align::End)
|
// pub struct LabledSwitch(ObjectSubclass<imp::LabledSwitch>)
|
||||||
.halign(gtk::Align::BaselineCenter)
|
// @extends gtk::Widget,
|
||||||
.label(text)
|
// @implements gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget;
|
||||||
.build();
|
// }
|
||||||
|
|
||||||
let container = Box::builder()
|
// impl LabledSwitch {
|
||||||
.orientation(gtk::Orientation::Horizontal)
|
// pub fn new() -> Self {
|
||||||
.build();
|
// Object::builder().build()
|
||||||
|
// }
|
||||||
|
|
||||||
container.append(&switch);
|
// pub fn with_label(label: &str) -> Self {
|
||||||
container.append(&label);
|
// Object::builder().property("label", label).build()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
(container, switch, label)
|
|
||||||
}
|
// // use gtk::{prelude::*, Box, Label, Switch};
|
||||||
|
|
||||||
|
// // pub fn build(text: &str) -> (Box, Switch, Label) {
|
||||||
|
// // let switch: Switch = Switch::builder()
|
||||||
|
// // .valign(gtk::Align::Start)
|
||||||
|
// // .halign(gtk::Align::Center)
|
||||||
|
// // .build();
|
||||||
|
|
||||||
|
// // let label: Label = Label::builder()
|
||||||
|
// // .valign(gtk::Align::End)
|
||||||
|
// // .halign(gtk::Align::BaselineCenter)
|
||||||
|
// // .label(text)
|
||||||
|
// // .build();
|
||||||
|
|
||||||
|
// // let container = Box::builder()
|
||||||
|
// // .orientation(gtk::Orientation::Horizontal)
|
||||||
|
// // .build();
|
||||||
|
|
||||||
|
// // container.append(&switch);
|
||||||
|
// // container.append(&label);
|
||||||
|
|
||||||
|
// // (container, switch, label)
|
||||||
|
// // }
|
||||||
|
|
29
src/main.rs
29
src/main.rs
|
@ -2,17 +2,34 @@ mod game;
|
||||||
mod labled_switch;
|
mod labled_switch;
|
||||||
mod ui;
|
mod ui;
|
||||||
|
|
||||||
use crate::ui::build_ui;
|
use crate::ui::menu::MenuScene;
|
||||||
|
|
||||||
use gtk::prelude::*;
|
use gtk::{prelude::*, ApplicationWindow};
|
||||||
use gtk::{glib, Application};
|
use gtk::{glib, Application, gio};
|
||||||
|
|
||||||
const APP_ID: &str = "org.foxarmy.learn-hieroglyph";
|
const APP_ID: &str = "org.foxarmy.learn-hieroglyph";
|
||||||
|
// const APP: Option<RefCell<Application>> = None;//RefCell::new(Application::builder().application_id(APP_ID).build());
|
||||||
|
// pub const S: Stack = Stack::new();
|
||||||
fn main() -> glib::ExitCode {
|
fn main() -> glib::ExitCode {
|
||||||
let app = Application::builder().application_id(APP_ID).build();
|
gio::resources_register_include!("compiled.gresource")
|
||||||
|
.expect("Cannot include gresources");
|
||||||
|
|
||||||
|
// APP = Option::from(RefCell::new(Application::builder().application_id(APP_ID).build()));
|
||||||
|
// *APP.unwrap().borrow_mut() = Application::builder().application_id(APP_ID).build();
|
||||||
|
|
||||||
|
let app: Application = Application::builder().application_id(APP_ID).build();
|
||||||
|
|
||||||
|
app.connect_activate(test_ui);
|
||||||
|
|
||||||
app.connect_activate(build_ui);
|
|
||||||
|
|
||||||
app.run()
|
app.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_ui (app: &Application) {
|
||||||
|
let window: ApplicationWindow = MenuScene::new(app).into();
|
||||||
|
|
||||||
|
window.present();
|
||||||
|
|
||||||
|
println!("{}", app.windows().len());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
use glib::subclass::InitializingObject;
|
||||||
|
use gtk::subclass::prelude::*;
|
||||||
|
use gtk::{glib, Button, CompositeTemplate};
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(CompositeTemplate, Default)]
|
||||||
|
#[template(resource = "/org/foxarmy/learn-hieroglyph/memory_cards_settings.ui.xml")]
|
||||||
|
pub struct MemoryCardsSetupScene {
|
||||||
|
#[template_child]
|
||||||
|
pub edit_button: TemplateChild<Button>,
|
||||||
|
#[template_child]
|
||||||
|
pub start_button: TemplateChild<Button>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[glib::object_subclass]
|
||||||
|
impl ObjectSubclass for MemoryCardsSetupScene {
|
||||||
|
const NAME: &'static str = "MemoryCardsSetupScene";
|
||||||
|
type Type = super::MemoryCardsSetupScene;
|
||||||
|
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 MemoryCardsSetupScene {
|
||||||
|
fn constructed(&self) {
|
||||||
|
|
||||||
|
self.parent_constructed();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WidgetImpl for MemoryCardsSetupScene {}
|
||||||
|
|
||||||
|
impl WindowImpl for MemoryCardsSetupScene {}
|
||||||
|
|
||||||
|
impl ApplicationWindowImpl for MemoryCardsSetupScene {}
|
|
@ -0,0 +1,17 @@
|
||||||
|
mod imp;
|
||||||
|
|
||||||
|
use glib::Object;
|
||||||
|
use gtk::{gio, glib, Application};
|
||||||
|
|
||||||
|
glib::wrapper! {
|
||||||
|
pub struct MemoryCardsSetupScene(ObjectSubclass<imp::MemoryCardsSetupScene>)
|
||||||
|
@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 MemoryCardsSetupScene {
|
||||||
|
pub fn new(app: &Application) -> Self {
|
||||||
|
Object::builder().property("application", app).build()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,130 @@
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
use crate::{game::*, APP_ID};
|
||||||
|
|
||||||
|
use gtk::glib::clone;
|
||||||
|
use gtk::prelude::*;
|
||||||
|
use glib::subclass::InitializingObject;
|
||||||
|
use gtk::gio::Settings;
|
||||||
|
use gtk::subclass::prelude::*;
|
||||||
|
use gtk::{glib, Label, Entry, CompositeTemplate};
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(CompositeTemplate, Default)]
|
||||||
|
#[template(resource = "/org/foxarmy/learn-hieroglyph/guessing.ui.xml")]
|
||||||
|
pub struct GuessingScene {
|
||||||
|
#[template_child]
|
||||||
|
pub question_label: TemplateChild<Label>,
|
||||||
|
#[template_child]
|
||||||
|
pub answer_entry: TemplateChild<Entry>,
|
||||||
|
#[template_child]
|
||||||
|
pub stats_label: TemplateChild<Label>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[glib::object_subclass]
|
||||||
|
impl ObjectSubclass for GuessingScene {
|
||||||
|
const NAME: &'static str = "GuessingScene";
|
||||||
|
type Type = super::GuessingScene;
|
||||||
|
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 GuessingScene {
|
||||||
|
fn constructed(&self) {
|
||||||
|
self.parent_constructed();
|
||||||
|
|
||||||
|
let settings = Settings::new(APP_ID);
|
||||||
|
|
||||||
|
let ktr: bool = settings.boolean("is-ktr-enabled");
|
||||||
|
let rtk: bool = settings.boolean("is-rtk-enabled");
|
||||||
|
let hiragana: bool = settings.boolean("is-hiragana-enabled");
|
||||||
|
let katakana: bool = settings.boolean("is-katakana-enabled");
|
||||||
|
|
||||||
|
let question: RefCell<Hieroglyph> = RefCell::new(ask(ktr, rtk, hiragana, katakana));
|
||||||
|
let exact_kana: RefCell<Kanas> = RefCell::new(if hiragana && katakana {
|
||||||
|
if rand::thread_rng().gen_bool(0.5) {
|
||||||
|
Kanas::Hiragana
|
||||||
|
} else {
|
||||||
|
Kanas::Katakana
|
||||||
|
}
|
||||||
|
} else if hiragana {
|
||||||
|
Kanas::Hiragana
|
||||||
|
} else {
|
||||||
|
Kanas::Katakana
|
||||||
|
});
|
||||||
|
|
||||||
|
let correct_answer: RefCell<Hieroglyph> = RefCell::new(get_kana_pair_for_hieroglyph(
|
||||||
|
match question.borrow().get_kana() {
|
||||||
|
Kanas::Romaji => match exact_kana.borrow().deref() {
|
||||||
|
Kanas::Hiragana => &Kanas::Hiragana,
|
||||||
|
Kanas::Katakana => &Kanas::Katakana,
|
||||||
|
_ => panic!("HOW DID YOU GET HERE?!"),
|
||||||
|
},
|
||||||
|
_ => &Kanas::Romaji,
|
||||||
|
},
|
||||||
|
&question.borrow(),
|
||||||
|
));
|
||||||
|
|
||||||
|
let binding = generate_question_text(&question.borrow(), exact_kana.borrow().deref());
|
||||||
|
let text: &str = &(binding.as_str());
|
||||||
|
self.question_label.set_label(text);
|
||||||
|
|
||||||
|
let stats: RefCell<(u32, u32)> = RefCell::new((0, 0));
|
||||||
|
|
||||||
|
let question_label_binding = &self.question_label.get();
|
||||||
|
let answer_entry_binding = &self.answer_entry.get();
|
||||||
|
let stats_label_binding = &self.stats_label.get();
|
||||||
|
|
||||||
|
let iteration = clone!(@strong stats,
|
||||||
|
@strong question_label_binding as question_label,
|
||||||
|
@strong answer_entry_binding as answer_entry,
|
||||||
|
@strong stats_label_binding as stats_label => move |_entry: &Entry| {
|
||||||
|
let answer: &String = &answer_entry.text().to_string();
|
||||||
|
println!("{} <-> {}? = {}", answer, correct_answer.borrow().to_string(), *answer == correct_answer.borrow().to_string());
|
||||||
|
*stats.borrow_mut() = if *answer == correct_answer.borrow().to_string() { (stats.borrow().0 + 1, stats.borrow().1) } else {(stats.borrow().0, stats.borrow().1 + 1)};
|
||||||
|
stats_label.set_label(format!("Correct|Incorrect: {}|{} ({:.2}%)", stats.borrow().0, stats.borrow().1, 100.0 * f64::from(stats.borrow().0) / f64::from(stats.borrow().0 + stats.borrow().1)).as_str());
|
||||||
|
*question.borrow_mut() = ask(ktr, rtk, hiragana, katakana);
|
||||||
|
*exact_kana.borrow_mut() =
|
||||||
|
if hiragana && katakana {
|
||||||
|
if rand::thread_rng().gen_bool(0.5) {Kanas::Hiragana} else {Kanas::Katakana}
|
||||||
|
} else if hiragana {
|
||||||
|
Kanas::Hiragana
|
||||||
|
} else {
|
||||||
|
Kanas::Katakana
|
||||||
|
};
|
||||||
|
*correct_answer.borrow_mut() = get_kana_pair_for_hieroglyph(
|
||||||
|
match question.borrow().get_kana() {
|
||||||
|
Kanas::Romaji => match exact_kana.borrow().deref() {
|
||||||
|
Kanas::Hiragana => &Kanas::Hiragana,
|
||||||
|
Kanas::Katakana => &Kanas::Katakana,
|
||||||
|
_ => panic!("HOW DID YOU GET HERE?!")
|
||||||
|
},
|
||||||
|
_ => &Kanas::Romaji
|
||||||
|
},
|
||||||
|
&question.borrow()
|
||||||
|
);
|
||||||
|
let binding = generate_question_text(&question.borrow(), exact_kana.borrow().deref());
|
||||||
|
let text: &str = &(binding.as_str());
|
||||||
|
question_label.set_label(text);
|
||||||
|
answer_entry.set_text("");
|
||||||
|
});
|
||||||
|
|
||||||
|
self.answer_entry.connect_activate(iteration);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WidgetImpl for GuessingScene {}
|
||||||
|
|
||||||
|
impl WindowImpl for GuessingScene {}
|
||||||
|
|
||||||
|
impl ApplicationWindowImpl for GuessingScene {}
|
|
@ -1,154 +1,17 @@
|
||||||
use crate::game::*;
|
mod imp;
|
||||||
|
|
||||||
use crate::APP_ID;
|
use glib::Object;
|
||||||
|
use gtk::{gio, glib, Application};
|
||||||
|
|
||||||
use gio::Settings;
|
glib::wrapper! {
|
||||||
use gtk::{gio, prelude::*, Entry, Label};
|
pub struct GuessingScene(ObjectSubclass<imp::GuessingScene>)
|
||||||
use gtk::{glib::clone, ApplicationWindow, Box};
|
@extends gtk::ApplicationWindow, gtk::Window, gtk::Widget,
|
||||||
use rand::prelude::*;
|
@implements gio::ActionGroup, gio::ActionMap, gtk::Accessible, gtk::Buildable,
|
||||||
use std::cell::RefCell;
|
gtk::ConstraintTarget, gtk::Native, gtk::Root, gtk::ShortcutManager;
|
||||||
use std::ops::Deref;
|
|
||||||
|
|
||||||
fn random_kana(hiragana: bool, katakana: bool) -> Hieroglyph {
|
|
||||||
if hiragana && katakana {
|
|
||||||
generate_random_hieroglyph(if rand::thread_rng().gen_bool(0.5) {
|
|
||||||
Kanas::Katakana
|
|
||||||
} else {
|
|
||||||
Kanas::Hiragana
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
generate_random_hieroglyph(if hiragana {
|
|
||||||
Kanas::Hiragana
|
|
||||||
} else {
|
|
||||||
Kanas::Katakana
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ask(ktr: bool, rtk: bool, hiragana: bool, katakana: bool) -> Hieroglyph {
|
impl GuessingScene {
|
||||||
if ktr && rtk {
|
pub fn new(app: &Application) -> Self {
|
||||||
return if rand::thread_rng().gen_bool(0.5) {
|
Object::builder().property("application", app).build()
|
||||||
random_kana(hiragana, katakana)
|
|
||||||
} else {
|
|
||||||
generate_random_hieroglyph(Kanas::Romaji)
|
|
||||||
};
|
|
||||||
} else if ktr {
|
|
||||||
return random_kana(hiragana, katakana);
|
|
||||||
} else {
|
|
||||||
return generate_random_hieroglyph(Kanas::Romaji);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_question_text(question: &Hieroglyph, exact_kana: &Kanas) -> String {
|
|
||||||
return String::from(match question.get_kana() {
|
|
||||||
Kanas::Romaji => match exact_kana {
|
|
||||||
Kanas::Hiragana => {
|
|
||||||
format!("Name corresponding hiragana for {}", question.to_string())
|
|
||||||
}
|
|
||||||
Kanas::Katakana => {
|
|
||||||
format!("Name corresponding katakana for {}", question.to_string())
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
panic!("HOW DID YOU GET HERE!?");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Kanas::Hiragana => {
|
|
||||||
format!(
|
|
||||||
"Name corresponding romaji for hiragana {}",
|
|
||||||
question.to_string()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Kanas::Katakana => {
|
|
||||||
format!(
|
|
||||||
"Name corresponding romaji for katakana {}",
|
|
||||||
question.to_string()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build_game(_w: &RefCell<ApplicationWindow>) -> Box {
|
|
||||||
let game: Box = Box::builder()
|
|
||||||
.orientation(gtk::Orientation::Vertical)
|
|
||||||
.build();
|
|
||||||
let mut question_label: RefCell<Label> =
|
|
||||||
RefCell::new(Label::builder().label("placeholder").build());
|
|
||||||
let entry: Entry = Entry::builder().placeholder_text("Answer").build();
|
|
||||||
let mut counter_label: RefCell<Label> =
|
|
||||||
RefCell::new(Label::builder().label("Correct|incorrect: 0|0").build());
|
|
||||||
let stats: RefCell<(u32, u32)> = RefCell::new((0, 0));
|
|
||||||
let settings: Settings = Settings::new(APP_ID);
|
|
||||||
|
|
||||||
let ktr: bool = settings.boolean("is-ktr-enabled");
|
|
||||||
let rtk: bool = settings.boolean("is-rtk-enabled");
|
|
||||||
let hiragana: bool = settings.boolean("is-hiragana-enabled");
|
|
||||||
let katakana: bool = settings.boolean("is-katakana-enabled");
|
|
||||||
|
|
||||||
let question: RefCell<Hieroglyph> = RefCell::new(ask(ktr, rtk, hiragana, katakana));
|
|
||||||
let exact_kana: RefCell<Kanas> = RefCell::new(if hiragana && katakana {
|
|
||||||
if rand::thread_rng().gen_bool(0.5) {
|
|
||||||
Kanas::Hiragana
|
|
||||||
} else {
|
|
||||||
Kanas::Katakana
|
|
||||||
}
|
|
||||||
} else if hiragana {
|
|
||||||
Kanas::Hiragana
|
|
||||||
} else {
|
|
||||||
Kanas::Katakana
|
|
||||||
});
|
|
||||||
|
|
||||||
let correct_answer: RefCell<Hieroglyph> = RefCell::new(get_kana_pair_for_hieroglyph(
|
|
||||||
match question.borrow().get_kana() {
|
|
||||||
Kanas::Romaji => match exact_kana.borrow().deref() {
|
|
||||||
Kanas::Hiragana => &Kanas::Hiragana,
|
|
||||||
Kanas::Katakana => &Kanas::Katakana,
|
|
||||||
_ => panic!("HOW DID YOU GET HERE?!"),
|
|
||||||
},
|
|
||||||
_ => &Kanas::Romaji,
|
|
||||||
},
|
|
||||||
&question.borrow(),
|
|
||||||
));
|
|
||||||
|
|
||||||
let binding = generate_question_text(&question.borrow(), exact_kana.borrow().deref());
|
|
||||||
let text: &str = &(binding.as_str());
|
|
||||||
question_label.borrow_mut().set_label(text);
|
|
||||||
|
|
||||||
let iteration = clone!( @strong question_label, @strong counter_label, @strong stats, @strong exact_kana => move |entry: &Entry| {
|
|
||||||
let answer: &String = &entry.text().to_string();
|
|
||||||
println!("{} <-> {}? = {}", answer, correct_answer.borrow().to_string(), *answer == correct_answer.borrow().to_string());
|
|
||||||
*stats.borrow_mut() = if *answer == correct_answer.borrow().to_string() { (stats.borrow().0 + 1, stats.borrow().1) } else {(stats.borrow().0, stats.borrow().1 + 1)};
|
|
||||||
counter_label.borrow_mut().set_label(format!("Correct|Incorrect: {}|{} ({:.2}%)", stats.borrow().0, stats.borrow().1, 100.0 * f64::from(stats.borrow().0) / f64::from(stats.borrow().0 + stats.borrow().1)).as_str());
|
|
||||||
*question.borrow_mut() = ask(ktr, rtk, hiragana, katakana);
|
|
||||||
*exact_kana.borrow_mut() =
|
|
||||||
if hiragana && katakana {
|
|
||||||
if rand::thread_rng().gen_bool(0.5) {Kanas::Hiragana} else {Kanas::Katakana}
|
|
||||||
} else if hiragana {
|
|
||||||
Kanas::Hiragana
|
|
||||||
} else {
|
|
||||||
Kanas::Katakana
|
|
||||||
};
|
|
||||||
*correct_answer.borrow_mut() = get_kana_pair_for_hieroglyph(
|
|
||||||
match question.borrow().get_kana() {
|
|
||||||
Kanas::Romaji => match exact_kana.borrow().deref() {
|
|
||||||
Kanas::Hiragana => &Kanas::Hiragana,
|
|
||||||
Kanas::Katakana => &Kanas::Katakana,
|
|
||||||
_ => panic!("HOW DID YOU GET HERE?!")
|
|
||||||
},
|
|
||||||
_ => &Kanas::Romaji
|
|
||||||
},
|
|
||||||
&question.borrow()
|
|
||||||
);
|
|
||||||
let binding = generate_question_text(&question.borrow(), exact_kana.borrow().deref());
|
|
||||||
let text: &str = &(binding.as_str());
|
|
||||||
question_label.borrow_mut().set_label(text);
|
|
||||||
entry.set_text("");
|
|
||||||
});
|
|
||||||
|
|
||||||
entry.connect_activate(iteration);
|
|
||||||
|
|
||||||
game.append(question_label.get_mut());
|
|
||||||
game.append(&entry);
|
|
||||||
game.append(counter_label.get_mut());
|
|
||||||
|
|
||||||
game
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
use crate::ui::{guessing::GuessingScene, cards::MemoryCardsSetupScene};
|
||||||
|
|
||||||
|
use glib::subclass::InitializingObject;
|
||||||
|
use gtk::glib::closure_local;
|
||||||
|
use gtk::subclass::prelude::*;
|
||||||
|
use gtk::{glib, prelude::*, Box, Button, CompositeTemplate};
|
||||||
|
|
||||||
|
#[derive(CompositeTemplate, Default)]
|
||||||
|
#[template(resource = "/org/foxarmy/learn-hieroglyph/menu.ui.xml")]
|
||||||
|
pub struct MenuScene {
|
||||||
|
#[template_child]
|
||||||
|
pub content: TemplateChild<Box>,
|
||||||
|
#[template_child]
|
||||||
|
pub hiragana_and_katakana: TemplateChild<Button>,
|
||||||
|
#[template_child]
|
||||||
|
pub memory_cards: TemplateChild<Button>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[glib::object_subclass]
|
||||||
|
impl ObjectSubclass for MenuScene {
|
||||||
|
const NAME: &'static str = "MenuScene";
|
||||||
|
type Type = super::MenuScene;
|
||||||
|
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 MenuScene {
|
||||||
|
fn constructed(&self) {
|
||||||
|
self.parent_constructed();
|
||||||
|
|
||||||
|
let binding = self.obj();
|
||||||
|
|
||||||
|
self.hiragana_and_katakana.connect_closure(
|
||||||
|
"clicked",
|
||||||
|
false,
|
||||||
|
closure_local!(@strong binding => move |_button: &Button| {
|
||||||
|
let new_win: GuessingScene = GuessingScene::new(&binding.application().unwrap());
|
||||||
|
new_win.present();
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
self.memory_cards.connect_closure(
|
||||||
|
"clicked",
|
||||||
|
false,
|
||||||
|
closure_local!(@strong binding => move |_button: &Button| {
|
||||||
|
let new_win: MemoryCardsSetupScene = MemoryCardsSetupScene::new(&binding.application().unwrap());
|
||||||
|
new_win.present();
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WidgetImpl for MenuScene {}
|
||||||
|
|
||||||
|
impl WindowImpl for MenuScene {
|
||||||
|
fn activate_default(&self) {
|
||||||
|
self.parent_activate_default();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApplicationWindowImpl for MenuScene {}
|
|
@ -1,80 +1,17 @@
|
||||||
use crate::ui::guessing::build_game;
|
mod imp;
|
||||||
|
|
||||||
use crate::APP_ID;
|
use glib::Object;
|
||||||
|
use gtk::{gio, glib, Application};
|
||||||
|
|
||||||
use gio::Settings;
|
glib::wrapper! {
|
||||||
use gtk::{gio, prelude::*, Button};
|
pub struct MenuScene(ObjectSubclass<imp::MenuScene>)
|
||||||
use gtk::{glib::clone, ApplicationWindow, Box};
|
@extends gtk::ApplicationWindow, gtk::Window, gtk::Widget,
|
||||||
use std::cell::{Cell, RefCell};
|
@implements gio::ActionGroup, gio::ActionMap, gtk::Accessible, gtk::Buildable,
|
||||||
|
gtk::ConstraintTarget, gtk::Native, gtk::Root, gtk::ShortcutManager;
|
||||||
use crate::labled_switch;
|
}
|
||||||
|
|
||||||
pub fn build_menu(w: &RefCell<ApplicationWindow>) -> Box {
|
impl MenuScene {
|
||||||
let menu: Box = Box::builder()
|
pub fn new(app: &Application) -> Self {
|
||||||
.orientation(gtk::Orientation::Vertical)
|
Object::builder().property("application", app).build()
|
||||||
.halign(gtk::Align::Center)
|
}
|
||||||
.build();
|
|
||||||
|
|
||||||
let settings_container: Box = Box::builder()
|
|
||||||
.orientation(gtk::Orientation::Vertical)
|
|
||||||
.valign(gtk::Align::Start)
|
|
||||||
.halign(gtk::Align::Start)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let gamemode_settings_container: Box = Box::builder()
|
|
||||||
.orientation(gtk::Orientation::Vertical)
|
|
||||||
.valign(gtk::Align::Start)
|
|
||||||
.halign(gtk::Align::Start)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let hiragana_setting_container: Box = Box::builder()
|
|
||||||
.orientation(gtk::Orientation::Horizontal)
|
|
||||||
.valign(gtk::Align::Center)
|
|
||||||
.halign(gtk::Align::Center)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let katakana_setting_container: Box = Box::builder()
|
|
||||||
.orientation(gtk::Orientation::Horizontal)
|
|
||||||
.valign(gtk::Align::Center)
|
|
||||||
.halign(gtk::Align::Center)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let start_button: Button = Button::builder().label("Start!").build();
|
|
||||||
|
|
||||||
let mut settings = Cell::new(Settings::new(APP_ID));
|
|
||||||
|
|
||||||
start_button.connect_clicked(clone!( @strong w => move |_| {
|
|
||||||
w.borrow_mut().set_child(Some(&build_game(&w)))
|
|
||||||
}));
|
|
||||||
//////////////////kana to romaji setting////////////////////////////
|
|
||||||
let ktr_switch = labled_switch::build("enable あ->a");
|
|
||||||
gamemode_settings_container.append(&ktr_switch.0);
|
|
||||||
|
|
||||||
////////////////romaji to kana setting///////////////////////////////
|
|
||||||
let rtk_switch = labled_switch::build("enable a->あ");
|
|
||||||
gamemode_settings_container.append(&rtk_switch.0);
|
|
||||||
////////////////hiragana enable setting/////////////////////////////
|
|
||||||
let hiragana_switch = labled_switch::build("enable hiragana");
|
|
||||||
hiragana_setting_container.append(&hiragana_switch.0);
|
|
||||||
////////////////katakana enable setting/////////////////////////////
|
|
||||||
let katakana_switch = labled_switch::build("enable katakana");
|
|
||||||
katakana_setting_container.append(&katakana_switch.0);
|
|
||||||
|
|
||||||
let s = settings.get_mut();
|
|
||||||
s.bind("is-ktr-enabled", &ktr_switch.1, "active").build();
|
|
||||||
s.bind("is-rtk-enabled", &rtk_switch.1, "active").build();
|
|
||||||
s.bind("is-hiragana-enabled", &hiragana_switch.1, "active")
|
|
||||||
.build();
|
|
||||||
s.bind("is-katakana-enabled", &katakana_switch.1, "active")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
settings_container.append(&gamemode_settings_container);
|
|
||||||
settings_container.append(&hiragana_setting_container);
|
|
||||||
settings_container.append(&katakana_setting_container);
|
|
||||||
|
|
||||||
menu.append(&settings_container);
|
|
||||||
|
|
||||||
menu.append(&start_button);
|
|
||||||
|
|
||||||
menu
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,24 @@
|
||||||
mod guessing;
|
pub(crate) mod menu;
|
||||||
mod menu;
|
pub(crate) mod guessing;
|
||||||
|
mod cards;
|
||||||
|
|
||||||
use crate::ui::menu::build_menu;
|
// use crate::ui::menu::build_menu_scene;
|
||||||
|
|
||||||
use gtk::prelude::*;
|
// use gtk::prelude::*;
|
||||||
use gtk::{Application, ApplicationWindow};
|
// use gtk::{Application, ApplicationWindow};
|
||||||
use std::cell::RefCell;
|
// use std::cell::RefCell;
|
||||||
|
|
||||||
pub fn build_ui(app: &Application) {
|
// pub fn build_ui(app: &Application) {
|
||||||
let mut window: RefCell<ApplicationWindow> = RefCell::new(
|
// let mut window: RefCell<ApplicationWindow> = RefCell::new(
|
||||||
ApplicationWindow::builder()
|
// ApplicationWindow::builder()
|
||||||
.application(app)
|
// .application(app)
|
||||||
.title("Test")
|
// .title("Test")
|
||||||
.build(),
|
// .build(),
|
||||||
);
|
// );
|
||||||
|
|
||||||
let menu = build_menu(&window);
|
// // let menu = build_menu_scene(&window);
|
||||||
|
|
||||||
window.get_mut().set_child(Some(&menu));
|
// // window.get_mut().set_child(Some(&menu));
|
||||||
|
|
||||||
window.get_mut().present();
|
// window.get_mut().present();
|
||||||
}
|
// }
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="hiragana_and_katakana">
|
||||||
|
<property name="label">Practice Hiragana And Katakana</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="memory_cards">
|
||||||
|
<property name="label">Practice Kana with memory cards</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
Loading…
Reference in New Issue