Compare commits

..

28 Commits

Author SHA1 Message Date
doryan cbde9a8af1 refactor: change import and function signature
SignalReduce model import has been added instead Infobar.
Return value in function signature has been changed (Option<[f64; 6]> ->
Result<SignalReduce, ParseFloarError>).
2024-08-03 00:06:22 +04:00
doryan 81b22a14c9 refactor: add a check for a non-zero denominator 2024-08-03 00:01:58 +04:00
doryan ebf7d9b85c feat(table): implement a result table 2024-08-03 00:00:05 +04:00
doryan d92b2419e0 refactor: change SchemeCharacteristics model 2024-08-02 23:59:31 +04:00
doryan c9dbe4ba6e refactor: remove cell::RefCell, rename TIMERS_QUEUE variable, and etc. (check desc)
Removed unused import, renamed static variable (TIMERS_QUEUE ->
TASKS_QUEUE) and refactored get_instance() and show_infobar() methods.
Return value has been changed (Self -> &'static Self) in get_instance()
method.
A check for opening an infobar has been added and renamed used static
variables in show_infobar() method.
2024-08-02 23:58:24 +04:00
doryan a2cb65d570 refactor: remove redundant import
Removed Revealer import because it is not used.
2024-08-02 01:11:22 +04:00
doryan d3787b2283 feat(model): add model for ColumnView
Added model that are GObject for generating values in tables.
2024-08-02 01:09:26 +04:00
doryan ade98179f7 feat(allows): add attributes that allow a non_snake_case variables 2024-08-02 01:04:37 +04:00
doryan 7157ffd55f refactor: fix some code style issues 2024-07-29 01:19:15 +04:00
doryan 09b05e7fa7 refactor: move parse field algorithm to a separate file 2024-07-29 01:18:15 +04:00
doryan 18e857b40c refactor: move parse field algorithm to a separate file 2024-07-29 01:17:52 +04:00
doryan 0d676820c6 feat(main): add any asynchronous timer that closes infobar automaticaly after 5 second 2024-07-29 01:15:22 +04:00
doryan 0aab9e9ebe feat(main): main function is async now 2024-07-29 01:10:34 +04:00
doryan b7b890ecb3 feat(tokio): update tokio 2024-07-29 01:10:06 +04:00
doryan 01f65376d0 feat(infobar): add a timer after which the infobar will be closed 2024-07-27 23:28:35 +04:00
doryan 33226ecae2 feat(infobar): add implementation of infobar for use instead deprecated built-in infobar 2024-07-27 22:42:10 +04:00
doryan bd394b9bf4 feat(infobar): add infobar as 'unique' instance instead manual implementation of infobar via box, label, revealer and button; 2024-07-27 22:22:51 +04:00
doryan cb2a52cc7b refactor: remove redundant argument; feat(infobar): add infobar for testing 2024-07-27 22:20:21 +04:00
doryan 5972d589fe refactor: remove redundant argument 2024-07-27 21:59:49 +04:00
doryan 1be7125ecf refactor: add spacebar lol 2024-07-27 21:38:39 +04:00
doryan f3ece276f1 feat(style): add style for button inner infobar 2024-07-27 21:37:50 +04:00
doryan 561f6fc065 feat(import): add infobar module to export 2024-07-27 20:46:43 +04:00
doryan a8e43df99e feat(libc): update libc 2024-07-27 20:08:11 +04:00
doryan 4b5589392d feat(tokio feature): add 'sync' feature 2024-07-27 20:07:37 +04:00
doryan acf1d9f30b feat(style): add styles for info bar 2024-07-22 16:43:47 +04:00
doryan fd2f605978 fix(func signature): Replaced EventHandler<T, C> -> Self 2024-07-22 16:43:03 +04:00
doryan 54a4b44780 fix(fn signature): remove return types from function signatures 2024-07-22 00:24:09 +04:00
doryan 2e543a22c8 fix(cond): remove redundant boolean operations and replace them with their correct analogs 2024-07-22 00:02:16 +04:00
19 changed files with 428 additions and 212 deletions

29
Cargo.lock generated
View File

@ -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",

View File

@ -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"] }

View File

@ -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("Режим: кодирование");

View File

@ -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));
} }

View File

@ -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));
} }

View File

@ -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());

View File

@ -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
}
} }

View File

@ -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

View File

@ -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],
))
} }

View File

@ -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();

View File

@ -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()
}
}

View File

@ -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 {}

View File

@ -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
}
}

View File

@ -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;

View File

@ -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()

View File

@ -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);
} }

View File

@ -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 {
} }
} }
} }

View File

@ -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;
} }

View File

@ -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()