From 54619cd3f9b80d8e5986ce5a293158db5d66967c Mon Sep 17 00:00:00 2001 From: doryan04 Date: Sun, 10 Mar 2024 12:35:02 +0400 Subject: [PATCH] Fully refactored project architecture, imports and etc. --- Cargo.lock | 238 +++++++++--------- Cargo.toml | 4 +- src/controller.rs | 47 ---- .../controller.rs} | 0 .../event_handlers/button_event_handlers.rs | 34 +++ src/controller/event_handlers/mod.rs | 2 + .../event_handlers/switch_event_handlers.rs | 30 +++ src/controller/mod.rs | 4 + .../model_utils}/hamming_code_seven_four.rs | 77 +++++- src/controller/model_utils/mod.rs | 1 + src/controller/view_utils/input_utils.rs | 72 ++++++ src/controller/view_utils/mod.rs | 1 + src/main.rs | 24 +- src/model.rs | 61 ----- src/model/mod.rs | 1 + src/model/model.rs | 16 ++ src/ui_src/components/switch.rs | 152 ----------- src/ui_src/components/wrapper.rs | 20 -- src/ui_src/properties.rs | 118 --------- src/utils/model_utils/check_correct_input.rs | 11 - .../model_utils/from_string_to_vec_bits.rs | 14 -- src/utils/model_utils/processing_input.rs | 10 - src/utils/parse_input.rs | 29 --- src/view.rs | 151 ----------- src/view/components/mod.rs | 3 + src/view/components/switch.rs | 153 +++++++++++ src/view/components/tabs.rs | 71 ++++++ src/view/components/wrapper.rs | 23 ++ src/view/mod.rs | 3 + src/view/properties.rs | 120 +++++++++ src/view/view.rs | 195 ++++++++++++++ 31 files changed, 923 insertions(+), 762 deletions(-) delete mode 100644 src/controller.rs rename src/{utils/state_controller.rs => controller/controller.rs} (100%) create mode 100644 src/controller/event_handlers/button_event_handlers.rs create mode 100644 src/controller/event_handlers/mod.rs create mode 100644 src/controller/event_handlers/switch_event_handlers.rs create mode 100644 src/controller/mod.rs rename src/{utils/hamming_code_utils => controller/model_utils}/hamming_code_seven_four.rs (63%) create mode 100644 src/controller/model_utils/mod.rs create mode 100644 src/controller/view_utils/input_utils.rs create mode 100644 src/controller/view_utils/mod.rs delete mode 100644 src/model.rs create mode 100644 src/model/mod.rs create mode 100644 src/model/model.rs delete mode 100644 src/ui_src/components/switch.rs delete mode 100644 src/ui_src/components/wrapper.rs delete mode 100644 src/ui_src/properties.rs delete mode 100644 src/utils/model_utils/check_correct_input.rs delete mode 100644 src/utils/model_utils/from_string_to_vec_bits.rs delete mode 100644 src/utils/model_utils/processing_input.rs delete mode 100644 src/utils/parse_input.rs delete mode 100644 src/view.rs create mode 100644 src/view/components/mod.rs create mode 100644 src/view/components/switch.rs create mode 100644 src/view/components/tabs.rs create mode 100644 src/view/components/wrapper.rs create mode 100644 src/view/mod.rs create mode 100644 src/view/properties.rs create mode 100644 src/view/view.rs diff --git a/Cargo.lock b/Cargo.lock index b5b14a5..4283424 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -64,23 +64,22 @@ dependencies = [ [[package]] name = "cairo-rs" -version = "0.18.3" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f33613627f0dea6a731b0605101fad59ba4f193a52c96c4687728d822605a8a1" +checksum = "2650f66005301bd33cc486dec076e1293c4cecf768bc7ba9bf5d2b1be339b99c" dependencies = [ "bitflags", "cairo-sys-rs", "glib", "libc", - "once_cell", "thiserror", ] [[package]] name = "cairo-sys-rs" -version = "0.18.2" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" +checksum = "fd3bb3119664efbd78b5e6c93957447944f16bdbced84c17a9f41c7829b81e64" dependencies = [ "glib-sys", "libc", @@ -199,22 +198,21 @@ dependencies = [ [[package]] name = "gdk-pixbuf" -version = "0.18.3" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "446f32b74d22c33b7b258d4af4ffde53c2bf96ca2e29abdf1a785fe59bd6c82c" +checksum = "f6a23f8a0b5090494fd04924662d463f8386cc678dd3915015a838c1a3679b92" dependencies = [ "gdk-pixbuf-sys", "gio", "glib", "libc", - "once_cell", ] [[package]] name = "gdk-pixbuf-sys" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" +checksum = "3dcbd04c1b2c4834cc008b4828bc917d062483b88d26effde6342e5622028f96" dependencies = [ "gio-sys", "glib-sys", @@ -225,9 +223,9 @@ dependencies = [ [[package]] name = "gdk4" -version = "0.7.3" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edb019ad581f8ecf8ea8e4baa6df7c483a95b5a59be3140be6a9c3b0c632af6" +checksum = "9100b25604183f2fd97f55ef087fae96ab4934d7215118a35303e422688e6e4b" dependencies = [ "cairo-rs", "gdk-pixbuf", @@ -240,9 +238,9 @@ dependencies = [ [[package]] name = "gdk4-sys" -version = "0.7.2" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbab43f332a3cf1df9974da690b5bb0e26720ed09a228178ce52175372dcfef0" +checksum = "d0b76874c40bb8d1c7d03a7231e23ac75fa577a456cd53af32ec17ec8f121626" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -263,9 +261,9 @@ checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" [[package]] name = "gio" -version = "0.18.3" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d809baf02bdf1b5ef4ad3bf60dd9d4977149db4612b7bbb58e56aef168193b" +checksum = "2eae10b27b6dd27e22ed0d812c6387deba295e6fc004a8b379e459b663b05a02" dependencies = [ "futures-channel", "futures-core", @@ -274,7 +272,6 @@ dependencies = [ "gio-sys", "glib", "libc", - "once_cell", "pin-project-lite", "smallvec", "thiserror", @@ -282,22 +279,22 @@ dependencies = [ [[package]] name = "gio-sys" -version = "0.18.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" +checksum = "bcf8e1d9219bb294636753d307b030c1e8a032062cba74f493c431a5c8b81ce4" dependencies = [ "glib-sys", "gobject-sys", "libc", "system-deps", - "winapi", + "windows-sys", ] [[package]] name = "glib" -version = "0.18.3" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58cf801b6f7829fa76db37449ab67c9c98a2b1bf21076d9113225621e61a0fa6" +checksum = "ab9e86540b5d8402e905ad4ce7d6aa544092131ab564f3102175af176b90a053" dependencies = [ "bitflags", "futures-channel", @@ -311,20 +308,18 @@ dependencies = [ "gobject-sys", "libc", "memchr", - "once_cell", "smallvec", "thiserror", ] [[package]] name = "glib-macros" -version = "0.18.3" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72793962ceece3863c2965d7f10c8786323b17c7adea75a515809fa20ab799a5" +checksum = "0f5897ca27a83e4cdc7b4666850bade0a2e73e17689aabafcc9acddad9d823b8" dependencies = [ "heck", - "proc-macro-crate 2.0.0", - "proc-macro-error", + "proc-macro-crate", "proc-macro2", "quote", "syn 2.0.39", @@ -332,9 +327,9 @@ dependencies = [ [[package]] name = "glib-sys" -version = "0.18.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" +checksum = "630f097773d7c7a0bb3258df4e8157b47dc98bbfa0e60ad9ab56174813feced4" dependencies = [ "libc", "system-deps", @@ -342,9 +337,9 @@ dependencies = [ [[package]] name = "gobject-sys" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" +checksum = "c85e2b1080b9418dd0c58b498da3a5c826030343e0ef07bde6a955d28de54979" dependencies = [ "glib-sys", "libc", @@ -353,9 +348,9 @@ dependencies = [ [[package]] name = "graphene-rs" -version = "0.18.1" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2228cda1505613a7a956cca69076892cfbda84fc2b7a62b94a41a272c0c401" +checksum = "99e4d388e96c5f29e2b2f67045d229ddf826d0a8d6d282f94ed3b34452222c91" dependencies = [ "glib", "graphene-sys", @@ -364,9 +359,9 @@ dependencies = [ [[package]] name = "graphene-sys" -version = "0.18.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc4144cee8fc8788f2a9b73dc5f1d4e1189d1f95305c4cb7bd9c1af1cfa31f59" +checksum = "236ed66cc9b18d8adf233716f75de803d0bf6fc806f60d14d948974a12e240d0" dependencies = [ "glib-sys", "libc", @@ -376,9 +371,9 @@ dependencies = [ [[package]] name = "gsk4" -version = "0.7.3" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d958e351d2f210309b32d081c832d7de0aca0b077aa10d88336c6379bd01f7e" +checksum = "c65036fc8f99579e8cb37b12487969b707ab23ec8ab953682ff347cbd15d396e" dependencies = [ "cairo-rs", "gdk4", @@ -391,9 +386,9 @@ dependencies = [ [[package]] name = "gsk4-sys" -version = "0.7.3" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12bd9e3effea989f020e8f1ff3fa3b8c63ba93d43b899c11a118868853a56d55" +checksum = "bd24c814379f9c3199dc53e52253ee8d0f657eae389ab282c330505289d24738" dependencies = [ "cairo-sys-rs", "gdk4-sys", @@ -407,9 +402,9 @@ dependencies = [ [[package]] name = "gtk4" -version = "0.7.3" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeb51aa3e9728575a053e1f43543cd9992ac2477e1b186ad824fd4adfb70842" +checksum = "aa82753b8c26277e4af1446c70e35b19aad4fb794a7b143859e7eeb9a4025d83" dependencies = [ "cairo-rs", "field-offset", @@ -428,12 +423,12 @@ dependencies = [ [[package]] name = "gtk4-macros" -version = "0.7.2" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d57ec49cf9b657f69a05bca8027cff0a8dfd0c49e812be026fc7311f2163832f" +checksum = "40300bf071d2fcd4c94eacc09e84ec6fe73129d2ceb635cf7e55b026b5443567" dependencies = [ "anyhow", - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro-error", "proc-macro2", "quote", @@ -442,9 +437,9 @@ dependencies = [ [[package]] name = "gtk4-sys" -version = "0.7.3" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54d8c4aa23638ce9faa2caf7e2a27d4a1295af2155c8e8d28c4d4eeca7a65eb8" +checksum = "0db1b104138f087ccdc81d2c332de5dd049b89de3d384437cc1093b17cd2da18" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -487,6 +482,15 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "laboratory_works" +version = "0.1.0" +dependencies = [ + "bitvec", + "gtk4", + "tokio", +] + [[package]] name = "libc" version = "0.2.150" @@ -495,9 +499,9 @@ checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memoffset" @@ -536,30 +540,23 @@ dependencies = [ "memchr", ] -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - [[package]] name = "pango" -version = "0.18.3" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" +checksum = "7809e8af4df8d024a066106b72ca6bc7253a484ae3867041a96103ef8a13188d" dependencies = [ "gio", "glib", "libc", - "once_cell", "pango-sys", ] [[package]] name = "pango-sys" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" +checksum = "f52ef6a881c19fbfe3b1484df5cad411acaaba29dbec843941c3110d19f340ea" dependencies = [ "glib-sys", "gobject-sys", @@ -581,27 +578,17 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "proc-macro-crate" -version = "1.3.1" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "once_cell", - "toml_edit 0.19.15", -] - -[[package]] -name = "proc-macro-crate" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" -dependencies = [ - "toml_edit 0.20.7", + "toml_edit", ] [[package]] @@ -713,9 +700,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "syn" @@ -816,7 +803,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.21.0", + "toml_edit", ] [[package]] @@ -828,28 +815,6 @@ dependencies = [ "serde", ] -[[package]] -name = "toml_edit" -version = "0.19.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow", -] - -[[package]] -name = "toml_edit" -version = "0.20.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow", -] - [[package]] name = "toml_edit" version = "0.21.0" @@ -869,15 +834,6 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" -[[package]] -name = "untitled" -version = "0.1.0" -dependencies = [ - "bitvec", - "gtk4", - "tokio", -] - [[package]] name = "version-compare" version = "0.1.1" @@ -891,26 +847,70 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] -name = "winapi" -version = "0.3.9" +name = "windows-sys" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "windows-targets", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "windows-targets" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows_aarch64_gnullvm" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "winnow" diff --git a/Cargo.toml b/Cargo.toml index 883b3b6..60ff8f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "untitled" +name = "laboratory_works" version = "0.1.0" edition = "2021" @@ -7,5 +7,5 @@ edition = "2021" [dependencies] bitvec = "1.0.1" -gtk4 = "0.7.3" +gtk4 = "0.8.1" tokio = { version = "1.0.0", features = ["rt", "rt-multi-thread", "macros"] } diff --git a/src/controller.rs b/src/controller.rs deleted file mode 100644 index a59fe79..0000000 --- a/src/controller.rs +++ /dev/null @@ -1,47 +0,0 @@ -use gtk4 as gtk; - -use gtk::prelude::*; -use super::switch::*; - -pub struct EventHandler{ - component: C, - callback: F, -} - -impl EventHandler -where F: Fn(&C) + FnOnce(&C) + FnMut(&C){ - pub fn new(component: C, callback: F) -> EventHandler{ - Self{ - component, - callback, - } - } -} - -pub trait BtnEventHandler{ - fn on_click(self) -> (); -} - -pub trait SwEventHandler{ - fn on_toggle(self) -> (); -} - -impl BtnEventHandler for EventHandler - where F: Fn(&C) + FnOnce(&C) + FnMut(&C) + 'static, C: ButtonExt + WidgetExt{ - fn on_click(self) -> () { - self.component.connect_clicked(move |button| { - (self.callback)(button) - }); - } -} - -impl SwEventHandler for EventHandler - where F: Fn(&C) + FnOnce(&C) + FnMut(&C) + 'static, C: SwitchExt + WidgetExt{ - fn on_toggle(self) -> () { - self.component.connect_state_notify(move |switch| { - (self.callback)(switch) - }); - } -} - - diff --git a/src/utils/state_controller.rs b/src/controller/controller.rs similarity index 100% rename from src/utils/state_controller.rs rename to src/controller/controller.rs diff --git a/src/controller/event_handlers/button_event_handlers.rs b/src/controller/event_handlers/button_event_handlers.rs new file mode 100644 index 0000000..26572de --- /dev/null +++ b/src/controller/event_handlers/button_event_handlers.rs @@ -0,0 +1,34 @@ +pub mod button_event_handlers_module{ + + use crate::{ + model::model::model_module::*, + gtk::{ + *, + prelude::* + }, + }; + + impl EventHandler + where F: Fn(&C) + FnOnce(&C) + FnMut(&C){ + pub fn new(component: C, callback: F) -> EventHandler{ + Self{ + component, + callback, + } + } + } + + pub trait BtnEventHandler{ + fn on_click(self) -> (); + } + + impl BtnEventHandler for EventHandler + where F: Fn(&C) + FnOnce(&C) + FnMut(&C) + 'static, C: ButtonExt + WidgetExt{ + fn on_click(self) -> () { + self.component.connect_clicked(move |button| { + (self.callback)(button) + }); + } + } + +} \ No newline at end of file diff --git a/src/controller/event_handlers/mod.rs b/src/controller/event_handlers/mod.rs new file mode 100644 index 0000000..00540aa --- /dev/null +++ b/src/controller/event_handlers/mod.rs @@ -0,0 +1,2 @@ +pub mod button_event_handlers; +pub mod switch_event_handlers; \ No newline at end of file diff --git a/src/controller/event_handlers/switch_event_handlers.rs b/src/controller/event_handlers/switch_event_handlers.rs new file mode 100644 index 0000000..68a3d37 --- /dev/null +++ b/src/controller/event_handlers/switch_event_handlers.rs @@ -0,0 +1,30 @@ +pub mod switch_event_handlers_module{ + + use crate::{ + model::model::model_module::*, + view::components::switch::switch_module::SwitchExt, + gtk::{ + *, + prelude::* + }, + }; + + pub trait SwEventHandler{ + fn on_toggle(self) -> (); + } + + impl SwEventHandler for EventHandler + where F: Fn(&C) + FnOnce(&C) + FnMut(&C) + 'static, C: SwitchExt + WidgetExt{ + fn on_toggle(self) -> () { + self.component.connect_state_notify(move |switch| { + (self.callback)(switch) + }); + } + } + + pub fn clearing(output : &TextView, input: &TextView){ + input.buffer().set_text(""); + output.buffer().set_text(""); + } + +} \ No newline at end of file diff --git a/src/controller/mod.rs b/src/controller/mod.rs new file mode 100644 index 0000000..5a6e4b4 --- /dev/null +++ b/src/controller/mod.rs @@ -0,0 +1,4 @@ +pub mod controller; +pub mod view_utils; +pub mod model_utils; +pub mod event_handlers; \ No newline at end of file diff --git a/src/utils/hamming_code_utils/hamming_code_seven_four.rs b/src/controller/model_utils/hamming_code_seven_four.rs similarity index 63% rename from src/utils/hamming_code_utils/hamming_code_seven_four.rs rename to src/controller/model_utils/hamming_code_seven_four.rs index 916f5ea..22d9ab1 100644 --- a/src/utils/hamming_code_utils/hamming_code_seven_four.rs +++ b/src/controller/model_utils/hamming_code_seven_four.rs @@ -1,16 +1,62 @@ -// ошибочная позиция 1 false true true -// ошибочная позиция 2 false false true -// ошибочная позиция 3 true false true -// ошибочная позиция 4 false true false -// ошибочная позиция 5 true true false -// ошибочная позиция 6 true false false -// ошибочная позиция 7 false false false - pub mod hamming_code{ - use std::borrow::Borrow; - use std::collections::HashMap; - pub fn hamming_encrypt_data(data: &Vec, result_string: &mut String, length_of_code: usize) -> () { + use std::{borrow::Borrow, collections::HashMap}; + + use crate::{ + model::model::model_module::*, + controller::view_utils::input_utils::input_utils_module::*, + }; + + /// **Синдромы** + /// + /// ошибочная позиция 1 false true true. + /// + /// ошибочная позиция 2 false false true. + /// + /// ошибочная позиция 3 true false true. + /// + /// ошибочная позиция 4 false true false. + /// + /// ошибочная позиция 5 true true false. + /// + /// ошибочная позиция 6 true false false. + /// + /// ошибочная позиция 7 false false false. + + pub fn hamming(raw_input: String, mode: HammingMode) -> Result{ + + let length_of_code : usize = mode.clone() as usize; + + let prepared_input : String = processing_input(&raw_input); + + let (fc, sc) = check_correct_input(&raw_input, &prepared_input, length_of_code); + + if !fc || !sc { + + Err("Ошибка. Проверьте корректность ввода.".to_string()) + + } else { + + let mut data : String = String::new(); + + let prepared_data: Vec = from_string_to_vec_bits(prepared_input); + + match mode { + HammingMode::Encrypt => hamming_encrypt_data(&prepared_data, &mut data, length_of_code), + HammingMode::Decrypt => hamming_decrypt_data(&prepared_data, &mut data, length_of_code), + } + + return Ok(data); + + } + + } + + pub fn hamming_encrypt_data( + data: &Vec, + result_string: &mut String, + length_of_code: usize + ) { let mut i : usize = length_of_code; while i <= data.len(){ @@ -31,7 +77,12 @@ pub mod hamming_code{ } } - pub fn hamming_decrypt_data(data: &Vec, result_string: &mut String, length_of_code: usize) -> () { + pub fn hamming_decrypt_data( + data: &Vec, + result_string: &mut String, + length_of_code: usize + ) { + let mut i : usize = length_of_code; let syndromes : HashMap = HashMap::from( @@ -102,5 +153,7 @@ pub mod hamming_code{ } else { result_string.push_str(errors.as_str()) } + } + } \ No newline at end of file diff --git a/src/controller/model_utils/mod.rs b/src/controller/model_utils/mod.rs new file mode 100644 index 0000000..a9207ce --- /dev/null +++ b/src/controller/model_utils/mod.rs @@ -0,0 +1 @@ +pub mod hamming_code_seven_four; \ No newline at end of file diff --git a/src/controller/view_utils/input_utils.rs b/src/controller/view_utils/input_utils.rs new file mode 100644 index 0000000..9237bdb --- /dev/null +++ b/src/controller/view_utils/input_utils.rs @@ -0,0 +1,72 @@ +pub mod input_utils_module { + + use gtk4 as gtk; + + use std::ops::Deref; + use gtk::{*, prelude::*}; + use bitvec::{order::Lsb0, view::AsBits}; + + use crate::{ + model::model::model_module::*, + model_utils::hamming_code_seven_four::hamming_code::* + }; + + pub fn parse_input(input : &TextView, output : &TextView, mode: bool) -> (){ + + let (iter_start, iter_end) = input.buffer().bounds(); + let parsed_input : String = input + .buffer() + .text(&iter_start, &iter_end, false) + .to_string() + .trim() + .parse() + .unwrap(); + + let operation = if mode == false { + HammingMode::Encrypt + } else { + HammingMode::Decrypt + }; + + match hamming(parsed_input, operation) { + Ok(res) => output.buffer().set_text(res.trim_end()), + Err(rej) => output.buffer().set_text(rej.as_str()), + } + + } + + pub fn processing_input(input : &String) -> String { + + input + .split_ascii_whitespace() + .filter(|&x| { + x != "" + }) + .fold(String::new(), |c: String, n: &str| { c + n }) + + } + + pub fn check_correct_input(input: &String, prepared_input: &String, l: usize) -> (bool, bool){ + + let first_condition = input + .chars() + .all(|c| {c == '1' || c == '0' || c == ' '}); + + let second_condition = prepared_input.len() % l == 0; + + (first_condition, second_condition) + + } + + pub fn from_string_to_vec_bits(raw_data: String) -> Vec{ + + raw_data + .as_bits::() + .iter() + .step_by(8) + .map(|x| *x.deref() as u8) + .collect() + + } + +} \ No newline at end of file diff --git a/src/controller/view_utils/mod.rs b/src/controller/view_utils/mod.rs new file mode 100644 index 0000000..2973e77 --- /dev/null +++ b/src/controller/view_utils/mod.rs @@ -0,0 +1 @@ +pub mod input_utils; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index d520a8d..08f8536 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,29 +1,21 @@ +extern crate core; + use gtk4 as gtk; use gtk::*; -use view::*; use gtk::prelude::*; -#[path="ui_src/components/switch.rs"] -mod switch; - -#[path="ui_src/components/wrapper.rs"] -mod wrapper; - -#[path="ui_src/properties.rs"] -mod properties; - -#[path="utils/parse_input.rs"] -mod parse_input; - -#[path="utils/state_controller.rs"] -mod state_controller; - mod view; +use view::view::view_module::*; + mod model; + mod controller; +use controller::*; + fn main() { + let app = Application::builder() .application_id("com.github.gtk-rs.examples.basic") .build(); diff --git a/src/model.rs b/src/model.rs deleted file mode 100644 index ed9c5d7..0000000 --- a/src/model.rs +++ /dev/null @@ -1,61 +0,0 @@ -use std::ops::Deref; -use bitvec::prelude::{AsBits}; -use crate::model::processing_input::processing_input; -use crate::model::check_correct_input::check_correct_input; -use crate::model::from_string_to_vec_bits::from_string_to_vec_bits; -use crate::model::hamming_code::hamming_code::hamming_decrypt_data; -use crate::model::hamming_code::hamming_code::hamming_encrypt_data; - -#[path="utils/model_utils/processing_input.rs"] -mod processing_input; - -#[path="utils/model_utils/check_correct_input.rs"] -mod check_correct_input; - -#[path="utils/model_utils/from_string_to_vec_bits.rs"] -mod from_string_to_vec_bits; - -#[path="utils/hamming_code_utils/hamming_code_seven_four.rs"] -mod hamming_code; - -pub enum HammingMode{ - Encrypt, - Decrypt -} - -// ошибочная позиция 1 false true true -// ошибочная позиция 2 false false true -// ошибочная позиция 3 true false true -// ошибочная позиция 4 false true false -// ошибочная позиция 5 true true false -// ошибочная позиция 6 true false false -// ошибочная позиция 7 false false false - -pub fn hamming(raw_input: String, mode: HammingMode) -> Result{ - - let length_of_code : usize = if let HammingMode::Encrypt = mode { 4 } else { 7 }; - - let prepared_input : String = processing_input(&raw_input); - - let (fc, sc) = check_correct_input(&raw_input, &prepared_input, length_of_code); - - if !fc || !sc { - - Err("Ошибка. Проверьте корректность ввода.".to_string()) - - } else { - - let mut data : String = String::new(); - - let prepared_data: Vec = from_string_to_vec_bits(prepared_input); - - match mode { - HammingMode::Encrypt => hamming_encrypt_data(&prepared_data, &mut data, length_of_code), - HammingMode::Decrypt => hamming_decrypt_data(&prepared_data, &mut data, length_of_code), - } - - return Ok(data); - - } -} - diff --git a/src/model/mod.rs b/src/model/mod.rs new file mode 100644 index 0000000..99bbd12 --- /dev/null +++ b/src/model/mod.rs @@ -0,0 +1 @@ +pub mod model; \ No newline at end of file diff --git a/src/model/model.rs b/src/model/model.rs new file mode 100644 index 0000000..61568a3 --- /dev/null +++ b/src/model/model.rs @@ -0,0 +1,16 @@ +pub mod model_module{ + + #[repr(usize)] + #[derive(Clone)] + pub enum HammingMode{ + Encrypt = 4, + Decrypt = 7 + } + + pub struct EventHandler{ + pub(crate) component: C, + pub(crate) callback: F, + } + +} + diff --git a/src/ui_src/components/switch.rs b/src/ui_src/components/switch.rs deleted file mode 100644 index 364fbc4..0000000 --- a/src/ui_src/components/switch.rs +++ /dev/null @@ -1,152 +0,0 @@ -use gtk4 as gtk; - -use gtk::*; -use gtk::prelude::*; - -use glib::{ - signal::{connect_raw, SignalHandlerId}, - translate::*, -}; -use std::boxed::Box as Box_; - -mod wrapper; - -mod sealed { - pub trait Sealed {} - impl> Sealed for T {} -} - -pub trait SwitchExt: IsA + sealed::Sealed + 'static { - #[doc(alias = "gtk_switch_get_active")] - #[doc(alias = "get_active")] - fn is_active(&self) -> bool { - unsafe { from_glib(ffi::gtk_switch_get_active(self.as_ref().to_glib_none().0)) } - } - - #[doc(alias = "gtk_switch_get_state")] - #[doc(alias = "get_state")] - fn state(&self) -> bool { - unsafe { from_glib(ffi::gtk_switch_get_state(self.as_ref().to_glib_none().0)) } - } - - #[doc(alias = "gtk_switch_set_active")] - fn set_active(&self, is_active: bool) { - unsafe { - ffi::gtk_switch_set_active(self.as_ref().to_glib_none().0, is_active.into_glib()); - } - } - - #[doc(alias = "gtk_switch_set_state")] - fn set_state(&self, state: bool) { - unsafe { - ffi::gtk_switch_set_state(self.as_ref().to_glib_none().0, state.into_glib()); - } - } - - #[doc(alias = "activate")] - fn connect_activate(&self, f: F) -> SignalHandlerId { - unsafe extern "C" fn activate_trampoline, F: Fn(&P) + 'static>( - this: *mut ffi::GtkSwitch, - f: glib::ffi::gpointer, - ) { - let f: &F = &*(f as *const F); - f(Switch::from_glib_borrow(this).unsafe_cast_ref()) - } - unsafe { - let f: Box_ = Box_::new(f); - connect_raw( - self.as_ptr() as *mut _, - b"activate\0".as_ptr() as *const _, - Some(std::mem::transmute::<_, unsafe extern "C" fn()>( - activate_trampoline:: as *const (), - )), - Box_::into_raw(f), - ) - } - } - - fn emit_activate(&self) { - self.emit_by_name::<()>("activate", &[]); - } - - #[doc(alias = "state-set")] - fn connect_state_set glib::Propagation + 'static>( - &self, - f: F, - ) -> SignalHandlerId { - unsafe extern "C" fn state_set_trampoline< - P: IsA, - F: Fn(&P, bool) -> glib::Propagation + 'static, - >( - this: *mut ffi::GtkSwitch, - state: glib::ffi::gboolean, - f: glib::ffi::gpointer, - ) -> glib::ffi::gboolean { - let f: &F = &*(f as *const F); - f( - Switch::from_glib_borrow(this).unsafe_cast_ref(), - from_glib(state), - ) - .into_glib() - } - unsafe { - let f: Box_ = Box_::new(f); - connect_raw( - self.as_ptr() as *mut _, - b"state-set\0".as_ptr() as *const _, - Some(std::mem::transmute::<_, unsafe extern "C" fn()>( - state_set_trampoline:: as *const (), - )), - Box_::into_raw(f), - ) - } - } - - #[doc(alias = "active")] - fn connect_active_notify(&self, f: F) -> SignalHandlerId { - unsafe extern "C" fn notify_active_trampoline, F: Fn(&P) + 'static>( - this: *mut ffi::GtkSwitch, - _param_spec: glib::ffi::gpointer, - f: glib::ffi::gpointer, - ) { - let f: &F = &*(f as *const F); - f(Switch::from_glib_borrow(this).unsafe_cast_ref()) - } - unsafe { - let f: Box_ = Box_::new(f); - connect_raw( - self.as_ptr() as *mut _, - b"notify::active\0".as_ptr() as *const _, - Some(std::mem::transmute::<_, unsafe extern "C" fn()>( - notify_active_trampoline:: as *const (), - )), - Box_::into_raw(f), - ) - } - } - - #[doc(alias = "state")] - fn connect_state_notify(&self, f: F) -> SignalHandlerId { - unsafe extern "C" fn notify_state_trampoline, F: Fn(&P) + 'static>( - this: *mut ffi::GtkSwitch, - _param_spec: glib::ffi::gpointer, - f: glib::ffi::gpointer, - ) { - let f: &F = &*(f as *const F); - f(Switch::from_glib_borrow(this).unsafe_cast_ref()) - } - unsafe { - let f: Box_ = Box_::new(f); - connect_raw( - self.as_ptr() as *mut _, - b"notify::state\0".as_ptr() as *const _, - Some(std::mem::transmute::<_, unsafe extern "C" fn()>( - notify_state_trampoline:: as *const (), - )), - Box_::into_raw(f), - ) - } - } -} - -impl> SwitchExt for O {} diff --git a/src/ui_src/components/wrapper.rs b/src/ui_src/components/wrapper.rs deleted file mode 100644 index 28fdd3c..0000000 --- a/src/ui_src/components/wrapper.rs +++ /dev/null @@ -1,20 +0,0 @@ -use gtk4 as gtk; - -use gtk::Orientation; -use gtk::builders::BoxBuilder; -use gtk::Box; - -#[allow(dead_code)] -pub struct Wrapper; - -impl Wrapper{ - - pub fn row_builder() -> BoxBuilder { - Box::builder().orientation(Orientation::Vertical) - } - - pub fn col_builder() -> BoxBuilder { - Box::builder().orientation(Orientation::Horizontal) - } - -} diff --git a/src/ui_src/properties.rs b/src/ui_src/properties.rs deleted file mode 100644 index a3685a5..0000000 --- a/src/ui_src/properties.rs +++ /dev/null @@ -1,118 +0,0 @@ -use gtk4 as gtk; - -use gtk::{Align}; -use gtk::builders::*; - -/** - * Types - */ - -pub type Margin = (i32, i32, i32, i32); - -/** - * Enums - */ - -pub enum MarginData{ - EqualsMargin(i32), - MultipleMargin(Margin), -} - -/** - * Structs - */ - -#[allow(dead_code)] - -pub struct Size { - pub width: i32, - pub height: i32 -} - -pub struct Alignment { - pub horizontal: Align, - pub vertical : Align -} - -/** - * Traits - */ - -pub trait Setters{ - fn set_margin(self, margin: MarginData) -> Self; - 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 - */ - -macro_rules! impl_setters { - ($($t:ty),+) => { - $( - impl Setters for $t { - fn set_margin(self, margin: MarginData) -> Self{ - match margin{ - MarginData::EqualsMargin(margin) => - self.margin_top(margin) - .margin_start(margin) - .margin_bottom(margin) - .margin_end(margin), - MarginData::MultipleMargin(margins) => - self.margin_top(margins.0) - .margin_start(margins.1) - .margin_bottom(margins.2) - .margin_end(margins.3), - } - } - fn set_align(self, align: Alignment) -> Self { - self.halign(align.horizontal) - .valign(align.vertical) - } - } - )* - } -} - -impl_setters!{ButtonBuilder, EntryBuilder, TextViewBuilder, - BoxBuilder, SwitchBuilder, FrameBuilder, LabelBuilder} - -#[allow(dead_code)] -impl Size{ - pub fn new(w: i32, h: i32) -> Size{ - Size{ - width: w, - height: h, - } - } -} - -impl Alignment{ - pub fn new(horizontal: Align, vertical : Align) -> Alignment{ - Alignment{ - horizontal, - vertical, - } - } -} diff --git a/src/utils/model_utils/check_correct_input.rs b/src/utils/model_utils/check_correct_input.rs deleted file mode 100644 index d9f7b79..0000000 --- a/src/utils/model_utils/check_correct_input.rs +++ /dev/null @@ -1,11 +0,0 @@ -pub fn check_correct_input(input: &String, prepared_input: &String, l: usize) -> (bool, bool){ - - let first_condition = input - .chars() - .all(|c| {c == '1' || c == '0' || c == ' '}); - - let second_condition = prepared_input.len() % l == 0; - - (first_condition, second_condition) - -} \ No newline at end of file diff --git a/src/utils/model_utils/from_string_to_vec_bits.rs b/src/utils/model_utils/from_string_to_vec_bits.rs deleted file mode 100644 index 1747bb2..0000000 --- a/src/utils/model_utils/from_string_to_vec_bits.rs +++ /dev/null @@ -1,14 +0,0 @@ -use std::ops::Deref; -use bitvec::order::Lsb0; -use bitvec::prelude::AsBits; - -pub fn from_string_to_vec_bits(raw_data: String) -> Vec{ - - raw_data - .as_bits::() - .iter() - .step_by(8) - .map(|x| *x.deref() as u8) - .collect() - -} \ No newline at end of file diff --git a/src/utils/model_utils/processing_input.rs b/src/utils/model_utils/processing_input.rs deleted file mode 100644 index 487842b..0000000 --- a/src/utils/model_utils/processing_input.rs +++ /dev/null @@ -1,10 +0,0 @@ -pub fn processing_input(input : &String) -> String { - - input - .split_ascii_whitespace() - .filter(|&x| { - x != "" - }) - .fold(String::new(), |c: String, n: &str| { c + n }) - -} \ No newline at end of file diff --git a/src/utils/parse_input.rs b/src/utils/parse_input.rs deleted file mode 100644 index 24a3719..0000000 --- a/src/utils/parse_input.rs +++ /dev/null @@ -1,29 +0,0 @@ -use gtk4 as gtk; - -use gtk::*; -use gtk::prelude::*; -use super::model::*; - -pub fn parse_input(input : &TextView, output : &TextView, mode: bool) -> (){ - - let (iter_start, iter_end) = input.buffer().bounds(); - let parsed_input : String = input - .buffer() - .text(&iter_start, &iter_end, false) - .to_string() - .trim() - .parse() - .unwrap(); - - let operation = if mode == false { - HammingMode::Encrypt - } else { - HammingMode::Decrypt - }; - - match hamming(parsed_input, operation) { - Ok(res) => output.buffer().set_text(res.trim_end()), - Err(rej) => output.buffer().set_text(rej.as_str()), - } - -} \ No newline at end of file diff --git a/src/view.rs b/src/view.rs deleted file mode 100644 index b6d4edc..0000000 --- a/src/view.rs +++ /dev/null @@ -1,151 +0,0 @@ -use gtk4 as gtk; - -use gtk::*; -use gtk::prelude::*; -use super::wrapper::*; -use super::controller::*; -use super::parse_input::parse_input; -use super::state_controller::state_controller; -use super::properties::{MarginData, Setters, TextViewSetters, Alignment}; - -fn clearing(output : &TextView, input: &TextView){ - input.buffer().set_text(""); - output.buffer().set_text(""); -} - -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 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 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(); - - // actions - - EventHandler::new( - hamming_crypt_button.clone(), - move |_| { - 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| { - 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(); - - // separators - - let separator = Separator::builder() - .orientation(Orientation::Horizontal) - .build(); - - crypt_mode_wrapper.append(&crypt_mode_switch); - crypt_mode_wrapper.append(&crypt_mode_label); - - 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); - wrapper.append(&separator); - -} - -pub fn ui(application: &Application) { - - let mutual_wrapper = 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); - - let window = ApplicationWindow::builder() - .title("Комплексная программа для лаб. работ") - .width_request(650) - .height_request(400) - .application(application) - .child(&mutual_wrapper) - .build(); - - window.show(); -} \ No newline at end of file diff --git a/src/view/components/mod.rs b/src/view/components/mod.rs new file mode 100644 index 0000000..2eb2f35 --- /dev/null +++ b/src/view/components/mod.rs @@ -0,0 +1,3 @@ +pub mod wrapper; +pub mod switch; +pub mod tabs; diff --git a/src/view/components/switch.rs b/src/view/components/switch.rs new file mode 100644 index 0000000..706ae14 --- /dev/null +++ b/src/view/components/switch.rs @@ -0,0 +1,153 @@ +pub mod switch_module { + + use gtk4 as gtk; + + use gtk::{*, prelude::*}; + + use glib::{ + signal::{connect_raw, SignalHandlerId}, + translate::*, + }; + + use std::boxed::Box as Box_; + + mod sealed { + pub trait Sealed {} + impl> Sealed for T {} + } + + pub trait SwitchExt: IsA + sealed::Sealed + 'static { + #[doc(alias = "gtk_switch_get_active")] + #[doc(alias = "get_active")] + fn is_active(&self) -> bool { + unsafe { from_glib(ffi::gtk_switch_get_active(self.as_ref().to_glib_none().0)) } + } + + #[doc(alias = "gtk_switch_get_state")] + #[doc(alias = "get_state")] + fn state(&self) -> bool { + unsafe { from_glib(ffi::gtk_switch_get_state(self.as_ref().to_glib_none().0)) } + } + + #[doc(alias = "gtk_switch_set_active")] + fn set_active(&self, is_active: bool) { + unsafe { + ffi::gtk_switch_set_active(self.as_ref().to_glib_none().0, is_active.into_glib()); + } + } + + #[doc(alias = "gtk_switch_set_state")] + fn set_state(&self, state: bool) { + unsafe { + ffi::gtk_switch_set_state(self.as_ref().to_glib_none().0, state.into_glib()); + } + } + + #[doc(alias = "activate")] + fn connect_activate(&self, f: F) -> SignalHandlerId { + unsafe extern "C" fn activate_trampoline, F: Fn(&P) + 'static>( + this: *mut ffi::GtkSwitch, + f: glib::ffi::gpointer, + ) { + let f: &F = &*(f as *const F); + f(Switch::from_glib_borrow(this).unsafe_cast_ref()) + } + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"activate\0".as_ptr() as *const _, + Some(std::mem::transmute::<_, unsafe extern "C" fn()>( + activate_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } + + fn emit_activate(&self) { + self.emit_by_name::<()>("activate", &[]); + } + + #[doc(alias = "state-set")] + fn connect_state_set glib::Propagation + 'static>( + &self, + f: F, + ) -> SignalHandlerId { + unsafe extern "C" fn state_set_trampoline< + P: IsA, + F: Fn(&P, bool) -> glib::Propagation + 'static, + >( + this: *mut ffi::GtkSwitch, + state: glib::ffi::gboolean, + f: glib::ffi::gpointer, + ) -> glib::ffi::gboolean { + let f: &F = &*(f as *const F); + f( + Switch::from_glib_borrow(this).unsafe_cast_ref(), + from_glib(state), + ) + .into_glib() + } + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"state-set\0".as_ptr() as *const _, + Some(std::mem::transmute::<_, unsafe extern "C" fn()>( + state_set_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } + + #[doc(alias = "active")] + fn connect_active_notify(&self, f: F) -> SignalHandlerId { + unsafe extern "C" fn notify_active_trampoline, F: Fn(&P) + 'static>( + this: *mut ffi::GtkSwitch, + _param_spec: glib::ffi::gpointer, + f: glib::ffi::gpointer, + ) { + let f: &F = &*(f as *const F); + f(Switch::from_glib_borrow(this).unsafe_cast_ref()) + } + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"notify::active\0".as_ptr() as *const _, + Some(std::mem::transmute::<_, unsafe extern "C" fn()>( + notify_active_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } + + #[doc(alias = "state")] + fn connect_state_notify(&self, f: F) -> SignalHandlerId { + unsafe extern "C" fn notify_state_trampoline, F: Fn(&P) + 'static>( + this: *mut ffi::GtkSwitch, + _param_spec: glib::ffi::gpointer, + f: glib::ffi::gpointer, + ) { + let f: &F = &*(f as *const F); + f(Switch::from_glib_borrow(this).unsafe_cast_ref()) + } + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"notify::state\0".as_ptr() as *const _, + Some(std::mem::transmute::<_, unsafe extern "C" fn()>( + notify_state_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } + } + + impl> SwitchExt for O {} +} diff --git a/src/view/components/tabs.rs b/src/view/components/tabs.rs new file mode 100644 index 0000000..965e93f --- /dev/null +++ b/src/view/components/tabs.rs @@ -0,0 +1,71 @@ +pub mod tabs_module { + + use gtk4 as gtk; + + use gtk::{Notebook, Label, Box}; + + pub type TabLabel = Label; + pub type TabContent = Box; + + #[derive(Clone)] + pub struct TabsBuilder { + tabs: Vec<(TabLabel, TabContent)> + } + + pub struct Tabs { + tabs_wrapper: Notebook + } + + impl Tabs { + pub fn builder() -> TabsBuilder { + TabsBuilder{ + tabs: Vec::new(), + } + } + + pub fn get(self) -> Notebook { + self.tabs_wrapper + } + + } + + 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)); + } + + pub fn add_tab(mut self, label: &str, page: TabContent) -> Self { + self.append_tab_private(label, page); + + self + } + + pub fn add_tabs(mut self, labels: Vec<&str>, pages: Vec) -> Self { + for (label, page) in labels.iter().zip(pages) { + self.append_tab_private(label, page); + } + + self + } + + pub fn build(&mut self, group_name: &str) -> Tabs { + let tabs_wrapper = Notebook::builder() + .group_name(group_name) + .build(); + + self.tabs + .iter() + .for_each(|(label, content)| { + tabs_wrapper.append_page(content, Some(label)); + }); + + Tabs { + tabs_wrapper + } + } + + } + +} \ No newline at end of file diff --git a/src/view/components/wrapper.rs b/src/view/components/wrapper.rs new file mode 100644 index 0000000..0398747 --- /dev/null +++ b/src/view/components/wrapper.rs @@ -0,0 +1,23 @@ +pub mod wrapper_module { + + use gtk4 as gtk; + + use gtk::{Orientation, builders::BoxBuilder, Box}; + + #[allow(dead_code)] + pub struct Wrapper; + + impl Wrapper{ + + pub fn row_builder() -> BoxBuilder { + Box::builder().orientation(Orientation::Vertical) + } + + pub fn col_builder() -> BoxBuilder { + Box::builder().orientation(Orientation::Horizontal) + } + + } + +} + diff --git a/src/view/mod.rs b/src/view/mod.rs new file mode 100644 index 0000000..5b8a5f4 --- /dev/null +++ b/src/view/mod.rs @@ -0,0 +1,3 @@ +pub mod view; +pub mod components; +pub mod properties; \ No newline at end of file diff --git a/src/view/properties.rs b/src/view/properties.rs new file mode 100644 index 0000000..58a71f1 --- /dev/null +++ b/src/view/properties.rs @@ -0,0 +1,120 @@ +pub mod properties_module{ + use gtk4 as gtk; + + use gtk::{Align}; + use gtk::builders::*; + + /** + * Types + */ + + pub type Margin = (i32, i32, i32, i32); + + /** + * Enums + */ + + pub enum MarginData{ + EqualsMargin(i32), + MultipleMargin(Margin), + } + + /** + * Structs + */ + + #[allow(dead_code)] + + pub struct Size { + pub width: i32, + pub height: i32 + } + + pub struct Alignment { + pub horizontal: Align, + pub vertical : Align + } + + /** + * Traits + */ + + pub trait Setters{ + fn set_margin(self, margin: MarginData) -> Self; + 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 + */ + + macro_rules! impl_setters { + ($($t:ty),+) => { + $( + impl Setters for $t { + fn set_margin(self, margin: MarginData) -> Self{ + match margin{ + MarginData::EqualsMargin(margin) => + self.margin_top(margin) + .margin_start(margin) + .margin_bottom(margin) + .margin_end(margin), + MarginData::MultipleMargin(margins) => + self.margin_top(margins.0) + .margin_start(margins.1) + .margin_bottom(margins.2) + .margin_end(margins.3), + } + } + fn set_align(self, align: Alignment) -> Self { + self.halign(align.horizontal) + .valign(align.vertical) + } + } + )* + } + } + + impl_setters!{ButtonBuilder, EntryBuilder, TextViewBuilder, + BoxBuilder, SwitchBuilder, FrameBuilder, LabelBuilder} + + #[allow(dead_code)] + impl Size{ + pub fn new(w: i32, h: i32) -> Size{ + Size{ + width: w, + height: h, + } + } + } + + impl Alignment{ + pub fn new(horizontal: Align, vertical : Align) -> Alignment{ + Alignment{ + horizontal, + vertical, + } + } + } +} diff --git a/src/view/view.rs b/src/view/view.rs new file mode 100644 index 0000000..b6e582a --- /dev/null +++ b/src/view/view.rs @@ -0,0 +1,195 @@ +pub mod view_module{ + + use gtk4 as gtk; + + use gtk::{*, prelude::*}; + + use crate::{ + model::model::model_module::*, + view::{ + properties::properties_module::*, + components::{ + *, + tabs::tabs_module::*, + switch::switch_module::*, + wrapper::wrapper_module::*, + } + }, + controller::{ + controller::*, + view_utils::input_utils::input_utils_module::*, + event_handlers::{ + button_event_handlers::button_event_handlers_module::*, + switch_event_handlers::switch_event_handlers_module::*, + }, + } + }; + + 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: &Application) { + + let mutual_wrapper = 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); + + let second_wrapper = 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("Код Хафмана"))); + + let notebook = Tabs::builder() + .add_tabs( + vec!["Код Хэмминга", "Код Хафмана"], + vec![mutual_wrapper, second_wrapper] + ) + .build("Tabs") + .get(); + + let window = ApplicationWindow::builder() + .title("Комплексная программа для лаб. работ") + .width_request(650) + .height_request(400) + .application(application) + .child(¬ebook) + .build(); + + window.show(); + } + +} +