From e4791d534e4adf18a18ab5ceee4e738102de69a5 Mon Sep 17 00:00:00 2001 From: Guangzong Chen Date: Mon, 27 Sep 2021 00:05:02 -0400 Subject: [PATCH] update ui and add some function --- Cargo.lock | 219 ++++++++++++++++++++++++++++----------------- Cargo.toml | 3 +- src/main.rs | 241 +++++++++++++++++++++++++++++++++++++++++--------- src/style.css | 9 ++ 4 files changed, 345 insertions(+), 127 deletions(-) create mode 100644 src/style.css diff --git a/Cargo.lock b/Cargo.lock index d15183b..01095dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,30 +38,6 @@ version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1" -[[package]] -name = "atk" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a83b21d2aa75e464db56225e1bda2dd5993311ba1095acaa8fa03d1ae67026ba" -dependencies = [ - "atk-sys", - "bitflags", - "glib", - "libc", -] - -[[package]] -name = "atk-sys" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "badcf670157c84bb8b1cf6b5f70b650fed78da2033c9eed84c4e49b11cbe83ea" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", -] - [[package]] name = "atty" version = "0.2.14" @@ -106,7 +82,7 @@ checksum = "d7c9c3928781e8a017ece15eace05230f04b647457d170d2d9641c94a444ff80" dependencies = [ "glib-sys", "libc", - "system-deps", + "system-deps 3.2.0", ] [[package]] @@ -124,6 +100,15 @@ dependencies = [ "smallvec", ] +[[package]] +name = "cfg-expr" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edae0b9625d1fce32f7d64b71784d9b1bf8469ec1a9c417e44aaf16a9cbd7571" +dependencies = [ + "smallvec", +] + [[package]] name = "cfg-if" version = "0.1.10" @@ -215,22 +200,6 @@ dependencies = [ "slab", ] -[[package]] -name = "gdk" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a453eae5ec10345b3a96ca1b547328bfc94edd40aa95b08f14bb4c35863db140" -dependencies = [ - "bitflags", - "cairo-rs", - "gdk-pixbuf", - "gdk-sys", - "gio", - "glib", - "libc", - "pango", -] - [[package]] name = "gdk-pixbuf" version = "0.14.0" @@ -253,24 +222,40 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps", + "system-deps 3.2.0", ] [[package]] -name = "gdk-sys" -version = "0.14.0" +name = "gdk4" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e091b3d3d6696949ac3b3fb3c62090e5bfd7bd6850bef5c3c5ea701de1b1f1e" +checksum = "4c0f7f98ad25b81ac9462f74a091b0e4c0983ed1e74d19a38230c772b4dcef81" +dependencies = [ + "bitflags", + "cairo-rs", + "gdk-pixbuf", + "gdk4-sys", + "gio", + "glib", + "libc", + "pango", +] + +[[package]] +name = "gdk4-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "262a79666b42e1884577f11a050439a964b95dec55343ac6ace7930e1415fa18" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", "gio-sys", "glib-sys", "gobject-sys", + "graphene-sys", "libc", "pango-sys", - "pkg-config", - "system-deps", + "system-deps 4.0.0", ] [[package]] @@ -299,7 +284,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps", + "system-deps 3.2.0", "winapi", ] @@ -344,7 +329,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c1d60554a212445e2a858e42a0e48cece1bd57b311a19a9468f70376cf554ae" dependencies = [ "libc", - "system-deps", + "system-deps 3.2.0", ] [[package]] @@ -355,58 +340,96 @@ checksum = "aa92cae29759dae34ab5921d73fff5ad54b3d794ab842c117e36cafc7994c3f5" dependencies = [ "glib-sys", "libc", - "system-deps", + "system-deps 3.2.0", ] [[package]] -name = "gtk" -version = "0.14.1" +name = "graphene-rs" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6603bb79ded6ac6f3bac203794383afa8b1d6a8656d34a93a88f0b22826cd46c" +checksum = "f1460a39f06e491e6112f27e71e51435c833ba370723224dd1743dfd1f201f19" +dependencies = [ + "glib", + "graphene-sys", + "libc", +] + +[[package]] +name = "graphene-sys" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7d23fb7a9547e5f072a7e0cd49cd648fedeb786d122b106217511980cbb8962" +dependencies = [ + "glib-sys", + "libc", + "pkg-config", + "system-deps 3.2.0", +] + +[[package]] +name = "gsk4" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20b71f2e2cc699c2e0fbfa22899eeaffd84f9c1dc01e9263deac8664eec22dc0" +dependencies = [ + "bitflags", + "cairo-rs", + "gdk4", + "glib", + "graphene-rs", + "gsk4-sys", + "libc", + "pango", +] + +[[package]] +name = "gsk4-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30468aff80e4faadf22f9ba164ea17511a69a9995d7a13827a13424ef47b2472" +dependencies = [ + "cairo-sys-rs", + "gdk4-sys", + "glib-sys", + "gobject-sys", + "graphene-sys", + "libc", + "pango-sys", + "system-deps 4.0.0", +] + +[[package]] +name = "gtk4" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "906f9308d15789d96a736881582181d710ae0937197119df459f3d2b46ef6776" dependencies = [ - "atk", "bitflags", "cairo-rs", "field-offset", "futures-channel", - "gdk", "gdk-pixbuf", + "gdk4", "gio", "glib", - "gtk-sys", - "gtk3-macros", + "graphene-rs", + "gsk4", + "gtk4-macros", + "gtk4-sys", "libc", "once_cell", "pango", - "pkg-config", ] [[package]] -name = "gtk-sys" -version = "0.14.0" +name = "gtk4-macros" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c14c8d3da0545785a7c5a120345b3abb534010fb8ae0f2ef3f47c027fba303e" -dependencies = [ - "atk-sys", - "cairo-sys-rs", - "gdk-pixbuf-sys", - "gdk-sys", - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "pango-sys", - "system-deps", -] - -[[package]] -name = "gtk3-macros" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21de1da96dc117443fb03c2e270b2d34b7de98d0a79a19bbb689476173745b79" +checksum = "4d0d008cdf23214c697482415dd20f666bdf3cc9f5e803b017223c17c5b59a6e" dependencies = [ "anyhow", "heck", + "itertools", "proc-macro-crate", "proc-macro-error", "proc-macro2", @@ -414,6 +437,25 @@ dependencies = [ "syn", ] +[[package]] +name = "gtk4-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d06be0a6322aa77dd372f726e97efbcbb192d9a824a414a8874f238effd7747c" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk4-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "graphene-sys", + "gsk4-sys", + "libc", + "pango-sys", + "system-deps 4.0.0", +] + [[package]] name = "heck" version = "0.3.3" @@ -547,7 +589,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps", + "system-deps 3.2.0", ] [[package]] @@ -687,7 +729,7 @@ dependencies = [ "colored", "gio", "glib", - "gtk", + "gtk4", "serialport", ] @@ -756,7 +798,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "480c269f870722b3b08d2f13053ce0c2ab722839f472863c3e2d61ff3a1c2fa6" dependencies = [ "anyhow", - "cfg-expr", + "cfg-expr 0.8.1", "heck", "itertools", "pkg-config", @@ -767,6 +809,19 @@ dependencies = [ "version-compare", ] +[[package]] +name = "system-deps" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c1889ab44c2a423ba9ba4d64cd04989b25c0280ca7ade813f05368418722a04" +dependencies = [ + "cfg-expr 0.9.0", + "heck", + "pkg-config", + "toml", + "version-compare", +] + [[package]] name = "thiserror" version = "1.0.29" diff --git a/Cargo.toml b/Cargo.toml index 2f2d32e..27567f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ colored = "2.0.0" #futures-preview = { version = "=0.3.0-alpha.16", features = ["async-await", "nightly"] } closure = "0.3.0" -gtk = "0.14.1" +gtk4 = "0.3.0" + glib = "0.14.5" gio = "0.14.6" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index fcde14d..99e570a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,9 +7,8 @@ use std::env; use serialport::{SerialPort, StopBits, Parity, FlowControl, DataBits}; // use mio_serial::{StopBits, SerialStream, Parity, SerialPortBuilder, FlowControl, DataBits, SerialPort}; -extern crate gtk; -extern crate glib; -extern crate gio; +// extern crate glib; +// extern crate gio; #[derive(Copy, Clone)] struct PortConfig { @@ -22,22 +21,6 @@ struct PortConfig { } -use gtk::{Application, ApplicationWindow, Orientation}; -use gtk::prelude::*; - -// #[derive(Copy, Clone)] -// enum MessageType { UserCommand, ReceiveMessage, ErrorMessage } -// -// #[derive(Copy, Clone)] -// enum UserCommand { Open, Close, Send, Set } -// -// #[derive(Clone)] -// struct Message { -// meeesage_type: MessageType, -// content: String, -// command: UserCommand, -// args: Vec, -// } use closure::closure; use std::time::Duration; @@ -45,10 +28,14 @@ enum Message { UiUpdateLog(String), UiUpdateReceiveMsg(String), UiCleanReceiveMsg, + UiCleanLog, + UiShowLog, + UiHideLog, MainCmdOpen(String), MainCmdClose, MainCmdSend(String), + MainCmdSet(Vec), PortCmdClose, PortCmdSend(String), @@ -58,6 +45,24 @@ enum Message { PortError(String), } +// use gtk::pango::*; +// use gtk::gdk::Display; +// use gtk::{Application, ApplicationWindow, Orientation, CssProvider, StyleContext}; +// use gtk::prelude::StyleContextExt; +// use gtk::prelude::*; +use gtk4::prelude::*; +// ::prelude::*; +// use gtk::prelude::WidgetExt; +use gtk4::{Application, ApplicationWindow, CssProvider, Entry, StyleContext, STYLE_PROVIDER_PRIORITY_APPLICATION, Orientation, ScrolledWindow, ScrollablePolicy, WrapMode}; +use gtk4::gdk::Display; + +// use gtk::gdk::{Display, Screen}; +// use gtk::{ +// Application, ApplicationWindow, Box as Box_, Button, ComboBoxText, CssProvider, Entry, +// Orientation, StyleContext, STYLE_PROVIDER_PRIORITY_APPLICATION, +// }; + + fn main() { let app = Application::builder() .application_id("org.example.HelloWorld") @@ -69,52 +74,97 @@ fn main() { .default_height(200) .title("hello world!") .build(); - let ui_layout_box = gtk::Box::new(Orientation::Vertical, 1); - ui_main_window.add(&ui_layout_box); - let ui_receive_view = gtk::TextView::new(); - let ui_command_editor = gtk::Entry::new(); - ui_layout_box.pack_start(&ui_receive_view, true, true, 5); - ui_layout_box.pack_start(&ui_command_editor, false, true, 5); + let provider = CssProvider::new(); + provider.load_from_data(include_bytes!("style.css")); + // StyleContext::add_providoer_for_screen(&provider, STYLE_PROVIDER_PRIORITY_APPLICATION); + StyleContext::add_provider_for_display( + &Display::default().expect("Error initializing gtk css provider."), + // &Screen::default().expect("Error"), + &provider, + STYLE_PROVIDER_PRIORITY_APPLICATION, + ); + + + let ui_layout_box = gtk4::Box::new(Orientation::Vertical, 1); + ui_main_window.set_child(Some(&ui_layout_box)); + + let ui_receive_view = gtk4::TextView::new(); + let ui_command_editor = gtk4::Entry::new(); + ui_command_editor.add_css_class("entry1"); + ui_receive_view.set_vexpand(true); + + let ui_main_scroller_window = ScrolledWindow::builder().build(); + ui_main_scroller_window.set_child(Some(&ui_receive_view)); + ui_receive_view.set_vscroll_policy(ScrollablePolicy::Natural); + + // ui_layout_box.append(&ui_receive_view); + ui_layout_box.append(&ui_main_scroller_window); + ui_layout_box.append(&ui_command_editor); + ui_receive_view.set_editable(false); ui_receive_view.show(); ui_command_editor.show(); ui_layout_box.show(); + let ui_log_window = ApplicationWindow::builder() - .application(app) - .default_width(200) - .default_height(320) + .default_width(350) + .default_height(450) .title("log") .build(); + ui_log_window.set_hide_on_close(true); + + let ui_log_view = gtk4::TextView::new(); + ui_log_view.set_can_focus(false); + ui_log_view.set_editable(false); + // ui_log_view.set_vscroll_policy(ScrollablePolicy::Natural); + ui_log_view.set_wrap_mode(WrapMode::Char); + ui_log_view.set_css_classes(&["textview1"]); + ui_log_window.set_child(Some(&ui_log_view)); + - let ui_log_view = gtk::TextView::new(); - ui_log_view.show(); - ui_log_window.add(&ui_log_view); ui_log_window.show(); + ui_main_window.show(); + ui_log_view.show(); let (sender_ui_upd, receiver_ui_upd) = glib::MainContext::channel(glib::PRIORITY_DEFAULT); + let tmp_command_editor = ui_command_editor.clone(); receiver_ui_upd.attach(None, move |msg| { match msg { Message::UiUpdateLog(text) => { - let buf = ui_log_view.buffer().unwrap(); + let buf = ui_log_view.buffer(); buf.insert(&mut buf.end_iter(), text.as_str()); + // ui_log_view.scroll_to_mark(&buf.get_insert(),0.0, true,0.5,0.5); } Message::UiUpdateReceiveMsg(text) => { - let buf = ui_receive_view.buffer().unwrap(); + let buf = ui_receive_view.buffer(); buf.insert(&mut buf.end_iter(), text.as_str()); + ui_receive_view.scroll_to_mark(&buf.get_insert(),0.0, true,0.5,0.5); } Message::UiCleanReceiveMsg => { - let buf = ui_receive_view.buffer().unwrap(); + let buf = ui_receive_view.buffer(); + buf.set_text("") ; + } + Message::UiCleanLog => { + let buf = ui_log_view.buffer(); buf.set_text(""); + + } + Message::UiShowLog => { + ui_log_window.show(); + } + Message::UiHideLog => { + ui_log_window.hide(); } _ => {} } + // ui_log_view.pango_context().set_font_description(&font); glib::Continue(true) }); - let sender_ui_upd_command_editor = sender_ui_upd.clone(); + let to_ui = sender_ui_upd.clone(); let (gui2main_tx, gui2main_rx) = channel::(); @@ -124,23 +174,28 @@ fn main() { let command_buf = x.buffer(); let command = command_buf.text(); command_buf.set_text(""); - process_cmd(command, sender_ui_upd_command_editor.clone(), gui2main_tx.clone()); + process_cmd(command, to_ui.clone(), gui2main_tx.clone()); }); - - ui_main_window.show(); }); app.run(); } -fn process_cmd(command: String, sender_ui_upd_command_editor: glib::Sender, gui2main_tx: Sender) { +fn process_cmd(command: String, to_ui: glib::Sender, gui2main_tx: Sender) { let command_split: Vec<&str> = command.split_whitespace().collect(); if command_split.len() != 0 { let cmd = command_split[0].to_ascii_lowercase(); match cmd.as_str() { - "set" => {} + "set" => { + if command_split.len() == 1 { + to_ui.send(Message::UiUpdateLog("No enough argument\n".to_string())).unwrap(); + } else { + let args: Vec = command_split[1..].to_vec().into_iter().map(|item| String::from(item)).collect(); + gui2main_tx.send(Message::MainCmdSet(args)).unwrap(); + } + } "open" => { if command_split.len() == 1 { - sender_ui_upd_command_editor.send(Message::UiUpdateLog("No enough argument\n".to_string())).unwrap(); + to_ui.send(Message::UiUpdateLog("No enough argument\n".to_string())).unwrap(); } else { let args: Vec = command_split[1..].to_vec().into_iter().map(|item| String::from(item)).collect(); gui2main_tx.send(Message::MainCmdOpen(args[0].clone())).unwrap(); @@ -150,13 +205,35 @@ fn process_cmd(command: String, sender_ui_upd_command_editor: glib::Sender { - sender_ui_upd_command_editor.send(Message::UiUpdateLog(list_available_ports())).unwrap(); + to_ui.send(Message::UiUpdateLog(list_available_ports())).unwrap(); } "send" => { gui2main_tx.send(Message::MainCmdSend(command[5..].parse().unwrap())).unwrap(); } "clean" => { - sender_ui_upd_command_editor.send(Message::UiCleanReceiveMsg).unwrap(); + to_ui.send(Message::UiCleanReceiveMsg).unwrap(); + to_ui.send(Message::UiCleanLog).unwrap(); + + } + "show" => { + if command_split.len() == 1 { + to_ui.send(Message::UiUpdateLog("No enough argument\n".to_string())).unwrap(); + } else { + match command_split[1] { + "log" => { to_ui.send(Message::UiShowLog).unwrap(); } + _ => {} + } + } + } + "hide" => { + if command_split.len() == 1 { + to_ui.send(Message::UiUpdateLog("No enough argument\n".to_string())).unwrap(); + } else { + match command_split[1] { + "log" => { to_ui.send(Message::UiHideLog).unwrap(); } + _ => {} + } + } } _ => {} } @@ -165,7 +242,7 @@ fn process_cmd(command: String, sender_ui_upd_command_editor: glib::Sender, rx: Receiver, ui_upd: glib::Sender) { let (mut main2port_tx, _rx_port_receive) = channel::(); - let port_default_config = PortConfig { + let mut port_default_config = PortConfig { baud_rate: 115_200, data_bits: DataBits::Eight, parity: Parity::None, @@ -200,6 +277,82 @@ fn main_proc(to_main_tx: Sender, rx: Receiver, ui_upd: glib::S Message::MainCmdSend(msg) => { main2port_tx.send(Message::PortCmdSend(msg)).unwrap(); } + Message::MainCmdSet(args) => { + match args[0].as_str() { + "baudrate" => { + if args.len() != 2 { + ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap(); + } else { + if let Ok(value) = args[1].parse::() { + port_default_config.baud_rate = value; + } else { + ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap(); + } + } + } + "databit" => { + if args.len() != 2 { + ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap(); + } else { + if let Ok(value) = args[1].parse::() { + match value { + 8 => port_default_config.data_bits = DataBits::Eight, + 7 => port_default_config.data_bits = DataBits::Seven, + 6 => port_default_config.data_bits = DataBits::Six, + 5 => port_default_config.data_bits = DataBits::Five, + _ => { ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap(); } + } + } else { + ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap(); + } + } + } + "parity" => { + if args.len() != 2 { + ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap(); + } else { + if let Ok(value) = args[1].parse::() { + match value { + 0 => port_default_config.parity = Parity::None, + 1 => port_default_config.parity = Parity::Odd, + 2 => port_default_config.parity = Parity::Even, + _ => { ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap(); } + } + } else { + ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap(); + } + } + } + "stopbit" => { + if args.len() != 2 { + ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap(); + } else { + if let Ok(value) = args[1].parse::() { + match value { + 0 => port_default_config.stopbit = StopBits::One, + 1 => port_default_config.stopbit = StopBits::Two, + _ => { ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap(); } + } + } else { + ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap(); + } + } + } + "flowcontrol" => { + if args.len() != 2 { + ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap(); + } else { + match args[1].as_str() { + "hard" => port_default_config.flow_control = FlowControl::Hardware, + "soft" => port_default_config.flow_control = FlowControl::Software, + "none" => port_default_config.flow_control = FlowControl::None, + _ => { ui_upd.send(Message::UiUpdateLog("Invalid command!\n".to_string())).unwrap(); } + } + } + } + _ => { ui_upd.send(Message::UiUpdateLog("command does not support!\n".to_string())).unwrap(); } + } + } Message::PortHaveData(data) => unsafe { ui_upd.send(Message::UiUpdateReceiveMsg(String::from_utf8_unchecked(data))).unwrap(); } diff --git a/src/style.css b/src/style.css new file mode 100644 index 0000000..ed520db --- /dev/null +++ b/src/style.css @@ -0,0 +1,9 @@ +entry.entry1 { + /*background: linear-gradient(to right, #f00, #0f0);*/ + /*color: blue;*/ + font-weight: bold; + font-size: 17pt; +} +textview.textview1 { + font-size: 20px; +}