From 5687d6773ac0793440ab047b167ac2959ab3e207 Mon Sep 17 00:00:00 2001
From: doryan04 <sagiev2015@yandex.ru>
Date: Sun, 17 Mar 2024 21:34:12 +0400
Subject: [PATCH] added inputs components and created page for fifth lab

---
 .../builder_traits.rs}                        |   0
 src/model/mod.rs                              |   3 +-
 src/view/components/input.rs                  |  92 ++++++++++
 src/view/components/mod.rs                    |   4 +-
 src/view/components/pages.rs                  |  14 +-
 src/view/components/tabs.rs                   |  17 +-
 src/view/mod.rs                               |   3 +-
 src/view/pages/hamming_code.rs                | 152 ++++++++++++++++
 src/view/pages/mod.rs                         |   2 +
 src/view/pages/signal_reducing.rs             |  78 +++++++++
 src/view/view.rs                              | 162 ++----------------
 11 files changed, 359 insertions(+), 168 deletions(-)
 rename src/{view/components/builder_pattern_traits.rs => model/builder_traits.rs} (100%)
 create mode 100644 src/view/components/input.rs
 create mode 100644 src/view/pages/hamming_code.rs
 create mode 100644 src/view/pages/mod.rs
 create mode 100644 src/view/pages/signal_reducing.rs

diff --git a/src/view/components/builder_pattern_traits.rs b/src/model/builder_traits.rs
similarity index 100%
rename from src/view/components/builder_pattern_traits.rs
rename to src/model/builder_traits.rs
diff --git a/src/model/mod.rs b/src/model/mod.rs
index 99bbd12..8ad3783 100644
--- a/src/model/mod.rs
+++ b/src/model/mod.rs
@@ -1 +1,2 @@
-pub mod model;
\ No newline at end of file
+pub mod model;
+pub mod builder_traits;
\ No newline at end of file
diff --git a/src/view/components/input.rs b/src/view/components/input.rs
new file mode 100644
index 0000000..3117803
--- /dev/null
+++ b/src/view/components/input.rs
@@ -0,0 +1,92 @@
+use gtk4 as gtk;
+
+use crate::{
+    view::properties::*,
+    model::builder_traits::*
+};
+use gtk::{*, prelude::*};
+
+pub type InputLabel = String;
+
+pub struct Input {
+    component: Box
+}
+
+pub struct InputBuilder {
+    align: Align,
+    label: InputLabel,
+    margins: MarginData,
+}
+
+impl Product<InputBuilder, Box> for Input {
+    fn builder() -> InputBuilder {
+        InputBuilder {
+            align: Align::Start,
+            label: String::new(),
+            margins: MarginData::EqualsMargin(5),
+        }
+    }
+
+    fn get(self) -> Box {
+        self.component
+    }
+}
+
+impl InputBuilder {
+
+    pub fn set_label(mut self, label: &str) -> Self {
+
+        self.label = String::from(label);
+
+        self
+
+    }
+
+    pub fn set_align(mut self, align: Align) -> Self {
+
+        self.align = align;
+
+        self
+
+    }
+
+    pub fn set_margins(mut self, margin: MarginData) -> Self {
+
+        self.margins = margin;
+
+        self
+
+    }
+
+    pub fn build(self, monospace: bool, wrap_mode: WrapMode, input_height: i32) -> Input {
+
+        let input_component = Box::new(Orientation::Vertical, 0);
+
+        let input_label = Label::builder()
+            .halign(self.align)
+            .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(&input_label);
+        input_component.append(&text_view_input_frame);
+
+        Input {
+            component: input_component
+        }
+
+    }
+
+}
\ No newline at end of file
diff --git a/src/view/components/mod.rs b/src/view/components/mod.rs
index 49d6e39..e113937 100644
--- a/src/view/components/mod.rs
+++ b/src/view/components/mod.rs
@@ -1,5 +1,7 @@
 pub mod tabs;
+pub mod input;
 pub mod pages;
 pub mod switch;
 pub mod wrapper;
-pub mod builder_pattern_traits;
+
+use crate::model::builder_traits;
diff --git a/src/view/components/pages.rs b/src/view/components/pages.rs
index 9a85e42..e956dec 100644
--- a/src/view/components/pages.rs
+++ b/src/view/components/pages.rs
@@ -12,7 +12,7 @@ use gtk::{
     prelude::{BoxExt, IsA},
 };
 
-use crate::view::components::builder_pattern_traits::{Builder, Product};
+use crate::view::components::builder_traits::{Builder, Product};
 
 pub type Page<'a> = (&'a str, &'a str, &'a Box);
 
@@ -25,6 +25,7 @@ pub struct PagesBuilder{
 }
 
 impl Product<PagesBuilder, Box> for Pages {
+
     fn builder() -> PagesBuilder {
         PagesBuilder {
             pages_content: Stack::new(),
@@ -34,9 +35,11 @@ impl Product<PagesBuilder, Box> for Pages {
     fn get(self) -> Box {
         self.wrapper
     }
+
 }
 
 impl Builder<Pages, Page<'_>, i32> for PagesBuilder{
+
     fn build(&self, build_param: i32) -> Pages {
         let stack_sidebar = StackSidebar::new();
         let stack_switcher = StackSwitcher::new();
@@ -56,17 +59,18 @@ impl Builder<Pages, Page<'_>, i32> for PagesBuilder{
 
     fn append_item(self, item: Page) -> Self {
         self.append_page_private(item);
+
         self
     }
 
     fn append_items(self, items: Vec<Page>) -> Self {
-        items.iter()
-            .for_each(|&item| {
-                self.append_page_private(item);
-            });
+        for item in items {
+            self.append_page_private(item);
+        }
 
         self
     }
+
 }
 
 impl PagesBuilder {
diff --git a/src/view/components/tabs.rs b/src/view/components/tabs.rs
index b206c46..8be52f2 100644
--- a/src/view/components/tabs.rs
+++ b/src/view/components/tabs.rs
@@ -1,12 +1,11 @@
 use gtk4 as gtk;
 
-use std::boxed::Box as BoxPtr;
 use gtk::{Notebook, Label, Box};
-use super::builder_pattern_traits::*;
+use super::builder_traits::*;
 
 pub type TabLabel = Label;
 pub type TabContent = Box;
-pub type TabPage = (BoxPtr<str>, TabContent);
+pub type TabPage<'a> = (&'a str, TabContent);
 
 #[derive(Clone)]
 pub struct TabsBuilder {
@@ -31,7 +30,7 @@ impl Product<TabsBuilder, Notebook> for Tabs {
 
 }
 
-impl Builder<Tabs, TabPage, &str> for TabsBuilder{
+impl Builder<Tabs, TabPage<'_>, &str> for TabsBuilder{
 
     fn build(&self, build_param: &str) -> Tabs {
         let tabs_wrapper = Notebook::builder()
@@ -50,14 +49,14 @@ impl Builder<Tabs, TabPage, &str> for TabsBuilder{
     }
 
     fn append_item(mut self, item: TabPage) -> Self {
-        self.append_tab_private(&item.0, item.1);
+        self.append_tab_private(item);
 
         self
     }
 
     fn append_items(mut self, items: Vec<TabPage>) -> Self {
         for item in items{
-            self.append_tab_private(&item.0, item.1);
+            self.append_tab_private(item);
         }
 
         self
@@ -68,9 +67,9 @@ impl Builder<Tabs, TabPage, &str> for TabsBuilder{
 
 impl TabsBuilder {
 
-    fn append_tab_private(&mut self, label: &str, page: TabContent) {
-        let tab_label = Label::new(Some(label));
-        self.tabs.push((tab_label, page));
+    fn append_tab_private(&mut self, item: TabPage) {
+        let tab_label = Label::new(Some(item.0));
+        self.tabs.push((tab_label, item.1));
     }
 
 }
\ No newline at end of file
diff --git a/src/view/mod.rs b/src/view/mod.rs
index 5b8a5f4..d832617 100644
--- a/src/view/mod.rs
+++ b/src/view/mod.rs
@@ -1,3 +1,4 @@
 pub mod view;
+pub mod pages;
 pub mod components;
-pub mod properties;
\ No newline at end of file
+pub mod properties;
diff --git a/src/view/pages/hamming_code.rs b/src/view/pages/hamming_code.rs
new file mode 100644
index 0000000..c0cbe6e
--- /dev/null
+++ b/src/view/pages/hamming_code.rs
@@ -0,0 +1,152 @@
+use gtk4 as gtk;
+
+use crate::{
+    model::model::*,
+    view::{
+        properties::*,
+        components::{
+            *,
+            switch::*,
+            wrapper::*,
+        }
+    },
+    controller::{
+        controller::*,
+        view_utils::input_utils::*,
+        event_handlers::{
+            button_event_handlers::*,
+            switch_event_handlers::*,
+        },
+    }
+};
+
+use gtk::{*, prelude::*};
+
+pub fn hamming_code_page(wrapper: &Box) -> (){
+
+    // input
+
+    let hamming_text_view_input_label = Label::builder()
+        .halign(Align::Start)
+        .set_margin(MarginData::MultipleMargin((10, 5, 0, 0)))
+        .label(String::from("Поле ввода для кода:"))
+        .build();
+
+    let hamming_text_view_input = TextView::builder()
+        .monospace(true)
+        .set_text_view_margin(MarginData::EqualsMargin(6))
+        .wrap_mode(WrapMode::Word)
+        .build();
+
+    let hamming_text_view_input_frame = Frame::builder()
+        .child(&hamming_text_view_input)
+        .height_request(64)
+        .set_margin(MarginData::MultipleMargin((0, 5, 0, 5)))
+        .build();
+
+    // output
+
+    let hamming_text_view_output_label = Label::builder()
+        .halign(Align::Start)
+        .set_margin(MarginData::MultipleMargin((10, 5, 0, 0)))
+        .label(String::from("Результат:"))
+        .build();
+
+    let hamming_text_view_output = TextView::builder()
+        .monospace(true)
+        .editable(false)
+        .set_text_view_margin(MarginData::EqualsMargin(6))
+        .wrap_mode(WrapMode::Word)
+        .build();
+
+    let hamming_text_view_output_frame = Frame::builder()
+        .child(&hamming_text_view_output)
+        .height_request(64)
+        .set_margin(MarginData::MultipleMargin((0, 5, 0, 5)))
+        .build();
+
+    // interactive panel
+
+    let clear_input_button =
+        Button::builder()
+            .set_align(Alignment::new(Align::Fill, Align::Fill))
+            .label("Очистка полей")
+            .build();
+
+    let hamming_crypt_button = Button::builder()
+        .set_align(Alignment::new(Align::Fill, Align::Fill))
+        .label("Выполнить")
+        .build();
+
+    let crypt_mode_switch = Switch::new();
+
+    let crypt_mode_label = Label::builder()
+        .label("Режим: кодирование")
+        .build();
+
+    // references for binding actions
+
+    let clear_input_button_to_handle = clear_input_button.clone();
+
+    let crypt_mode_label_to_handle = crypt_mode_label.clone();
+    let crypt_mode_switch_to_handle = crypt_mode_switch.clone();
+
+    let text_view_input_for_parse = hamming_text_view_input.clone();
+    let text_view_output_for_output = hamming_text_view_output.clone();
+
+    let text_view_input_for_clearing = hamming_text_view_input.clone();
+    let text_view_output_for_clearing = hamming_text_view_input.clone();
+
+    // actions
+
+    EventHandler::new(
+        clear_input_button_to_handle,
+        move |_| {
+            clearing(&text_view_input_for_clearing, &text_view_output_for_clearing);
+        }
+    ).on_click();
+
+    EventHandler::new(
+        hamming_crypt_button.clone(),
+        move |button: &Button| {
+            parse_input(
+                &text_view_input_for_parse,
+                &text_view_output_for_output,
+                crypt_mode_switch_to_handle.state()
+            )
+        }).on_click();
+
+    EventHandler::new(
+        crypt_mode_switch.clone(),
+        move |s : &Switch| {
+            state_controller(s, &crypt_mode_label_to_handle);
+        }).on_toggle();
+
+    // wrappers
+
+    let crypt_mode_wrapper = Wrapper::col_builder()
+        .set_align(Alignment::new(Align::Fill, Align::Center))
+        .hexpand(true)
+        .spacing(10)
+        .build();
+
+    let interactive_components_wrapper = Wrapper::col_builder()
+        .set_align(Alignment::new(Align::Fill, Align::Fill))
+        .set_margin(MarginData::MultipleMargin((0, 5, 0, 5)))
+        .spacing(10)
+        .build();
+
+    crypt_mode_wrapper.append(&crypt_mode_switch);
+    crypt_mode_wrapper.append(&crypt_mode_label);
+
+    interactive_components_wrapper.append(&clear_input_button);
+    interactive_components_wrapper.append(&crypt_mode_wrapper);
+    interactive_components_wrapper.append(&hamming_crypt_button);
+
+    wrapper.append(&hamming_text_view_input_label);
+    wrapper.append(&hamming_text_view_input_frame);
+    wrapper.append(&interactive_components_wrapper);
+    wrapper.append(&hamming_text_view_output_label);
+    wrapper.append(&hamming_text_view_output_frame);
+
+}
\ No newline at end of file
diff --git a/src/view/pages/mod.rs b/src/view/pages/mod.rs
new file mode 100644
index 0000000..975bbcd
--- /dev/null
+++ b/src/view/pages/mod.rs
@@ -0,0 +1,2 @@
+pub mod hamming_code;
+pub mod signal_reducing;
\ No newline at end of file
diff --git a/src/view/pages/signal_reducing.rs b/src/view/pages/signal_reducing.rs
new file mode 100644
index 0000000..8c51a61
--- /dev/null
+++ b/src/view/pages/signal_reducing.rs
@@ -0,0 +1,78 @@
+use gtk4 as gtk;
+
+use gtk::{*, prelude::*};
+use crate::model::builder_traits::Product;
+use crate::view::{
+    properties::*,
+    components::{
+        wrapper::*,
+        input::Input,
+    },
+};
+
+pub fn signal_reducing_page(wrapper: &Box) {
+
+    let inputs_first_line = Box::new(Orientation::Horizontal, 5);
+
+    inputs_first_line.set_valign(Align::Fill);
+
+    let input_height : i32 = 20;
+
+    let wire_length_input = Input::builder()
+        .set_label("Длина провода (L = [м]):")
+        .set_align(Align::Fill)
+        .set_margins(MarginData::EqualsMargin(5))
+        .build(true, WrapMode::Word, input_height)
+        .get();
+
+    let resistance_input = Input::builder()
+        .set_label("Сопротивление (Rм = [Ом * м]):")
+        .set_align(Align::Fill)
+        .set_margins(MarginData::EqualsMargin(5))
+        .build(true, WrapMode::Word, input_height)
+        .get();
+
+    let capacity_input = Input::builder()
+        .set_label("Ёмкость (Cм = [пФ * м]):")
+        .set_align(Align::Fill)
+        .set_margins(MarginData::EqualsMargin(5))
+        .build(true, WrapMode::Word, input_height)
+        .get();
+
+    let inputs_second_line = Box::new(Orientation::Horizontal, 5);
+
+    inputs_second_line.set_valign(Align::Fill);
+
+    let voltage_input = Input::builder()
+        .set_label("Напряжение (Vи = [мВ]):")
+        .set_align(Align::Fill)
+        .set_margins(MarginData::EqualsMargin(5))
+        .build(true, WrapMode::Word, input_height)
+        .get();
+
+    let source_implicit_resistance_input = Input::builder()
+        .set_label("Сопротивление источника (R = [Ом]):")
+        .set_align(Align::Fill)
+        .set_margins(MarginData::EqualsMargin(5))
+        .build(true, WrapMode::Word, input_height)
+        .get();
+
+    let freq_input = Input::builder()
+        .set_label("Частота (f = [МГц]):")
+        .set_align(Align::Fill)
+        .set_margins(MarginData::EqualsMargin(5))
+        .build(true, WrapMode::Word, input_height)
+        .get();
+
+
+    inputs_first_line.append(&wire_length_input);
+    inputs_first_line.append(&resistance_input);
+    inputs_first_line.append(&capacity_input);
+    inputs_second_line.append(&voltage_input);
+    inputs_second_line.append(&source_implicit_resistance_input);
+    inputs_second_line.append(&freq_input);
+
+    wrapper.append(&inputs_first_line);
+    wrapper.append(&inputs_second_line);
+
+}
\ No newline at end of file
diff --git a/src/view/view.rs b/src/view/view.rs
index 46b303b..fbd439c 100644
--- a/src/view/view.rs
+++ b/src/view/view.rs
@@ -1,190 +1,50 @@
-use crate::view::components::builder_pattern_traits::{Builder, Product};
+use crate::model::builder_traits::*;
 use gtk4 as gtk;
 
-use gtk::{*, prelude::*};
-use gtk4::StackTransitionType::SlideLeftRight;
+use gtk::{*, prelude::*, StackTransitionType::SlideLeftRight};
 
 use crate::{
-    model::model::*,
     view::{
         properties::*,
         components::{
             *,
-            tabs::*,
-            switch::*,
             wrapper::*,
-        }
-    },
-    controller::{
-        controller::*,
-        view_utils::input_utils::*,
-        event_handlers::{
-            button_event_handlers::*,
-            switch_event_handlers::*,
         },
-    }
+        pages::*
+    },
 };
 use crate::view::components::pages::Pages;
 
-pub fn laboratory_work_first_section(wrapper: &Box) -> (){
-
-    // input
-
-    let hamming_text_view_input_label = Label::builder()
-        .halign(Align::Start)
-        .set_margin(MarginData::MultipleMargin((10, 5, 0, 0)))
-        .label(String::from("Поле ввода для кода:"))
-        .build();
-
-    let hamming_text_view_input = TextView::builder()
-        .monospace(true)
-        .set_text_view_margin(MarginData::EqualsMargin(6))
-        .wrap_mode(WrapMode::Word)
-        .build();
-
-    let hamming_text_view_input_frame = Frame::builder()
-        .child(&hamming_text_view_input)
-        .height_request(64)
-        .set_margin(MarginData::MultipleMargin((0, 5, 0, 5)))
-        .build();
-
-    // output
-
-    let hamming_text_view_output_label = Label::builder()
-        .halign(Align::Start)
-        .set_margin(MarginData::MultipleMargin((10, 5, 0, 0)))
-        .label(String::from("Результат:"))
-        .build();
-
-    let hamming_text_view_output = TextView::builder()
-        .monospace(true)
-        .editable(false)
-        .set_text_view_margin(MarginData::EqualsMargin(6))
-        .wrap_mode(WrapMode::Word)
-        .build();
-
-    let hamming_text_view_output_frame = Frame::builder()
-        .child(&hamming_text_view_output)
-        .height_request(64)
-        .set_margin(MarginData::MultipleMargin((0, 5, 0, 5)))
-        .build();
-
-    // interactive panel
-
-    let clear_input_button =
-        Button::builder()
-            .set_align(Alignment::new(Align::Fill, Align::Fill))
-            .label("Очистка полей")
-            .build();
-
-    let hamming_crypt_button = Button::builder()
-        .set_align(Alignment::new(Align::Fill, Align::Fill))
-        .label("Выполнить")
-        .build();
-
-    let crypt_mode_switch = Switch::new();
-
-    let crypt_mode_label = Label::builder()
-        .label("Режим: кодирование")
-        .build();
-
-    // references for binding actions
-
-    let clear_input_button_to_handle = clear_input_button.clone();
-
-    let crypt_mode_label_to_handle = crypt_mode_label.clone();
-    let crypt_mode_switch_to_handle = crypt_mode_switch.clone();
-
-    let text_view_input_for_parse = hamming_text_view_input.clone();
-    let text_view_output_for_output = hamming_text_view_output.clone();
-
-    let text_view_input_for_clearing = hamming_text_view_input.clone();
-    let text_view_output_for_clearing = hamming_text_view_input.clone();
-
-    // actions
-
-    EventHandler::new(
-        clear_input_button_to_handle,
-        move |_| {
-            clearing(&text_view_input_for_clearing, &text_view_output_for_clearing);
-        }
-    ).on_click();
-
-    EventHandler::new(
-        hamming_crypt_button.clone(),
-        move |button: &Button| {
-            parse_input(
-                &text_view_input_for_parse,
-                &text_view_output_for_output,
-                crypt_mode_switch_to_handle.state()
-            )
-        }).on_click();
-
-    EventHandler::new(
-        crypt_mode_switch.clone(),
-        move |s : &Switch| {
-            state_controller(s, &crypt_mode_label_to_handle);
-        }).on_toggle();
-
-    // wrappers
-
-    let crypt_mode_wrapper = Wrapper::col_builder()
-        .set_align(Alignment::new(Align::Fill, Align::Center))
-        .hexpand(true)
-        .spacing(10)
-        .build();
-
-    let interactive_components_wrapper = Wrapper::col_builder()
-        .set_align(Alignment::new(Align::Fill, Align::Fill))
-        .set_margin(MarginData::MultipleMargin((0, 5, 0, 5)))
-        .spacing(10)
-        .build();
-
-    crypt_mode_wrapper.append(&crypt_mode_switch);
-    crypt_mode_wrapper.append(&crypt_mode_label);
-
-    interactive_components_wrapper.append(&clear_input_button);
-    interactive_components_wrapper.append(&crypt_mode_wrapper);
-    interactive_components_wrapper.append(&hamming_crypt_button);
-
-    wrapper.append(&hamming_text_view_input_label);
-    wrapper.append(&hamming_text_view_input_frame);
-    wrapper.append(&interactive_components_wrapper);
-    wrapper.append(&hamming_text_view_output_label);
-    wrapper.append(&hamming_text_view_output_frame);
-
-}
-
 pub fn ui(application: &adw::Application) {
 
-    let mutual_wrapper = Wrapper::row_builder()
+    let hamming_code = Wrapper::row_builder()
         .set_align(Alignment::new(Align::Fill, Align::Fill))
         .set_margin(MarginData::EqualsMargin(15))
         .spacing(10)
         .build();
 
-    laboratory_work_first_section(&mutual_wrapper);
+    hamming_code::hamming_code_page(&hamming_code);
 
-    let second_wrapper = Wrapper::row_builder()
+    let signal_reducing = Wrapper::row_builder()
         .set_align(Alignment::new(Align::Fill, Align::Fill))
         .set_margin(MarginData::EqualsMargin(15))
         .spacing(10)
         .build();
 
-    second_wrapper.append(&Label::new(Some("Код Хафмана")));
+    signal_reducing::signal_reducing_page(&signal_reducing);
 
     let pages = Pages::builder()
         .set_transition(SlideLeftRight, 200)
         .append_items(vec![
-            ("Код Хэмминга", "Код Хэмминга", &mutual_wrapper),
-            ("Код Хафмана", "Код Хафмана", &second_wrapper)
+            ("Код Хэмминга", "Код Хэмминга", &hamming_code),
+            ("Затухание сигнала", "Затухание сигнала", &signal_reducing)
         ])
         .build(5)
         .get();
 
     let window = ApplicationWindow::builder()
         .title("Комплексная программа для лаб. работ")
-        .width_request(650)
+        .width_request(700)
         .height_request(400)
         .application(application)
         .child(&pages)