Compare commits
24 Commits
24b60e74a0
...
62b7036933
Author | SHA1 | Date | |
---|---|---|---|
doryan | 62b7036933 | ||
doryan | 3d896c7061 | ||
doryan | e8c73b75a1 | ||
doryan | b4fb37539c | ||
doryan | f9699180b9 | ||
doryan | 839694edc1 | ||
doryan | cedb844826 | ||
doryan | a7cf11737a | ||
doryan | f78001167a | ||
doryan | 11ba24d7ed | ||
doryan | e9764cf0e8 | ||
doryan | ac9e8953a9 | ||
doryan | 4e872ddcff | ||
doryan | 8e8cecd463 | ||
doryan | cd697b9f5d | ||
doryan | 7116b565de | ||
doryan | 7282045c98 | ||
doryan | f57aed1fb8 | ||
doryan | 2e1f4b6a12 | ||
doryan | d3327a7c36 | ||
doryan | 06439585eb | ||
doryan | 418e916c0d | ||
doryan | 23bfd10e2b | ||
doryan | 269b30312d |
|
@ -2,7 +2,7 @@ use std::collections::HashMap;
|
|||
use std::sync::LazyLock;
|
||||
|
||||
use crate::{
|
||||
controller::view_utils::{hamming_code_input_utils::*, input_utils::*},
|
||||
controller::view_utils::{hamming_code_utils::*, input_utils::*},
|
||||
model::{models::*, Result},
|
||||
};
|
||||
|
||||
|
@ -24,7 +24,7 @@ pub fn hamming(raw_input: String, mode: HammingMode) -> Result<String> {
|
|||
let prepared_input: String = processing_input(&raw_input);
|
||||
|
||||
let (first_condition, second_condition): (bool, bool) =
|
||||
check_correct_binary_code(&raw_input, &prepared_input, length_of_code);
|
||||
check_correct_binary_code(&prepared_input, length_of_code);
|
||||
|
||||
if raw_input.is_empty() {
|
||||
Err("Введите код.".into())
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
use crate::model::Frequency;
|
||||
|
||||
use gio::{prelude::Cast, ListStore};
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn reactive_resistance_of_capacitor(Cm: f64, L: f64, f: f64) -> f64 {
|
||||
if f == 0.0 || Cm == 0.0 || L == 0.0 {
|
||||
|
@ -29,3 +33,19 @@ pub fn coef_of_signal_reduce(Vs: f64, V: f64) -> f64 {
|
|||
Vs / V
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_default_values(model: &ListStore) {
|
||||
for number in (0..=100).step_by(5) {
|
||||
if number == 0 {
|
||||
model.append(&Frequency::new(1.0));
|
||||
} else if (number >= 70 && number % 10 == 0) || (number < 70 && number % 5 == 0) {
|
||||
model.append(&Frequency::new(number as f64));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_by_frequency_value(model: &ListStore, new_elem: &Frequency) -> Option<u32> {
|
||||
model.find_with_equal_func(|elem| {
|
||||
elem.downcast_ref::<Frequency>().unwrap().frequency() == new_elem.frequency()
|
||||
})
|
||||
}
|
||||
|
|
|
@ -25,10 +25,10 @@ pub fn start_hamming_algorithm(input: &TextView, state: bool) -> Result<String>
|
|||
hamming(parsed_input, operation)
|
||||
}
|
||||
|
||||
pub fn check_correct_binary_code(input: &str, prepared_input: &str, l: usize) -> (bool, bool) {
|
||||
pub fn check_correct_binary_code(prepared_input: &str, l: usize) -> (bool, bool) {
|
||||
let first_condition: bool = prepared_input.len() % l == 0;
|
||||
|
||||
let second_condition: bool = input.chars().all(|c| c == '1' || c == '0' || c == ' ');
|
||||
let second_condition: bool = prepared_input.chars().all(|c| c == '1' || c == '0');
|
||||
|
||||
(first_condition, second_condition)
|
||||
}
|
|
@ -9,8 +9,8 @@ const ASCII_ZERO_CHAR_POSITION: u8 = 48;
|
|||
pub fn processing_input(input: impl Into<String>) -> String {
|
||||
input
|
||||
.into()
|
||||
.split_ascii_whitespace()
|
||||
.filter(|&x| !x.is_empty())
|
||||
.split(&[' ', '\n'][..])
|
||||
.filter(|x| !x.is_empty())
|
||||
.fold(String::new(), |c: String, n: &str| c + n)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
pub mod hamming_code_input_utils;
|
||||
pub mod hamming_code_utils;
|
||||
pub mod input_utils;
|
||||
pub mod signal_reduce_input_utils;
|
||||
|
||||
pub mod signal_reduce_utils;
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
use gtk4 as gtk;
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use gtk::{
|
||||
prelude::{TextBufferExt, TextViewExt},
|
||||
TextBuffer,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
model::{models::SignalReduce, Error, Result},
|
||||
view::components::input::Input,
|
||||
};
|
||||
|
||||
pub fn get_error_message(error: Error) -> Option<&'static str> {
|
||||
match error.to_string().as_str() {
|
||||
"cannot parse float from empty string" => Some("Вы не ввели данные в поле/-я"),
|
||||
"invalid float literal" => Some("Вы ввели не корректные данные в поле/-я"),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_fields(all_inputs: Vec<Input>) -> Result<SignalReduce> {
|
||||
let mut values: [f64; 6] = [0.0; 6];
|
||||
|
||||
for (i, input) in all_inputs.iter().enumerate() {
|
||||
let input_text_buffer: TextBuffer = input.clone().get_input().buffer();
|
||||
let extracted_value = f64::from_str(
|
||||
input_text_buffer
|
||||
.text(
|
||||
&input_text_buffer.start_iter(),
|
||||
&input_text_buffer.end_iter(),
|
||||
false,
|
||||
)
|
||||
.as_str()
|
||||
.trim(),
|
||||
)?;
|
||||
values[i] = extracted_value;
|
||||
}
|
||||
|
||||
Ok(SignalReduce {
|
||||
length: values[0],
|
||||
wire_resistance: values[1],
|
||||
wire_capacity: values[2],
|
||||
source_resistance: values[3],
|
||||
source_voltage: values[4],
|
||||
frequency: values[5],
|
||||
})
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
use gtk4 as gtk;
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::{
|
||||
model::{models::SignalReduce, Error, Frequency, Result},
|
||||
model_utils::signal_reducer::*,
|
||||
view::components::input::Input,
|
||||
};
|
||||
|
||||
use gtk::{
|
||||
prelude::{Cast, CastNone, EditableExt, ListItemExt, ObjectExt, WidgetExt},
|
||||
ColumnView, Entry, Label, ListItem, SignalListItemFactory,
|
||||
};
|
||||
|
||||
pub fn get_error_message(error: Error) -> Option<&'static str> {
|
||||
match error.to_string().as_str() {
|
||||
"cannot parse float from empty string" => Some("Вы не ввели данные в поле/-я"),
|
||||
"invalid float literal" => Some("Вы ввели не корректные данные в поле/-я"),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_fields(all_inputs: Vec<Input<Entry>>) -> Result<SignalReduce> {
|
||||
let mut values: [f64; 6] = [0.0; 6];
|
||||
|
||||
for (i, input) in all_inputs.iter().enumerate() {
|
||||
let input_text_buffer = input.get_input();
|
||||
let extracted_value = f64::from_str(input_text_buffer.text().as_str().trim())?;
|
||||
values[i] = extracted_value;
|
||||
}
|
||||
|
||||
Ok(SignalReduce {
|
||||
length: values[0],
|
||||
wire_resistance: values[1],
|
||||
wire_capacity: values[2],
|
||||
source_resistance: values[3],
|
||||
source_voltage: values[4],
|
||||
frequency: values[5],
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn update_column_view(column_view: &ColumnView) {
|
||||
column_view.hide();
|
||||
column_view.show();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn column_view_setup_factory(_factory: &SignalListItemFactory, list_item: &ListItem) {
|
||||
list_item
|
||||
.downcast_ref::<ListItem>()
|
||||
.expect("Needs to be ListItem")
|
||||
.set_child(Some(&Label::new(None)));
|
||||
}
|
||||
|
||||
pub fn column_view_bind_factory(
|
||||
_factory: &SignalListItemFactory,
|
||||
list_item: &ListItem,
|
||||
values: SignalReduce,
|
||||
label: &str,
|
||||
) {
|
||||
let cell_value = list_item
|
||||
.downcast_ref::<ListItem>()
|
||||
.expect("Needs to be ListItem")
|
||||
.item()
|
||||
.and_downcast::<Frequency>()
|
||||
.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`.");
|
||||
|
||||
cell_value
|
||||
.bind_property("frequency", &cell_label, "label")
|
||||
.sync_create()
|
||||
.build();
|
||||
|
||||
if cell_value.reactive_resist() == 0.0 {
|
||||
cell_value.set_reactive_resist(reactive_resistance_of_capacitor(
|
||||
values.wire_capacity * 10f64.powi(-12),
|
||||
values.length,
|
||||
cell_value.frequency() * 10f64.powi(6),
|
||||
));
|
||||
}
|
||||
|
||||
if cell_value.full_resistance() == 0.0 {
|
||||
cell_value.set_full_resistance(full_resistance_of_capacitor(
|
||||
cell_value.reactive_resist(),
|
||||
values.source_resistance,
|
||||
values.wire_resistance,
|
||||
values.length,
|
||||
));
|
||||
}
|
||||
|
||||
if cell_value.signal_source_voltage() == 0.0 {
|
||||
cell_value.set_signal_source_voltage(
|
||||
voltage_from_signal_source(
|
||||
values.source_voltage * 10f64.powi(-3),
|
||||
cell_value.reactive_resist(),
|
||||
cell_value.full_resistance(),
|
||||
) * 1000.0,
|
||||
);
|
||||
}
|
||||
|
||||
match label {
|
||||
"f, МГц" => {
|
||||
cell_label.set_label(&cell_value.frequency().to_string());
|
||||
}
|
||||
"Xc, Ом" => {
|
||||
cell_label.set_label(format!("{0:.1$}", cell_value.reactive_resist(), 6).as_str());
|
||||
}
|
||||
"Vп, мВ" => {
|
||||
cell_label
|
||||
.set_label(format!("{0:.1$}", cell_value.signal_source_voltage(), 6).as_str());
|
||||
}
|
||||
"ζ" => {
|
||||
let coef: f64 =
|
||||
coef_of_signal_reduce(values.source_voltage, cell_value.signal_source_voltage());
|
||||
|
||||
cell_label.set_label(format!("{0:.1$}", coef, 6).as_str());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
use gtk4 as gtk;
|
||||
|
||||
extern crate gio;
|
||||
|
||||
use gtk::prelude::*;
|
||||
|
||||
mod controller;
|
||||
|
|
|
@ -31,6 +31,12 @@ pub struct SignalReduce {
|
|||
pub struct Frequency {
|
||||
#[property(get, set)]
|
||||
frequency: Cell<f64>,
|
||||
#[property(get, set)]
|
||||
reactive_resist: Cell<f64>,
|
||||
#[property(get, set)]
|
||||
full_resistance: Cell<f64>,
|
||||
#[property(get, set)]
|
||||
signal_source_voltage: Cell<f64>,
|
||||
}
|
||||
|
||||
#[glib::derived_properties]
|
||||
|
|
|
@ -26,8 +26,6 @@ pub struct InfoBarBuilder {
|
|||
button: ButtonBuilder,
|
||||
}
|
||||
|
||||
// TODO: Develop a method to safely mutate static.
|
||||
// Not necessary.
|
||||
static mut TASKS_QUEUE: VecDeque<JoinHandle<()>> = VecDeque::new();
|
||||
|
||||
//
|
||||
|
|
|
@ -5,12 +5,46 @@ use gtk::{prelude::*, *};
|
|||
|
||||
pub type InputLabel = String;
|
||||
|
||||
macro_rules! build_for {
|
||||
( $(($comp:ty,$name:ident)),* ) => {
|
||||
$(
|
||||
pub fn $name(self, input_height: Option<i32>) -> Input<$comp> {
|
||||
let input_component = Box::new(Orientation::Vertical, 0);
|
||||
|
||||
let input_label = Label::builder()
|
||||
.halign(self.align.horizontal)
|
||||
.valign(self.align.vertical)
|
||||
.set_margin(self.margins)
|
||||
.label(self.label)
|
||||
.build();
|
||||
|
||||
let mut input_builder = <$comp>::builder()
|
||||
.set_margin(MarginData::EqualsMargin(6));
|
||||
|
||||
if let Some(height) = input_height {
|
||||
input_builder = input_builder.height_request(height);
|
||||
}
|
||||
|
||||
let input = input_builder.build();
|
||||
|
||||
input_component.append(&input_label);
|
||||
input_component.append(&input);
|
||||
|
||||
Input {
|
||||
component: input_component,
|
||||
input: input.clone(),
|
||||
input_label: input_label.clone(),
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Input {
|
||||
pub struct Input<I> {
|
||||
component: Box,
|
||||
input: TextView,
|
||||
input: I,
|
||||
input_label: Label,
|
||||
input_frame: Frame,
|
||||
}
|
||||
|
||||
pub struct InputBuilder {
|
||||
|
@ -19,7 +53,7 @@ pub struct InputBuilder {
|
|||
margins: MarginData,
|
||||
}
|
||||
|
||||
impl Product<InputBuilder, Box> for Input {
|
||||
impl<I> Product<InputBuilder, Box> for Input<I> {
|
||||
fn builder() -> InputBuilder {
|
||||
InputBuilder {
|
||||
align: Alignment {
|
||||
|
@ -36,13 +70,13 @@ impl Product<InputBuilder, Box> for Input {
|
|||
}
|
||||
}
|
||||
|
||||
impl Input {
|
||||
pub fn get_input(&self) -> &TextView {
|
||||
&self.input
|
||||
impl<I> Input<I> {
|
||||
pub fn get_component(&self) -> &Box {
|
||||
&self.component
|
||||
}
|
||||
|
||||
pub fn get_frame(&self) -> &Frame {
|
||||
&self.input_frame
|
||||
pub fn get_input(&self) -> &I {
|
||||
&self.input
|
||||
}
|
||||
|
||||
pub fn get_label(&self) -> &Label {
|
||||
|
@ -69,36 +103,5 @@ impl InputBuilder {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn build(self, monospace: bool, wrap_mode: WrapMode, input_height: i32) -> Input {
|
||||
let input_component = Box::new(Orientation::Vertical, 0);
|
||||
|
||||
let text_view_label = Label::builder()
|
||||
.halign(self.align.horizontal)
|
||||
.valign(self.align.vertical)
|
||||
.set_margin(self.margins)
|
||||
.label(self.label)
|
||||
.build();
|
||||
|
||||
let text_view_input = TextView::builder()
|
||||
.monospace(monospace)
|
||||
.height_request(input_height)
|
||||
.set_text_view_margin(MarginData::EqualsMargin(6))
|
||||
.wrap_mode(wrap_mode)
|
||||
.build();
|
||||
|
||||
let text_view_input_frame = Frame::builder()
|
||||
.child(&text_view_input)
|
||||
.set_margin(MarginData::MultipleMargin((0, 5, 0, 5)))
|
||||
.build();
|
||||
|
||||
input_component.append(&text_view_label);
|
||||
input_component.append(&text_view_input_frame);
|
||||
|
||||
Input {
|
||||
component: input_component,
|
||||
input: text_view_input.clone(),
|
||||
input_frame: text_view_input_frame.clone(),
|
||||
input_label: text_view_label.clone(),
|
||||
}
|
||||
}
|
||||
build_for!((TextView, build), (Entry, build_entry));
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
|||
components::{info_bar::InfoBar, input::Input, wrapper::*},
|
||||
properties::*,
|
||||
},
|
||||
view_utils::{hamming_code_input_utils::start_hamming_algorithm, input_utils::clearing},
|
||||
view_utils::{hamming_code_utils::start_hamming_algorithm, input_utils::clearing},
|
||||
};
|
||||
|
||||
use gtk::{glib::clone, prelude::*, *};
|
||||
|
@ -14,20 +14,25 @@ use gtk::{glib::clone, prelude::*, *};
|
|||
pub fn hamming_code_page(wrapper: &Box) {
|
||||
let info_bar = InfoBar::get_instance();
|
||||
|
||||
let input_code = Input::builder()
|
||||
let input_code = Input::<TextView>::builder()
|
||||
.label("Поле ввода для кода:")
|
||||
.margins(MarginData::EqualsMargin(6))
|
||||
.align(Alignment::new(Align::Start, Align::Start))
|
||||
.build(true, WrapMode::Word, 64);
|
||||
.build(Some(64));
|
||||
|
||||
let output_code = Input::builder()
|
||||
let output_code = Input::<TextView>::builder()
|
||||
.label("Результат:")
|
||||
.margins(MarginData::EqualsMargin(6))
|
||||
.align(Alignment::new(Align::Start, Align::Start))
|
||||
.build(true, WrapMode::Word, 64);
|
||||
.build(Some(64));
|
||||
|
||||
output_code.get_input().set_editable(false);
|
||||
|
||||
for input in [&input_code, &output_code] {
|
||||
input.get_input().set_monospace(true);
|
||||
input.get_input().set_wrap_mode(WrapMode::Word);
|
||||
}
|
||||
|
||||
let clear_input_button = Button::builder()
|
||||
.set_align(Alignment::new(Align::Fill, Align::Fill))
|
||||
.label("Очистка полей")
|
||||
|
|
|
@ -1,29 +1,24 @@
|
|||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
use std::{cell::Cell, rc::Rc};
|
||||
|
||||
use crate::{
|
||||
model::{builder_traits::Product, models::SignalReduce, Frequency},
|
||||
model_utils::signal_reducer::{
|
||||
coef_of_signal_reduce, full_resistance_of_capacitor, reactive_resistance_of_capacitor,
|
||||
voltage_from_signal_source,
|
||||
},
|
||||
model_utils::signal_reducer::{find_by_frequency_value, set_default_values},
|
||||
view::{
|
||||
components::{info_bar::InfoBar, input::Input},
|
||||
properties::*,
|
||||
},
|
||||
view_utils::signal_reduce_input_utils::{get_error_message, parse_fields},
|
||||
view_utils::signal_reduce_utils::*,
|
||||
};
|
||||
|
||||
use glib::clone;
|
||||
|
||||
extern crate gio;
|
||||
|
||||
use gio::ListStore;
|
||||
|
||||
use gtk::{
|
||||
prelude::{BoxExt, ButtonExt, Cast, CastNone, GridExt, ListItemExt, ListModelExt, SorterExt},
|
||||
Align, WrapMode, *,
|
||||
prelude::{BoxExt, ButtonExt, Cast, GridExt, SorterExt},
|
||||
Align, *,
|
||||
};
|
||||
|
||||
use gtk4 as gtk;
|
||||
|
||||
pub fn signal_reducing_page(wrapper: &Box) {
|
||||
|
@ -31,9 +26,6 @@ pub fn signal_reducing_page(wrapper: &Box) {
|
|||
|
||||
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();
|
||||
|
||||
input_block.set_column_homogeneous(true);
|
||||
|
@ -46,37 +38,31 @@ pub fn signal_reducing_page(wrapper: &Box) {
|
|||
|
||||
let input_labels: [&str; 6] = ["l, м:", "Rм, Ом", "Cм, пФ:", "Rи, Ом:", "Vи, мВ", "f, мГц:"];
|
||||
|
||||
let all_inputs: Vec<Input> = input_labels
|
||||
let all_inputs: Vec<Input<Entry>> = input_labels
|
||||
.iter()
|
||||
.map(move |label| {
|
||||
Input::builder()
|
||||
.enumerate()
|
||||
.map(|(index, label)| {
|
||||
let elem = Input::<Entry>::builder()
|
||||
.label(label)
|
||||
.margins(MarginData::EqualsMargin(6))
|
||||
.align(input_label_alignment)
|
||||
.build(monospace, input_wrapping, input_height)
|
||||
.build_entry(None);
|
||||
|
||||
let row = index as i32 / 3;
|
||||
|
||||
input_block.attach(elem.get(), (index as i32) - (3 * row), row, 1, 1);
|
||||
|
||||
elem
|
||||
})
|
||||
.collect();
|
||||
|
||||
for (id, elem) in all_inputs.iter().enumerate() {
|
||||
let row = id as i32 / 3;
|
||||
|
||||
input_block.attach(elem.get(), (id as i32) - (3 * row), row, 1, 1);
|
||||
}
|
||||
|
||||
let calculate_button = Button::builder().label("Расчитать").build();
|
||||
|
||||
let result_table_headers_labels: [&str; 4] = ["f, МГц", "Xc, Ом", "Vп, мВ", "ζ"];
|
||||
|
||||
let model = ListStore::new::<Frequency>();
|
||||
let model_for_events = model.clone();
|
||||
|
||||
for number in (0..=100).step_by(5) {
|
||||
if number == 0 {
|
||||
model.append(&Frequency::new(1.0));
|
||||
} else if (number >= 70 && number % 10 == 0) || (number < 70 && number % 5 == 0) {
|
||||
model.append(&Frequency::new(number as f64));
|
||||
}
|
||||
}
|
||||
set_default_values(&model);
|
||||
|
||||
let numeric_sorter = CustomSorter::new(|a, b| {
|
||||
let a = a.downcast_ref::<Frequency>().unwrap().frequency();
|
||||
|
@ -85,12 +71,11 @@ pub fn signal_reducing_page(wrapper: &Box) {
|
|||
a.total_cmp(&b).into()
|
||||
});
|
||||
|
||||
let sorted_model = SortListModel::new(Some(model), Some(numeric_sorter.clone()));
|
||||
let sorted_model = SortListModel::new(Some(model.clone()), Some(numeric_sorter.clone()));
|
||||
|
||||
let selection_model = NoSelection::new(Some(sorted_model));
|
||||
let selection_model = NoSelection::new(Some(sorted_model.clone()));
|
||||
|
||||
let result_table = ColumnView::builder()
|
||||
.reorderable(true)
|
||||
.show_row_separators(true)
|
||||
.model(&selection_model)
|
||||
.build();
|
||||
|
@ -98,78 +83,19 @@ pub fn signal_reducing_page(wrapper: &Box) {
|
|||
result_table.connect_activate(clone!(
|
||||
#[strong]
|
||||
numeric_sorter,
|
||||
move |_, _| {
|
||||
numeric_sorter.changed(SorterChange::Different);
|
||||
}
|
||||
move |_, _| numeric_sorter.changed(SorterChange::Different)
|
||||
));
|
||||
|
||||
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)));
|
||||
});
|
||||
factory.connect_setup(column_view_setup_factory);
|
||||
|
||||
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::<Frequency>()
|
||||
.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.get();
|
||||
|
||||
let reactive_resist: f64 = reactive_resistance_of_capacitor(
|
||||
result_values.wire_capacity * 10f64.powi(-12),
|
||||
result_values.length,
|
||||
cell_value.frequency() * 10f64.powi(6),
|
||||
);
|
||||
|
||||
let full_resistance: f64 = full_resistance_of_capacitor(
|
||||
reactive_resist,
|
||||
result_values.source_resistance,
|
||||
result_values.wire_resistance,
|
||||
result_values.length,
|
||||
);
|
||||
|
||||
let signal_source_voltage: f64 = voltage_from_signal_source(
|
||||
result_values.source_voltage * 10f64.powi(-3),
|
||||
reactive_resist,
|
||||
full_resistance,
|
||||
) * 1000.0;
|
||||
|
||||
match label {
|
||||
"f, МГц" => {
|
||||
cell_label.set_label(&cell_value.frequency().to_string());
|
||||
}
|
||||
"Xc, Ом" => {
|
||||
cell_label.set_label(format!("{0:.1$}", reactive_resist, 6).as_str());
|
||||
}
|
||||
"Vп, мВ" => {
|
||||
cell_label.set_label(format!("{0:.1$}", signal_source_voltage, 6).as_str());
|
||||
}
|
||||
"ζ" => {
|
||||
let coef: f64 =
|
||||
coef_of_signal_reduce(result_values.source_voltage, signal_source_voltage);
|
||||
|
||||
cell_label.set_label(format!("{0:.1$}", coef, 6).as_str());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
factory.connect_bind(clone!(
|
||||
#[strong]
|
||||
values,
|
||||
move |factory, list| column_view_bind_factory(factory, list, values.get(), label)
|
||||
));
|
||||
|
||||
let column = ColumnViewColumn::builder()
|
||||
.title(label)
|
||||
|
@ -193,28 +119,23 @@ pub fn signal_reducing_page(wrapper: &Box) {
|
|||
|
||||
calculate_button.connect_clicked(clone!(
|
||||
#[strong]
|
||||
model_for_events,
|
||||
model,
|
||||
#[strong]
|
||||
result_table,
|
||||
move |_| match parse_fields(all_inputs.clone()) {
|
||||
Ok(results) => {
|
||||
values.set(results);
|
||||
|
||||
let new_elem = &Frequency::new(values.get().frequency);
|
||||
let new_elem = Frequency::new(values.get().frequency);
|
||||
|
||||
let exist_elem_pos = model_for_events.find_with_equal_func(|elem| {
|
||||
elem.downcast_ref::<Frequency>().unwrap().frequency() == new_elem.frequency()
|
||||
});
|
||||
let exist_elem_pos = find_by_frequency_value(&model, &new_elem);
|
||||
|
||||
match exist_elem_pos {
|
||||
Some(_) => {
|
||||
info_bar.set_text_label(Some("Данная частота уже была задана."));
|
||||
info_bar.show_infobar(5u64);
|
||||
}
|
||||
None => {
|
||||
model_for_events.append(&Frequency::new(values.get().frequency));
|
||||
|
||||
model_for_events.items_changed(0, 0, 1);
|
||||
model_for_events.items_changed(1, 1, 0);
|
||||
}
|
||||
if exist_elem_pos.is_some() {
|
||||
info_bar.set_text_label(Some("Данная частота уже была задана."));
|
||||
info_bar.show_infobar(5u64);
|
||||
} else {
|
||||
model.append(&new_elem);
|
||||
update_column_view(&result_table)
|
||||
}
|
||||
}
|
||||
Err(error) => {
|
||||
|
|
|
@ -23,7 +23,6 @@ pub enum MarginData {
|
|||
*/
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
||||
pub struct Size {
|
||||
pub width: i32,
|
||||
pub height: i32,
|
||||
|
@ -44,27 +43,6 @@ pub trait Setters {
|
|||
fn set_align(self, align: Alignment) -> Self;
|
||||
}
|
||||
|
||||
pub trait TextViewSetters {
|
||||
fn set_text_view_margin(self, margin: MarginData) -> Self;
|
||||
}
|
||||
|
||||
impl TextViewSetters for TextViewBuilder {
|
||||
fn set_text_view_margin(self, margin: MarginData) -> Self {
|
||||
match margin {
|
||||
MarginData::EqualsMargin(margin) => self
|
||||
.top_margin(margin)
|
||||
.left_margin(margin)
|
||||
.bottom_margin(margin)
|
||||
.right_margin(margin),
|
||||
MarginData::MultipleMargin(margins) => self
|
||||
.top_margin(margins.0)
|
||||
.left_margin(margins.1)
|
||||
.bottom_margin(margins.2)
|
||||
.right_margin(margins.3),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Macros
|
||||
*/
|
||||
|
@ -97,7 +75,7 @@ macro_rules! impl_setters {
|
|||
}
|
||||
|
||||
impl_setters! {ButtonBuilder, EntryBuilder, TextViewBuilder,
|
||||
BoxBuilder, SwitchBuilder, FrameBuilder, LabelBuilder}
|
||||
BoxBuilder, SwitchBuilder, FrameBuilder, LabelBuilder, PasswordEntryBuilder}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl Size {
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
@import url("info_bar.css");
|
||||
@import url("text_view.css");
|
|
@ -9,7 +9,8 @@ use gtk::{
|
|||
|
||||
pub fn load_css() {
|
||||
let style_provider = CssProvider::new();
|
||||
style_provider.load_from_path(Path::new("./src/view/styles/info_bar.css"));
|
||||
|
||||
style_provider.load_from_path(Path::new("./src/view/styles/base.css"));
|
||||
|
||||
style_context_add_provider_for_display(
|
||||
&Display::default().expect("Could not connect to a display"),
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
textview {
|
||||
border-radius: 5px;
|
||||
padding: 7px 8px;
|
||||
background: #E6E6E6;
|
||||
outline-offset: 2px;
|
||||
outline: 2px solid #81ABDF00;
|
||||
transition-duration: .15s;
|
||||
transition-timing-function: ease-in-out;
|
||||
}
|
||||
|
||||
textview:focus-within {
|
||||
outline-offset: -2px;
|
||||
outline: 2px solid #81ABDF;
|
||||
}
|
|
@ -53,8 +53,8 @@ pub fn ui(application: &adw::Application) {
|
|||
|
||||
let window = ApplicationWindow::builder()
|
||||
.title("Комплексная программа для лаб. работ")
|
||||
.width_request(700)
|
||||
.height_request(400)
|
||||
.width_request(800)
|
||||
.height_request(600)
|
||||
.application(application)
|
||||
.child(&application_box)
|
||||
.build();
|
||||
|
|
Loading…
Reference in New Issue