Compare commits
28 Commits
81a8d9b2c6
...
cbde9a8af1
Author | SHA1 | Date | |
---|---|---|---|
doryan | cbde9a8af1 | ||
doryan | 81b22a14c9 | ||
doryan | ebf7d9b85c | ||
doryan | d92b2419e0 | ||
doryan | c9dbe4ba6e | ||
doryan | a2cb65d570 | ||
doryan | d3787b2283 | ||
doryan | ade98179f7 | ||
doryan | 7157ffd55f | ||
doryan | 09b05e7fa7 | ||
doryan | 18e857b40c | ||
doryan | 0d676820c6 | ||
doryan | 0aab9e9ebe | ||
doryan | b7b890ecb3 | ||
doryan | 01f65376d0 | ||
doryan | 33226ecae2 | ||
doryan | bd394b9bf4 | ||
doryan | cb2a52cc7b | ||
doryan | 5972d589fe | ||
doryan | 1be7125ecf | ||
doryan | f3ece276f1 | ||
doryan | 561f6fc065 | ||
doryan | a8e43df99e | ||
doryan | 4b5589392d | ||
doryan | acf1d9f30b | ||
doryan | fd2f605978 | ||
doryan | 54a4b44780 | ||
doryan | 2e543a22c8 |
|
@ -463,12 +463,6 @@ version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hermit-abi"
|
|
||||||
version = "0.3.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.2.6"
|
version = "2.2.6"
|
||||||
|
@ -523,9 +517,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.153"
|
version = "0.2.155"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
|
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
|
@ -551,16 +545,6 @@ dependencies = [
|
||||||
"adler",
|
"adler",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num_cpus"
|
|
||||||
version = "1.16.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
|
||||||
dependencies = [
|
|
||||||
"hermit-abi",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.32.2"
|
version = "0.32.2"
|
||||||
|
@ -803,21 +787,20 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.37.0"
|
version = "1.39.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
|
checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"num_cpus",
|
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-macros"
|
name = "tokio-macros"
|
||||||
version = "2.2.0"
|
version = "2.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
|
checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
|
@ -9,5 +9,5 @@ edition = "2021"
|
||||||
adw = { version = "0.6.0", package = "libadwaita", features = ["v1_4"] }
|
adw = { version = "0.6.0", package = "libadwaita", features = ["v1_4"] }
|
||||||
bitvec = "1.0.1"
|
bitvec = "1.0.1"
|
||||||
gtk4 = "0.8.1"
|
gtk4 = "0.8.1"
|
||||||
tokio = { version = "1.0.0", features = ["rt", "time", "rt-multi-thread", "macros"] }
|
tokio = { version = "1.39.2", features = ["rt", "time", "rt-multi-thread", "macros", "sync"] }
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use gtk::*;
|
use gtk::*;
|
||||||
use gtk4 as gtk;
|
use gtk4 as gtk;
|
||||||
|
|
||||||
pub fn state_controller(switch: &Switch, label: &Label) -> () {
|
pub fn state_controller(switch: &Switch, label: &Label) {
|
||||||
if switch.state() == true {
|
if switch.state() {
|
||||||
label.set_label("Режим: проверка");
|
label.set_label("Режим: проверка");
|
||||||
} else {
|
} else {
|
||||||
label.set_label("Режим: кодирование");
|
label.set_label("Режим: кодирование");
|
||||||
|
|
|
@ -4,7 +4,7 @@ impl<F, C> EventHandler<F, C>
|
||||||
where
|
where
|
||||||
F: Fn(&C) + FnOnce(&C) + FnMut(&C),
|
F: Fn(&C) + FnOnce(&C) + FnMut(&C),
|
||||||
{
|
{
|
||||||
pub fn new(component: C, callback: F) -> EventHandler<F, C> {
|
pub fn new(component: C, callback: F) -> Self {
|
||||||
Self {
|
Self {
|
||||||
component,
|
component,
|
||||||
callback,
|
callback,
|
||||||
|
@ -13,7 +13,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait BtnEventHandler {
|
pub trait BtnEventHandler {
|
||||||
fn on_click(self) -> ();
|
fn on_click(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F, C> BtnEventHandler for EventHandler<F, C>
|
impl<F, C> BtnEventHandler for EventHandler<F, C>
|
||||||
|
@ -21,7 +21,7 @@ where
|
||||||
F: Fn(&C) + FnOnce(&C) + FnMut(&C) + 'static,
|
F: Fn(&C) + FnOnce(&C) + FnMut(&C) + 'static,
|
||||||
C: ButtonExt + WidgetExt,
|
C: ButtonExt + WidgetExt,
|
||||||
{
|
{
|
||||||
fn on_click(self) -> () {
|
fn on_click(self) {
|
||||||
self.component
|
self.component
|
||||||
.connect_clicked(move |button| (self.callback)(button));
|
.connect_clicked(move |button| (self.callback)(button));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{gtk::prelude::*, model::models::*, view::components::switch::SwitchExt};
|
use crate::{gtk::prelude::*, model::models::*, view::components::switch::SwitchExt};
|
||||||
|
|
||||||
pub trait SwEventHandler {
|
pub trait SwEventHandler {
|
||||||
fn on_toggle(self) -> ();
|
fn on_toggle(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F, C> SwEventHandler for EventHandler<F, C>
|
impl<F, C> SwEventHandler for EventHandler<F, C>
|
||||||
|
@ -9,7 +9,7 @@ where
|
||||||
F: Fn(&C) + FnOnce(&C) + FnMut(&C) + 'static,
|
F: Fn(&C) + FnOnce(&C) + FnMut(&C) + 'static,
|
||||||
C: SwitchExt + WidgetExt,
|
C: SwitchExt + WidgetExt,
|
||||||
{
|
{
|
||||||
fn on_toggle(self) -> () {
|
fn on_toggle(self) {
|
||||||
self.component
|
self.component
|
||||||
.connect_state_notify(move |switch| (self.callback)(switch));
|
.connect_state_notify(move |switch| (self.callback)(switch));
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ pub fn hamming(raw_input: String, mode: HammingMode) -> Result<String, String> {
|
||||||
HammingMode::Decrypt => hamming_decrypt_data(&prepared_data, &mut data, length_of_code),
|
HammingMode::Decrypt => hamming_decrypt_data(&prepared_data, &mut data, length_of_code),
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(data);
|
Ok(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ pub fn hamming_decrypt_data(data: &Vec<u8>, result_string: &mut String, length_o
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0;
|
.0;
|
||||||
|
|
||||||
let uncorrect_code: String = from_vec_bits_to_string(&data_bits);
|
let uncorrect_code: String = from_vec_bits_to_string(data_bits);
|
||||||
let correct_code: String = from_vec_bits_to_string(
|
let correct_code: String = from_vec_bits_to_string(
|
||||||
data_bits
|
data_bits
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -125,8 +125,8 @@ pub fn hamming_decrypt_data(data: &Vec<u8>, result_string: &mut String, length_o
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if data.len() > 0 {
|
if !data.is_empty() {
|
||||||
if errors.len() == 0 {
|
if errors.is_empty() {
|
||||||
result_string.push_str("Все коды корректны.");
|
result_string.push_str("Все коды корректны.");
|
||||||
} else {
|
} else {
|
||||||
result_string.push_str(errors.as_str());
|
result_string.push_str(errors.as_str());
|
||||||
|
|
|
@ -1,15 +1,31 @@
|
||||||
|
#[allow(non_snake_case)]
|
||||||
pub fn reactive_resistance_of_capacitor(Cm: f64, L: f64, f: f64) -> f64 {
|
pub fn reactive_resistance_of_capacitor(Cm: f64, L: f64, f: f64) -> f64 {
|
||||||
|
if f == 0.0 || Cm == 0.0 || L == 0.0 {
|
||||||
|
0.0
|
||||||
|
} else {
|
||||||
1f64 / (2f64 * std::f64::consts::PI * f * Cm * L)
|
1f64 / (2f64 * std::f64::consts::PI * f * Cm * L)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
pub fn full_resistance_of_capacitor(Xc: f64, Rs: f64, Rm: f64, L: f64) -> f64 {
|
pub fn full_resistance_of_capacitor(Xc: f64, Rs: f64, Rm: f64, L: f64) -> f64 {
|
||||||
(Xc.powf(2f64) + (Rs + Rm * L).powf(2f64)).sqrt()
|
(Xc.powf(2f64) + (Rs + Rm * L).powf(2f64)).sqrt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
pub fn voltage_from_signal_source(Vs: f64, Xc: f64, Z: f64) -> f64 {
|
pub fn voltage_from_signal_source(Vs: f64, Xc: f64, Z: f64) -> f64 {
|
||||||
|
if Z == 0.0 {
|
||||||
|
0.0
|
||||||
|
} else {
|
||||||
(Vs * Xc) / Z
|
(Vs * Xc) / Z
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
pub fn coef_of_signal_reduce(Vs: f64, V: f64) -> f64 {
|
pub fn coef_of_signal_reduce(Vs: f64, V: f64) -> f64 {
|
||||||
|
if V == 0.0 {
|
||||||
|
0.0
|
||||||
|
} else {
|
||||||
Vs / V
|
Vs / V
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ pub fn start_hamming_algorithm(input: &TextView, output: &TextView, mode: bool)
|
||||||
.parse()
|
.parse()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let operation = if mode == false {
|
let operation = if mode {
|
||||||
HammingMode::Encrypt
|
HammingMode::Encrypt
|
||||||
} else {
|
} else {
|
||||||
HammingMode::Decrypt
|
HammingMode::Decrypt
|
||||||
|
|
|
@ -1,119 +1,44 @@
|
||||||
use gtk4 as gtk;
|
use gtk4 as gtk;
|
||||||
|
|
||||||
use crate::controller::model_utils::signal_reducer::*;
|
use std::{num::ParseFloatError, str::FromStr};
|
||||||
use crate::model::models::SchemeCharacteristics;
|
|
||||||
use gtk::{prelude::*, *};
|
|
||||||
|
|
||||||
pub fn check_characteristics(
|
use gtk::{
|
||||||
raw_characteristics: &Vec<TextView>,
|
prelude::{TextBufferExt, TextViewExt},
|
||||||
all_inputs_data: &mut Vec<f64>,
|
TextBuffer,
|
||||||
output: &mut String,
|
};
|
||||||
) -> bool {
|
|
||||||
for input in raw_characteristics {
|
|
||||||
let (iter_start, iter_end) = input.buffer().bounds();
|
|
||||||
let parsed_input: Result<f64, _> = input
|
|
||||||
.buffer()
|
|
||||||
.text(&iter_start, &iter_end, false)
|
|
||||||
.to_string()
|
|
||||||
.trim()
|
|
||||||
.parse();
|
|
||||||
|
|
||||||
match parsed_input {
|
use crate::{model::models::SignalReduce, view::components::input::Input};
|
||||||
Ok(int) => {
|
|
||||||
all_inputs_data.push(int);
|
|
||||||
println!("{:?}", int);
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
if output.is_empty() {
|
|
||||||
output.push_str("Введите пожалуйста числа в полях");
|
|
||||||
println!("{:?}", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
!output.is_empty()
|
pub fn get_error_message(error_instance: ParseFloatError) -> Option<&'static str> {
|
||||||
|
match error_instance.to_string().as_str() {
|
||||||
|
"cannot parse float from empty string" => Some("Вы не ввели данные в поле/-я"),
|
||||||
|
"invalid float literal" => Some("Вы ввели не корректные данные в поле/-я"),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_algorithm(
|
pub fn parse_fields(all_inputs: Vec<Input>) -> Result<SignalReduce, ParseFloatError> {
|
||||||
error_log_label: &Label,
|
let mut values: [f64; 6] = [0f64; 6];
|
||||||
raw_characteristics: &Vec<TextView>,
|
|
||||||
table: &Frame,
|
|
||||||
header: &ListBoxRow,
|
|
||||||
) {
|
|
||||||
let mut all_inputs_data: Vec<f64> = Vec::new();
|
|
||||||
let mut output: String = String::new();
|
|
||||||
|
|
||||||
if !check_characteristics(raw_characteristics, &mut all_inputs_data, &mut output) {
|
for (i, input) in all_inputs.iter().enumerate() {
|
||||||
error_log_label.set_text(output.as_str());
|
let input_text_buffer: TextBuffer = input.clone().get_input().buffer();
|
||||||
} else {
|
let try_extract_value = f64::from_str(
|
||||||
error_log_label.set_text("");
|
input_text_buffer
|
||||||
|
.text(
|
||||||
let new_table = ListBox::builder().hexpand(true).halign(Align::Fill).build();
|
&input_text_buffer.start_iter(),
|
||||||
|
&input_text_buffer.end_iter(),
|
||||||
new_table.append(header);
|
false,
|
||||||
|
)
|
||||||
let (L, Rm, Cm, Vs, Rs, f): SchemeCharacteristics = (
|
.as_str()
|
||||||
all_inputs_data[0],
|
.trim(),
|
||||||
all_inputs_data[1],
|
|
||||||
all_inputs_data[2],
|
|
||||||
all_inputs_data[3],
|
|
||||||
all_inputs_data[4],
|
|
||||||
all_inputs_data[5],
|
|
||||||
);
|
);
|
||||||
|
match try_extract_value {
|
||||||
let mut frequencies: Vec<usize> = vec![f as usize, 1usize];
|
Ok(value) => values[i] = value,
|
||||||
|
Err(error) => return Err(error),
|
||||||
frequencies.append(&mut (0..100).step_by(5).collect());
|
|
||||||
|
|
||||||
for i in frequencies {
|
|
||||||
if i == 0 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let table_row = ListBoxRow::new();
|
|
||||||
|
|
||||||
let columns = ColumnView::builder().reorderable(false).build();
|
|
||||||
|
|
||||||
let frequency_column = ColumnViewColumn::builder()
|
|
||||||
.title(format!("{i}"))
|
|
||||||
.fixed_width(200)
|
|
||||||
.expand(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let Xc: f64 = reactive_resistance_of_capacitor(Cm, L, f);
|
|
||||||
let Z: f64 = full_resistance_of_capacitor(Xc, Vs, Rm, L);
|
|
||||||
let V: f64 = voltage_from_signal_source(Vs, Xc, Z);
|
|
||||||
let xi: f64 = coef_of_signal_reduce(Vs, V);
|
|
||||||
|
|
||||||
let reactive_resistance_column = ColumnViewColumn::builder()
|
|
||||||
.title(format!("{:?}", Xc))
|
|
||||||
.fixed_width(200)
|
|
||||||
.expand(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let voltage_column = ColumnViewColumn::builder()
|
|
||||||
.title(format!("{:?}", V))
|
|
||||||
.fixed_width(200)
|
|
||||||
.expand(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let coef_column = ColumnViewColumn::builder()
|
|
||||||
.title(format!("{:?}", xi))
|
|
||||||
.fixed_width(200)
|
|
||||||
.expand(true)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
columns.append_column(&frequency_column);
|
|
||||||
columns.append_column(&reactive_resistance_column);
|
|
||||||
columns.append_column(&voltage_column);
|
|
||||||
columns.append_column(&coef_column);
|
|
||||||
|
|
||||||
table_row.set_child(Some(&columns));
|
|
||||||
|
|
||||||
new_table.append(&table_row);
|
|
||||||
|
|
||||||
table.set_child(Some(&new_table));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(SignalReduce(
|
||||||
|
values[0], values[1], values[2], values[3], values[4], values[5],
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,8 @@ mod view;
|
||||||
use controller::*;
|
use controller::*;
|
||||||
use view::view::*;
|
use view::view::*;
|
||||||
|
|
||||||
fn main() {
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
let app: adw::Application = adw::Application::builder()
|
let app: adw::Application = adw::Application::builder()
|
||||||
.application_id("com.github.gtk-rs.examples.basic")
|
.application_id("com.github.gtk-rs.examples.basic")
|
||||||
.build();
|
.build();
|
||||||
|
|
|
@ -1,2 +1,15 @@
|
||||||
pub mod builder_traits;
|
pub mod builder_traits;
|
||||||
pub mod models;
|
pub mod models;
|
||||||
|
|
||||||
|
use crate::gtk::glib;
|
||||||
|
use glib::Object;
|
||||||
|
|
||||||
|
glib::wrapper! {
|
||||||
|
pub struct ResultValue(ObjectSubclass<models::ResultValue>);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResultValue {
|
||||||
|
pub fn new(val: f64) -> Self {
|
||||||
|
Object::builder().property("value", val).build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
use std::cell::Cell;
|
||||||
|
|
||||||
|
use crate::gtk;
|
||||||
|
|
||||||
|
use glib::Properties;
|
||||||
|
use gtk::glib;
|
||||||
|
use gtk::prelude::*;
|
||||||
|
use gtk::subclass::prelude::*;
|
||||||
|
|
||||||
#[repr(usize)]
|
#[repr(usize)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum HammingMode {
|
pub enum HammingMode {
|
||||||
|
@ -10,4 +19,28 @@ pub struct EventHandler<F, C> {
|
||||||
pub(crate) callback: F,
|
pub(crate) callback: F,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type SchemeCharacteristics = (f64, f64, f64, f64, f64, f64);
|
#[derive(Default, Copy, Clone)]
|
||||||
|
pub struct SignalReduce(pub f64, pub f64, pub f64, pub f64, pub f64, pub f64);
|
||||||
|
|
||||||
|
impl SignalReduce {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Properties, Default)]
|
||||||
|
#[properties(wrapper_type = super::ResultValue)]
|
||||||
|
pub struct ResultValue {
|
||||||
|
#[property(get, set)]
|
||||||
|
value: Cell<f64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// The central trait for subclassing a GObject
|
||||||
|
#[glib::object_subclass]
|
||||||
|
impl ObjectSubclass for ResultValue {
|
||||||
|
const NAME: &'static str = "MyGtkAppCustomButton";
|
||||||
|
type Type = super::ResultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[glib::derived_properties]
|
||||||
|
impl ObjectImpl for ResultValue {}
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
use gtk4 as gtk;
|
||||||
|
|
||||||
|
use std::{collections::VecDeque, sync::LazyLock};
|
||||||
|
|
||||||
|
use gtk::{
|
||||||
|
builders::{BoxBuilder, ButtonBuilder, LabelBuilder},
|
||||||
|
prelude::{BoxExt, ObjectExt, WidgetExt},
|
||||||
|
Box, Button, Label, Revealer, RevealerTransitionType,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
event_handlers::button_event_handlers::BtnEventHandler,
|
||||||
|
model::{builder_traits::Product, models::EventHandler},
|
||||||
|
};
|
||||||
|
|
||||||
|
use tokio::{
|
||||||
|
task::{spawn, JoinHandle},
|
||||||
|
time::{sleep, Duration},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct InfoBar {
|
||||||
|
instance: Revealer,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct InfoBarBuilder {
|
||||||
|
label: LabelBuilder,
|
||||||
|
r#box: BoxBuilder,
|
||||||
|
button: ButtonBuilder,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Develop a method to safely mutate static.
|
||||||
|
// Not necessary.
|
||||||
|
static mut TASKS_QUEUE: VecDeque<JoinHandle<()>> = VecDeque::new();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Singleton pattern implementation
|
||||||
|
//
|
||||||
|
|
||||||
|
unsafe impl Send for InfoBar {}
|
||||||
|
unsafe impl Sync for InfoBar {}
|
||||||
|
|
||||||
|
static INFO_BAR_INSTANCE: LazyLock<InfoBar> = LazyLock::new(|| InfoBar {
|
||||||
|
instance: Revealer::new(),
|
||||||
|
});
|
||||||
|
|
||||||
|
impl InfoBar {
|
||||||
|
pub fn get_instance() -> &'static Self {
|
||||||
|
&INFO_BAR_INSTANCE
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_text_label(&self, text_label: Option<&str>) {
|
||||||
|
if let Some(text) = text_label {
|
||||||
|
let _ = &INFO_BAR_INSTANCE
|
||||||
|
.instance
|
||||||
|
.child()
|
||||||
|
.unwrap()
|
||||||
|
.first_child()
|
||||||
|
.unwrap()
|
||||||
|
.set_property("label", text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_reveal_child(&self, is_reveal: bool) {
|
||||||
|
let _ = &INFO_BAR_INSTANCE.instance.set_reveal_child(is_reveal);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn show_infobar(&self, duration_secs: u64) {
|
||||||
|
if !INFO_BAR_INSTANCE.instance.reveals_child() {
|
||||||
|
INFO_BAR_INSTANCE.set_reveal_child(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
let callback = spawn(async move {
|
||||||
|
sleep(Duration::from_secs(duration_secs)).await;
|
||||||
|
INFO_BAR_INSTANCE.set_reveal_child(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
if !TASKS_QUEUE.is_empty() {
|
||||||
|
TASKS_QUEUE.pop_back().unwrap().abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
TASKS_QUEUE.push_back(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Builder pattern implementation
|
||||||
|
//
|
||||||
|
|
||||||
|
impl InfoBarBuilder {
|
||||||
|
pub fn build(self) -> &'static InfoBar {
|
||||||
|
let info_bar_label = self.label.build();
|
||||||
|
let info_bar_box = self.r#box.build();
|
||||||
|
let info_bar_close_btn = self.button.build();
|
||||||
|
|
||||||
|
info_bar_label.set_hexpand(true);
|
||||||
|
|
||||||
|
info_bar_box.append(&info_bar_label);
|
||||||
|
info_bar_box.append(&info_bar_close_btn);
|
||||||
|
info_bar_box.set_widget_name("info_bar");
|
||||||
|
|
||||||
|
let info_bar: &Revealer = &INFO_BAR_INSTANCE.instance;
|
||||||
|
|
||||||
|
info_bar.set_transition_type(RevealerTransitionType::SlideUp);
|
||||||
|
info_bar.set_transition_duration(200);
|
||||||
|
|
||||||
|
info_bar.set_child(Some(&info_bar_box));
|
||||||
|
|
||||||
|
let info_bar_to_close = info_bar.clone();
|
||||||
|
|
||||||
|
EventHandler::new(info_bar_close_btn.clone(), move |_| {
|
||||||
|
info_bar_to_close.set_reveal_child(false);
|
||||||
|
})
|
||||||
|
.on_click();
|
||||||
|
|
||||||
|
&INFO_BAR_INSTANCE
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_text_label(mut self, text: &str) -> Self {
|
||||||
|
self.label = self.label.label(text);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_button_icon(mut self, icon_name: &str) -> Self {
|
||||||
|
self.button = self.button.icon_name(icon_name);
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Product<InfoBarBuilder, &'static Revealer> for InfoBar {
|
||||||
|
fn builder() -> InfoBarBuilder {
|
||||||
|
InfoBarBuilder {
|
||||||
|
label: Label::builder(),
|
||||||
|
r#box: Box::builder(),
|
||||||
|
button: Button::builder(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(self) -> &'static Revealer {
|
||||||
|
&INFO_BAR_INSTANCE.instance
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
pub mod info_bar;
|
||||||
pub mod input;
|
pub mod input;
|
||||||
pub mod pages;
|
pub mod pages;
|
||||||
pub mod switch;
|
pub mod switch;
|
||||||
|
|
|
@ -12,7 +12,7 @@ use crate::{
|
||||||
|
|
||||||
use gtk::{prelude::*, *};
|
use gtk::{prelude::*, *};
|
||||||
|
|
||||||
pub fn hamming_code_page(wrapper: &Box, info_bar: Revealer) {
|
pub fn hamming_code_page(wrapper: &Box) {
|
||||||
// input
|
// input
|
||||||
|
|
||||||
let hamming_text_view_input_label = Label::builder()
|
let hamming_text_view_input_label = Label::builder()
|
||||||
|
|
|
@ -1,21 +1,38 @@
|
||||||
use glib::property::PropertyGet;
|
use std::{cell::Cell, rc::Rc};
|
||||||
use gtk4 as gtk;
|
|
||||||
use gtk4::prelude::WidgetExt;
|
|
||||||
use std::{str::FromStr, time::Duration};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
event_handlers::button_event_handlers::BtnEventHandler,
|
event_handlers::button_event_handlers::BtnEventHandler,
|
||||||
model::{builder_traits::Product, models::*},
|
model::{
|
||||||
view::{components::input::Input, properties::*},
|
builder_traits::Product,
|
||||||
};
|
models::{EventHandler, SignalReduce},
|
||||||
use gtk::{
|
ResultValue,
|
||||||
prelude::{BoxExt, GridExt, TextBufferExt, TextViewExt},
|
},
|
||||||
Align, WrapMode, *,
|
model_utils::signal_reducer::{
|
||||||
|
coef_of_signal_reduce, full_resistance_of_capacitor, reactive_resistance_of_capacitor,
|
||||||
|
voltage_from_signal_source,
|
||||||
|
},
|
||||||
|
view::{
|
||||||
|
components::{info_bar::InfoBar, input::Input},
|
||||||
|
properties::*,
|
||||||
|
},
|
||||||
|
view_utils::signal_reduce_input_utils::{get_error_message, parse_fields},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn signal_reducing_page(wrapper: &Box, info_bar: Revealer) {
|
use gtk::{
|
||||||
let (input_height, monospace, input_alignment, input_wrapping): (i32, bool, Align, WrapMode) =
|
prelude::{BoxExt, Cast, CastNone, GridExt, ListItemExt},
|
||||||
(24, true, Align::Fill, WrapMode::Word);
|
Align, WrapMode, *,
|
||||||
|
};
|
||||||
|
use gtk4 as gtk;
|
||||||
|
|
||||||
|
pub fn signal_reducing_page(wrapper: &Box) {
|
||||||
|
let values = Rc::new(Cell::new(SignalReduce::default()));
|
||||||
|
|
||||||
|
let last_query: Vec<TreeIter> = Vec::new();
|
||||||
|
|
||||||
|
let info_bar = InfoBar::get_instance();
|
||||||
|
|
||||||
|
let (input_height, monospace, input_wrapping): (i32, bool, WrapMode) =
|
||||||
|
(24, true, WrapMode::Word);
|
||||||
|
|
||||||
let input_block: Grid = Grid::new();
|
let input_block: Grid = Grid::new();
|
||||||
|
|
||||||
|
@ -65,49 +82,123 @@ pub fn signal_reducing_page(wrapper: &Box, info_bar: Revealer) {
|
||||||
|
|
||||||
let calculate_button = Button::builder().label("Расчитать").build();
|
let calculate_button = Button::builder().label("Расчитать").build();
|
||||||
|
|
||||||
// TODO: Make asynchronious auto-hide info bar.
|
let result_table_headers_labels: [&str; 4] = ["f, МГц", "Xc, пФ", "Vп, мВ", "ζ"];
|
||||||
let test = info_bar.clone();
|
|
||||||
|
|
||||||
// let (tx, rx) = std::sync::mpsc::channel::<bool>();
|
let model = gio::ListStore::new::<ResultValue>();
|
||||||
|
|
||||||
|
let cloned_model = model.clone();
|
||||||
|
|
||||||
|
let selection_model = SingleSelection::new(Some(model));
|
||||||
|
|
||||||
|
let result_table = ColumnView::builder()
|
||||||
|
.reorderable(true)
|
||||||
|
.model(&selection_model)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
for label in result_table_headers_labels {
|
||||||
|
let factory = SignalListItemFactory::new();
|
||||||
|
|
||||||
|
factory.connect_setup(move |_, list_item| {
|
||||||
|
list_item
|
||||||
|
.downcast_ref::<ListItem>()
|
||||||
|
.expect("Needs to be ListItem")
|
||||||
|
.set_child(Some(&Label::new(None)));
|
||||||
|
});
|
||||||
|
|
||||||
|
let values_for_factory = values.clone();
|
||||||
|
|
||||||
|
factory.connect_bind(move |_, list_item| {
|
||||||
|
let cell_value = list_item
|
||||||
|
.downcast_ref::<ListItem>()
|
||||||
|
.expect("Needs to be ListItem")
|
||||||
|
.item()
|
||||||
|
.and_downcast::<ResultValue>()
|
||||||
|
.expect("The item has to be an `IntegerObject`.");
|
||||||
|
|
||||||
|
let cell_label = list_item
|
||||||
|
.downcast_ref::<ListItem>()
|
||||||
|
.expect("Needs to be ListItem")
|
||||||
|
.child()
|
||||||
|
.and_downcast::<Label>()
|
||||||
|
.expect("The child has to be a `Label`.");
|
||||||
|
|
||||||
|
let result_values = values_for_factory.clone().get();
|
||||||
|
|
||||||
|
let reactive_resist: f64 = reactive_resistance_of_capacitor(
|
||||||
|
result_values.2,
|
||||||
|
result_values.0,
|
||||||
|
cell_value.value(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let full_resistance: f64 = full_resistance_of_capacitor(
|
||||||
|
reactive_resist,
|
||||||
|
result_values.4,
|
||||||
|
result_values.1,
|
||||||
|
result_values.0,
|
||||||
|
);
|
||||||
|
|
||||||
|
let signal_source_voltage: f64 =
|
||||||
|
voltage_from_signal_source(result_values.3, reactive_resist, full_resistance);
|
||||||
|
|
||||||
|
let coef: f64 = coef_of_signal_reduce(signal_source_voltage, signal_source_voltage);
|
||||||
|
|
||||||
|
match label {
|
||||||
|
"f, МГц" => {
|
||||||
|
cell_label.set_label(&cell_value.value().to_string());
|
||||||
|
}
|
||||||
|
"Xc, пФ" => {
|
||||||
|
cell_label.set_label(&reactive_resist.to_string());
|
||||||
|
}
|
||||||
|
"Vп, мВ" => {
|
||||||
|
cell_label.set_label(&signal_source_voltage.to_string());
|
||||||
|
}
|
||||||
|
"ζ" => {
|
||||||
|
cell_label.set_label(&coef.to_string());
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let column = ColumnViewColumn::builder()
|
||||||
|
.title(label)
|
||||||
|
.expand(true)
|
||||||
|
.resizable(false)
|
||||||
|
.factory(&factory)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
result_table.append_column(&column);
|
||||||
|
}
|
||||||
|
|
||||||
|
let scrollable_table = ScrolledWindow::builder()
|
||||||
|
.vexpand(true)
|
||||||
|
.child(&result_table)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let table = Frame::builder()
|
||||||
|
.child(&scrollable_table)
|
||||||
|
.vexpand(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
EventHandler::new(calculate_button.clone(), move |_| {
|
EventHandler::new(calculate_button.clone(), move |_| {
|
||||||
let mut values: [f64; 6] = [0f64; 6];
|
match parse_fields(all_inputs.clone()) {
|
||||||
|
Ok(results) => {
|
||||||
|
values.set(results);
|
||||||
|
|
||||||
for (i, input) in all_inputs.iter().enumerate() {
|
let tree_iter: TreeIter = cloned_model.append(&ResultValue::new(results.5));
|
||||||
let input_text_buffer: TextBuffer = input.clone().get_input().buffer();
|
|
||||||
let try_extract_value = f64::from_str(
|
|
||||||
input_text_buffer
|
|
||||||
.text(
|
|
||||||
&input_text_buffer.start_iter(),
|
|
||||||
&input_text_buffer.end_iter(),
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
.as_str()
|
|
||||||
.trim(),
|
|
||||||
);
|
|
||||||
if let Ok(value) = try_extract_value {
|
|
||||||
values[i] = value;
|
|
||||||
} else {
|
|
||||||
test.set_reveal_child(true);
|
|
||||||
|
|
||||||
// TODO: Make asynchronious auto-hide info bar.
|
last_query.append(tree_iter);
|
||||||
// let transmitter = tx.clone();
|
}
|
||||||
//
|
Err(error) => {
|
||||||
// gio::spawn_blocking(move || {
|
let error_kind: Option<&str> = get_error_message(error);
|
||||||
// std::thread::sleep(Duration::from_secs(5));
|
|
||||||
// transmitter.send(false).unwrap();
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// test.set_reveal_child(rx.recv().unwrap());
|
|
||||||
|
|
||||||
println!("Вы ввели некорректное значение поля.");
|
info_bar.set_text_label(error_kind);
|
||||||
return;
|
info_bar.show_infobar(5u64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println!("{:?}", values);
|
|
||||||
})
|
})
|
||||||
.on_click();
|
.on_click();
|
||||||
|
|
||||||
wrapper.append(&input_block);
|
wrapper.append(&input_block);
|
||||||
wrapper.append(&calculate_button);
|
wrapper.append(&calculate_button);
|
||||||
|
wrapper.append(&table);
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ macro_rules! impl_setters {
|
||||||
($($t:ty),+) => {
|
($($t:ty),+) => {
|
||||||
$(
|
$(
|
||||||
impl Setters for $t {
|
impl Setters for $t {
|
||||||
fn set_margin(self, margin: MarginData) -> Self{
|
fn set_margin(self, margin: MarginData) -> Self {
|
||||||
match margin{
|
match margin{
|
||||||
MarginData::EqualsMargin(margin) =>
|
MarginData::EqualsMargin(margin) =>
|
||||||
self.margin_top(margin)
|
self.margin_top(margin)
|
||||||
|
@ -117,4 +117,3 @@ impl Alignment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,15 @@
|
||||||
.info_box{
|
#info_bar{
|
||||||
background-color: yellow;
|
background-color:#F1E6D9;
|
||||||
|
padding: 5px;
|
||||||
|
font-size: 11pt;
|
||||||
|
}
|
||||||
|
#info_bar > button {
|
||||||
|
transform: scale(0.9);
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
#info_bar > button:hover {
|
||||||
|
background-color: #00000010;
|
||||||
|
}
|
||||||
|
#info_bar > button:active {
|
||||||
|
background-color: #00000020;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
use crate::model::builder_traits::*;
|
use crate::model::builder_traits::*;
|
||||||
use builders::{BoxBuilder, RevealerBuilder};
|
|
||||||
use gtk4 as gtk;
|
use gtk4 as gtk;
|
||||||
|
|
||||||
use gtk::{prelude::*, Revealer, StackTransitionType::SlideLeftRight, *};
|
use gtk::{prelude::*, StackTransitionType::SlideLeftRight, *};
|
||||||
|
use info_bar::InfoBar;
|
||||||
use crate::view::components::pages::Pages;
|
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
use crate::view::{
|
use crate::view::{
|
||||||
components::{wrapper::*, *},
|
components::{pages::Pages, wrapper::*, *},
|
||||||
pages::*,
|
pages::*,
|
||||||
properties::*,
|
properties::*,
|
||||||
};
|
};
|
||||||
|
@ -24,15 +23,12 @@ pub fn ui(application: &adw::Application) {
|
||||||
.spacing(10)
|
.spacing(10)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let info_bar_label = Label::builder().label("test").build();
|
let info_bar = InfoBar::builder()
|
||||||
|
.set_text_label("Sample text")
|
||||||
let info_bar: Revealer = Revealer::builder()
|
.set_button_icon("close")
|
||||||
.child(&info_bar_label)
|
|
||||||
.transition_type(RevealerTransitionType::SlideUp)
|
|
||||||
.transition_duration(200)
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
hamming_code::hamming_code_page(&hamming_code, info_bar.clone());
|
hamming_code::hamming_code_page(&hamming_code);
|
||||||
|
|
||||||
let signal_reducing = Wrapper::row_builder()
|
let signal_reducing = Wrapper::row_builder()
|
||||||
.set_align(Alignment::new(Align::Fill, Align::Fill))
|
.set_align(Alignment::new(Align::Fill, Align::Fill))
|
||||||
|
@ -40,7 +36,7 @@ pub fn ui(application: &adw::Application) {
|
||||||
.spacing(10)
|
.spacing(10)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
signal_reducing::signal_reducing_page(&signal_reducing, info_bar.clone());
|
signal_reducing::signal_reducing_page(&signal_reducing);
|
||||||
|
|
||||||
let pages = Pages::builder()
|
let pages = Pages::builder()
|
||||||
.set_transition(SlideLeftRight, 200)
|
.set_transition(SlideLeftRight, 200)
|
||||||
|
@ -53,7 +49,7 @@ pub fn ui(application: &adw::Application) {
|
||||||
|
|
||||||
let application_box = Box::new(Orientation::Vertical, 0);
|
let application_box = Box::new(Orientation::Vertical, 0);
|
||||||
|
|
||||||
application_box.append(&info_bar);
|
application_box.append(info_bar.clone().get());
|
||||||
application_box.append(&pages);
|
application_box.append(&pages);
|
||||||
|
|
||||||
let window = ApplicationWindow::builder()
|
let window = ApplicationWindow::builder()
|
||||||
|
|
Loading…
Reference in New Issue