Compare commits

...

18 Commits

Author SHA1 Message Date
doryan 81a8d9b2c6 fix(const): use PI const from std instead 3.14f32 2024-07-19 23:39:44 +04:00
doryan 74835302ce fix(import + expand): change import and fix expand of box node 2024-07-19 23:38:43 +04:00
doryan 7e30117c84 fix(check): change method of check for an empty array 2024-07-19 23:37:24 +04:00
doryan dbf7dab513 refactor(import + some code): change import and refactor some bad blocks of code 2024-07-19 23:33:50 +04:00
doryan fcfb0d1fa6 fix(modules): sort modules 2024-07-19 23:32:09 +04:00
doryan 731cce4ad8 rename(model): model.rs -> models.rs 2024-07-19 23:31:32 +04:00
doryan d77e12f2f6 refactor(Cargo.toml): add 'time' feature 2024-07-19 23:27:23 +04:00
doryan 3c2ab67d31 feat(import): sorted and add some modules 2024-07-19 23:26:43 +04:00
doryan b12be95959 fix(imports + signature): change imports and removed return type () from function signature 2024-07-19 23:25:41 +04:00
doryan b3678c43c4 fix(imports): change imports 2024-07-19 23:24:38 +04:00
doryan 61f6777735 fix(imports): change imports 2024-07-19 23:24:10 +04:00
doryan 21ccba9ddb sort(module): module imports 2024-07-19 23:18:50 +04:00
doryan cb5d219319 feat: change function signature (add one parameter) 2024-07-19 23:17:02 +04:00
doryan 2866d26253 BREAKING CHANGE: refactor code and add event handler for button 2024-07-19 23:16:11 +04:00
doryan 682682eb13 feat(info bar): add info bar for warnings 2024-07-19 23:12:42 +04:00
doryan 7264b704d0 feat(stylesheets): add stylesheet for info bar 2024-07-19 23:06:34 +04:00
doryan f88946b507 rename(model): model.rs -> models.rs 2024-07-19 23:05:55 +04:00
doryan b663859eee remove(type): redundant type definition 2024-07-19 23:04:01 +04:00
19 changed files with 149 additions and 210 deletions

View File

@ -9,4 +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", "rt-multi-thread", "macros"] } tokio = { version = "1.0.0", features = ["rt", "time", "rt-multi-thread", "macros"] }

View File

@ -1,4 +1,4 @@
use crate::{gtk::prelude::*, model::model::*}; use crate::{gtk::prelude::*, model::models::*};
impl<F, C> EventHandler<F, C> impl<F, C> EventHandler<F, C>
where where
@ -26,4 +26,3 @@ where
.connect_clicked(move |button| (self.callback)(button)); .connect_clicked(move |button| (self.callback)(button));
} }
} }

View File

@ -1,4 +1,4 @@
use crate::{gtk::prelude::*, model::model::*, 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) -> ();

View File

@ -2,7 +2,7 @@ use std::collections::HashMap;
use crate::{ use crate::{
controller::view_utils::{hamming_code_input_utils::*, input_utils::*}, controller::view_utils::{hamming_code_input_utils::*, input_utils::*},
model::model::*, model::models::*,
}; };
/// **Синдромы** /// **Синдромы**

View File

@ -1,5 +1,5 @@
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 {
1f64 / (2f64 * 3.14f64 * f * Cm * L) 1f64 / (2f64 * std::f64::consts::PI * f * Cm * L)
} }
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 {

View File

@ -1,9 +1,9 @@
use gtk4 as gtk; use gtk4 as gtk;
use crate::{model::model::*, model_utils::hamming_code_seven_four::*}; use crate::{model::models::*, model_utils::hamming_code_seven_four::*};
use gtk::{prelude::*, *}; use gtk::{prelude::*, *};
pub fn start_hamming_algorithm(input: &TextView, output: &TextView, mode: bool) -> () { pub fn start_hamming_algorithm(input: &TextView, output: &TextView, mode: bool) {
let (iter_start, iter_end) = input.buffer().bounds(); let (iter_start, iter_end) = input.buffer().bounds();
let parsed_input: String = input let parsed_input: String = input
.buffer() .buffer()

View File

@ -9,7 +9,7 @@ const ASCII_ZERO_CHAR_POSITION: u8 = 48;
pub fn processing_input(input: &String) -> String { pub fn processing_input(input: &String) -> String {
input input
.split_ascii_whitespace() .split_ascii_whitespace()
.filter(|&x| x != "") .filter(|&x| x.is_empty())
.fold(String::new(), |c: String, n: &str| c + n) .fold(String::new(), |c: String, n: &str| c + n)
} }

View File

@ -1,7 +1,7 @@
use gtk4 as gtk; use gtk4 as gtk;
use crate::controller::model_utils::signal_reducer::*; use crate::controller::model_utils::signal_reducer::*;
use crate::model::model::SchemeCharacteristics; use crate::model::models::SchemeCharacteristics;
use gtk::{prelude::*, *}; use gtk::{prelude::*, *};
pub fn check_characteristics( pub fn check_characteristics(
@ -24,7 +24,7 @@ pub fn check_characteristics(
println!("{:?}", int); println!("{:?}", int);
} }
Err(err) => { Err(err) => {
if output.len() == 0 { if output.is_empty() {
output.push_str("Введите пожалуйста числа в полях"); output.push_str("Введите пожалуйста числа в полях");
println!("{:?}", err); println!("{:?}", err);
} }
@ -32,11 +32,7 @@ pub fn check_characteristics(
} }
} }
if output.len() != 0 { !output.is_empty()
false
} else {
true
}
} }
pub fn start_algorithm( pub fn start_algorithm(
@ -48,7 +44,7 @@ pub fn start_algorithm(
let mut all_inputs_data: Vec<f64> = Vec::new(); let mut all_inputs_data: Vec<f64> = Vec::new();
let mut output: String = String::new(); let mut output: String = String::new();
if let false = check_characteristics(raw_characteristics, &mut all_inputs_data, &mut output) { if !check_characteristics(raw_characteristics, &mut all_inputs_data, &mut output) {
error_log_label.set_text(output.as_str()); error_log_label.set_text(output.as_str());
} else { } else {
error_log_label.set_text(""); error_log_label.set_text("");

View File

@ -10,7 +10,7 @@ use controller::*;
use view::view::*; use view::view::*;
fn main() { fn main() {
let app = 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,2 @@
pub mod model;
pub mod builder_traits; pub mod builder_traits;
pub mod models;

View File

@ -1,7 +1,7 @@
pub mod tabs;
pub mod input; pub mod input;
pub mod pages; pub mod pages;
pub mod switch; pub mod switch;
pub mod tabs;
pub mod wrapper; pub mod wrapper;
use crate::model::builder_traits; use crate::model::builder_traits;

View File

@ -1,4 +1,4 @@
use gtk4 as gtk; use gtk4::{self as gtk, prelude::WidgetExt, Align};
#[allow(unused)] #[allow(unused)]
use gtk::{ use gtk::{
@ -42,6 +42,7 @@ impl Builder<Pages, Page<'_>, i32> for PagesBuilder {
wrapper.append(&stack_sidebar); wrapper.append(&stack_sidebar);
wrapper.append(&self.pages_content); wrapper.append(&self.pages_content);
wrapper.set_vexpand(true);
Pages { wrapper } Pages { wrapper }
} }
@ -73,4 +74,3 @@ impl PagesBuilder {
self self
} }
} }

View File

@ -1,4 +1,5 @@
pub mod view;
pub mod pages;
pub mod components; pub mod components;
pub mod pages;
pub mod properties; pub mod properties;
pub mod styles;
pub mod view;

View File

@ -6,13 +6,13 @@ use crate::{
event_handlers::{button_event_handlers::*, switch_event_handlers::*}, event_handlers::{button_event_handlers::*, switch_event_handlers::*},
view_utils::{hamming_code_input_utils::*, input_utils::*}, view_utils::{hamming_code_input_utils::*, input_utils::*},
}, },
model::model::*, model::models::*,
view::{components::wrapper::*, properties::*}, view::{components::wrapper::*, properties::*},
}; };
use gtk::{prelude::*, *}; use gtk::{prelude::*, *};
pub fn hamming_code_page(wrapper: &Box) -> () { pub fn hamming_code_page(wrapper: &Box, info_bar: Revealer) {
// input // input
let hamming_text_view_input_label = Label::builder() let hamming_text_view_input_label = Label::builder()

View File

@ -1,211 +1,113 @@
use glib::property::PropertyGet;
use gtk4 as gtk; use gtk4 as gtk;
use gtk4::prelude::WidgetExt;
use std::{str::FromStr, time::Duration};
use crate::{ use crate::{
controller::event_handlers::button_event_handlers::*, event_handlers::button_event_handlers::BtnEventHandler,
model::{builder_traits::Product, model::*}, model::{builder_traits::Product, models::*},
view::{ view::{components::input::Input, properties::*},
components::{input::Input, wrapper::Wrapper},
properties::*,
},
view_utils::signal_reduce_input_utils::start_algorithm,
}; };
use gtk::{ use gtk::{
prelude::{BoxExt, ListBoxRowExt, WidgetExt}, prelude::{BoxExt, GridExt, TextBufferExt, TextViewExt},
Align, WrapMode, *, Align, WrapMode, *,
}; };
pub fn signal_reducing_page(wrapper: &Box) { pub fn signal_reducing_page(wrapper: &Box, info_bar: Revealer) {
let (input_height, monospace, input_alignment, input_wrapping): (i32, bool, Align, WrapMode) = let (input_height, monospace, input_alignment, input_wrapping): (i32, bool, Align, WrapMode) =
(24, true, Align::Fill, WrapMode::Word); (24, true, Align::Fill, WrapMode::Word);
let input_block: Grid = Grid::new();
input_block.set_column_homogeneous(true);
input_block.set_row_homogeneous(true);
let input_label_alignment = Alignment { let input_label_alignment = Alignment {
horizontal: Align::Start, horizontal: Align::Start,
vertical: Align::Fill, vertical: Align::Fill,
}; };
let wire_length_input: Input = Input::builder() let input_labels: [&str; 6] = [
.set_label("l, м:") "l, м:",
.set_margins(MarginData::EqualsMargin(5)) "Rм, Ом:",
.set_align(input_label_alignment) "Cм, пФ:",
.build(monospace, input_wrapping, input_height); "Vи, мВ",
"Rи, Ом:",
let resistance_per_meter_input: Input = Input::builder() "f, мГц:",
.set_label("Rм, Ом:")
.set_margins(MarginData::EqualsMargin(5))
.set_align(input_label_alignment)
.build(monospace, input_wrapping, input_height);
let capacity_per_meter_input: Input = Input::builder()
.set_label("Cм, пФ:")
.set_margins(MarginData::EqualsMargin(5))
.set_align(input_label_alignment)
.build(monospace, input_wrapping, input_height);
let wrapper_first_row = Wrapper::col_builder()
.halign(Align::Fill)
.hexpand(true)
.spacing(5)
.build();
let first_row_elements: Vec<&Input> = vec![
&wire_length_input,
&resistance_per_meter_input,
&capacity_per_meter_input,
]; ];
for elem in first_row_elements { let all_inputs: Vec<Input> = input_labels
let input: Box = elem.clone().get(); .iter()
.map(move |label| {
input.set_halign(input_alignment); Input::builder()
input.set_hexpand(true); .set_label(label)
wrapper_first_row.append(&input);
}
let info_signal_voltage_input: Input = Input::builder()
.set_label("Vи, мВ:")
.set_margins(MarginData::EqualsMargin(5)) .set_margins(MarginData::EqualsMargin(5))
.set_align(input_label_alignment) .set_align(input_label_alignment)
.build(monospace, input_wrapping, input_height); .build(monospace, input_wrapping, input_height)
})
.collect();
let resistance_of_info_voltage_source_input: Input = Input::builder() let mut row_position = 0i32;
.set_label("Rи, Ом:")
.set_margins(MarginData::EqualsMargin(5))
.set_align(input_label_alignment)
.build(monospace, input_wrapping, input_height);
let info_voltage_source_frequency_input: Input = Input::builder() for (id, elem) in all_inputs.iter().enumerate() {
.set_label("f, мГц:") if id % 3 == 0 {
.set_margins(MarginData::EqualsMargin(5)) row_position += 1;
.set_align(input_label_alignment)
.build(monospace, input_wrapping, input_height);
let wrapper_second_row = Wrapper::col_builder()
.halign(Align::Fill)
.hexpand(true)
.spacing(5)
.build();
let second_row_elements: Vec<&Input> = vec![
&info_signal_voltage_input,
&resistance_of_info_voltage_source_input,
&info_voltage_source_frequency_input,
];
for elem in second_row_elements {
let input: Box = elem.clone().get();
input.set_halign(input_alignment);
input.set_hexpand(true);
wrapper_second_row.append(&input);
} }
let all_text_views: Vec<TextView> = vec![ input_block.attach(
wire_length_input.get_input(), &elem.clone().get(),
resistance_per_meter_input.get_input(), (id as i32) - (3 * row_position),
capacity_per_meter_input.get_input(), row_position,
info_signal_voltage_input.get_input(), 1,
resistance_of_info_voltage_source_input.get_input(), 1,
info_voltage_source_frequency_input.get_input(), );
];
let main_wrapper = Wrapper::row_builder().spacing(5).build();
main_wrapper.append(&wrapper_first_row);
main_wrapper.append(&wrapper_second_row);
let calculate_button = Button::builder()
.label("Расчитать")
.halign(Align::End)
.set_margin(MarginData::MultipleMargin((10, 5, 0, 0)))
.build();
let table_header_labels = vec!["f, Гц", "Xc, пФ", "Vп, мВ", "ζ"];
let table_header = ColumnView::builder()
.focusable(false)
.reorderable(false)
.show_row_separators(true)
.show_column_separators(true)
.halign(Align::Fill)
.hexpand(true)
.build();
for table_header_label in table_header_labels {
let column = ColumnViewColumn::builder()
.title(table_header_label)
.fixed_width(200)
.expand(true)
.build();
table_header.append_column(&column);
} }
let mut table = ListBox::builder().hexpand(true).halign(Align::Fill).build(); let calculate_button = Button::builder().label("Расчитать").build();
let header = ListBoxRow::builder().child(&table_header).build(); // TODO: Make asynchronious auto-hide info bar.
let test = info_bar.clone();
table.append(&header); // let (tx, rx) = std::sync::mpsc::channel::<bool>();
for i in (0..=100).step_by(5) {
if i == 0 {
continue;
}
let table_row = ListBoxRow::new();
let columns = ColumnView::builder().reorderable(false).build();
let column = ColumnViewColumn::builder()
.title(format!("{i}"))
.fixed_width(200)
.expand(true)
.build();
columns.append_column(&column);
for table_row_label in 1..=3 {
let column = ColumnViewColumn::builder()
.title(format!("{table_row_label}"))
.fixed_width(200)
.expand(true)
.build();
columns.append_column(&column);
}
table_row.set_child(Some(&columns));
table.append(&table_row);
}
let table_of_calculated_values = Frame::builder()
.height_request(64)
.hexpand(true)
.child(&table)
.halign(Align::Fill)
.set_margin(MarginData::MultipleMargin((10, 5, 0, 0)))
.build();
let table_frame = table_of_calculated_values.clone();
let errors_label: Label = Label::new(Some(""));
let errors_label_for_handler: Label = errors_label.clone();
EventHandler::new(calculate_button.clone(), move |_| { EventHandler::new(calculate_button.clone(), move |_| {
start_algorithm( let mut values: [f64; 6] = [0f64; 6];
&errors_label_for_handler,
&all_text_views, for (i, input) in all_inputs.iter().enumerate() {
&table_frame.clone(), let input_text_buffer: TextBuffer = input.clone().get_input().buffer();
&header, 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.
// let transmitter = tx.clone();
//
// gio::spawn_blocking(move || {
// std::thread::sleep(Duration::from_secs(5));
// transmitter.send(false).unwrap();
// });
//
// test.set_reveal_child(rx.recv().unwrap());
println!("Вы ввели некорректное значение поля.");
return;
}
}
println!("{:?}", values);
}) })
.on_click(); .on_click();
main_wrapper.append(&errors_label); wrapper.append(&input_block);
main_wrapper.append(&calculate_button); wrapper.append(&calculate_button);
main_wrapper.append(&table_of_calculated_values);
wrapper.append(&main_wrapper);
} }

View File

@ -0,0 +1,3 @@
.info_box{
background-color: yellow;
}

19
src/view/styles/mod.rs Normal file
View File

@ -0,0 +1,19 @@
use adw::gdk::Display;
use gtk4 as gtk;
use std::path::Path;
use gtk::{
style_context_add_provider_for_display, CssProvider, STYLE_PROVIDER_PRIORITY_APPLICATION,
};
pub fn load_css() {
let style_provider = CssProvider::new();
style_provider.load_from_path(Path::new("./src/view/styles/info_bar.css"));
style_context_add_provider_for_display(
&Display::default().expect("Could not connect to a display"),
&style_provider,
STYLE_PROVIDER_PRIORITY_APPLICATION,
);
}

View File

@ -1,7 +1,8 @@
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::*, StackTransitionType::SlideLeftRight, *}; use gtk::{prelude::*, Revealer, StackTransitionType::SlideLeftRight, *};
use crate::view::components::pages::Pages; use crate::view::components::pages::Pages;
@ -12,14 +13,26 @@ use crate::view::{
properties::*, properties::*,
}; };
use super::styles::load_css;
pub fn ui(application: &adw::Application) { pub fn ui(application: &adw::Application) {
load_css();
let hamming_code = Wrapper::row_builder() let hamming_code = Wrapper::row_builder()
.set_align(Alignment::new(Align::Fill, Align::Fill)) .set_align(Alignment::new(Align::Fill, Align::Fill))
.set_margin(MarginData::EqualsMargin(15)) .set_margin(MarginData::EqualsMargin(15))
.spacing(10) .spacing(10)
.build(); .build();
hamming_code::hamming_code_page(&hamming_code); let info_bar_label = Label::builder().label("test").build();
let info_bar: Revealer = Revealer::builder()
.child(&info_bar_label)
.transition_type(RevealerTransitionType::SlideUp)
.transition_duration(200)
.build();
hamming_code::hamming_code_page(&hamming_code, info_bar.clone());
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))
@ -27,7 +40,7 @@ pub fn ui(application: &adw::Application) {
.spacing(10) .spacing(10)
.build(); .build();
signal_reducing::signal_reducing_page(&signal_reducing); signal_reducing::signal_reducing_page(&signal_reducing, info_bar.clone());
let pages = Pages::builder() let pages = Pages::builder()
.set_transition(SlideLeftRight, 200) .set_transition(SlideLeftRight, 200)
@ -38,12 +51,17 @@ pub fn ui(application: &adw::Application) {
.build(5) .build(5)
.get(); .get();
let application_box = Box::new(Orientation::Vertical, 0);
application_box.append(&info_bar);
application_box.append(&pages);
let window = ApplicationWindow::builder() let window = ApplicationWindow::builder()
.title("Комплексная программа для лаб. работ") .title("Комплексная программа для лаб. работ")
.width_request(700) .width_request(700)
.height_request(400) .height_request(400)
.application(application) .application(application)
.child(&pages) .child(&application_box)
.build(); .build();
window.show(); window.show();