downgrade to gtk3

This commit is contained in:
Guangzong Chen 2021-10-03 23:01:11 -04:00
parent dbcd7c11b2
commit 0e323bcafb
No known key found for this signature in database
GPG Key ID: E3E141D720E7F9A3
5 changed files with 555 additions and 434 deletions

273
Cargo.lock generated
View File

@ -39,14 +39,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1"
[[package]]
name = "atty"
version = "0.2.14"
name = "atk"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
checksum = "a83b21d2aa75e464db56225e1bda2dd5993311ba1095acaa8fa03d1ae67026ba"
dependencies = [
"hermit-abi",
"atk-sys",
"bitflags",
"glib",
"libc",
"winapi",
]
[[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]]
@ -57,9 +70,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bitflags"
version = "1.2.1"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cairo-rs"
@ -82,7 +95,7 @@ checksum = "d7c9c3928781e8a017ece15eace05230f04b647457d170d2d9641c94a444ff80"
dependencies = [
"glib-sys",
"libc",
"system-deps 3.2.0",
"system-deps",
]
[[package]]
@ -100,15 +113,6 @@ 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"
@ -121,17 +125,6 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6173fd61b610d15a7566dd7b7620775627441c4ab9dac8906e17cb93a24b782"
[[package]]
name = "colored"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd"
dependencies = [
"atty",
"lazy_static",
"winapi",
]
[[package]]
name = "either"
version = "1.6.1"
@ -200,6 +193,22 @@ 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"
@ -222,40 +231,24 @@ dependencies = [
"glib-sys",
"gobject-sys",
"libc",
"system-deps 3.2.0",
"system-deps",
]
[[package]]
name = "gdk4"
version = "0.3.0"
name = "gdk-sys"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
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"
checksum = "0e091b3d3d6696949ac3b3fb3c62090e5bfd7bd6850bef5c3c5ea701de1b1f1e"
dependencies = [
"cairo-sys-rs",
"gdk-pixbuf-sys",
"gio-sys",
"glib-sys",
"gobject-sys",
"graphene-sys",
"libc",
"pango-sys",
"system-deps 4.0.0",
"pkg-config",
"system-deps",
]
[[package]]
@ -284,7 +277,7 @@ dependencies = [
"glib-sys",
"gobject-sys",
"libc",
"system-deps 3.2.0",
"system-deps",
"winapi",
]
@ -329,7 +322,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c1d60554a212445e2a858e42a0e48cece1bd57b311a19a9468f70376cf554ae"
dependencies = [
"libc",
"system-deps 3.2.0",
"system-deps",
]
[[package]]
@ -340,96 +333,58 @@ checksum = "aa92cae29759dae34ab5921d73fff5ad54b3d794ab842c117e36cafc7994c3f5"
dependencies = [
"glib-sys",
"libc",
"system-deps 3.2.0",
"system-deps",
]
[[package]]
name = "graphene-rs"
version = "0.14.0"
name = "gtk"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
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"
checksum = "6603bb79ded6ac6f3bac203794383afa8b1d6a8656d34a93a88f0b22826cd46c"
dependencies = [
"atk",
"bitflags",
"cairo-rs",
"field-offset",
"futures-channel",
"gdk",
"gdk-pixbuf",
"gdk4",
"gio",
"glib",
"graphene-rs",
"gsk4",
"gtk4-macros",
"gtk4-sys",
"gtk-sys",
"gtk3-macros",
"libc",
"once_cell",
"pango",
"pkg-config",
]
[[package]]
name = "gtk4-macros"
version = "0.3.0"
name = "gtk-sys"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d0d008cdf23214c697482415dd20f666bdf3cc9f5e803b017223c17c5b59a6e"
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"
dependencies = [
"anyhow",
"heck",
"itertools",
"proc-macro-crate",
"proc-macro-error",
"proc-macro2",
@ -438,22 +393,14 @@ dependencies = [
]
[[package]]
name = "gtk4-sys"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d06be0a6322aa77dd372f726e97efbcbb192d9a824a414a8874f238effd7747c"
name = "gtk_ui"
version = "0.1.0"
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",
"closure",
"gio",
"glib",
"gtk",
"serialport",
]
[[package]]
@ -465,15 +412,6 @@ dependencies = [
"unicode-segmentation",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "itertools"
version = "0.10.1"
@ -483,17 +421,11 @@ dependencies = [
"either",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.102"
version = "0.2.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103"
checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
[[package]]
name = "libudev"
@ -589,7 +521,7 @@ dependencies = [
"glib-sys",
"gobject-sys",
"libc",
"system-deps 3.2.0",
"system-deps",
]
[[package]]
@ -615,9 +547,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.19"
version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
checksum = "7c9b1041b4387893b91ee6746cddfc28516aff326a3519fb2adf820932c5e6cb"
[[package]]
name = "proc-macro-crate"
@ -721,18 +653,6 @@ version = "1.0.130"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
[[package]]
name = "serial_communication_tool_v2"
version = "0.1.0"
dependencies = [
"closure",
"colored",
"gio",
"glib",
"gtk4",
"serialport",
]
[[package]]
name = "serialport"
version = "4.0.1"
@ -758,9 +678,9 @@ checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590"
[[package]]
name = "smallvec"
version = "1.6.1"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
[[package]]
name = "strum"
@ -798,7 +718,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "480c269f870722b3b08d2f13053ce0c2ab722839f472863c3e2d61ff3a1c2fa6"
dependencies = [
"anyhow",
"cfg-expr 0.8.1",
"cfg-expr",
"heck",
"itertools",
"pkg-config",
@ -809,19 +729,6 @@ 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"

View File

@ -6,15 +6,13 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
#fltk = "1.2.3"
#fltk-theme = "0.1.8"
serialport = "4.0.1"
colored = "2.0.0"
#mio-serial = "5.0.1"
#futures-preview = { version = "=0.3.0-alpha.16", features = ["async-await", "nightly"] }
closure = "0.3.0"
gtk4 = "0.3.0"
glib = "0.14.5"
gtk = "0.14.1"
gio = "0.14.6"
glib = "0.14.5"
#gtk4 = {git = "https://github.com/gtk-rs/gtk4-rs/"}
#gtk4 = "0.3.0"
#gio4_sys ="0."
#gtk4_sys = "0.3.0"
#gtk4-sys = "0.3.0"
serialport = "4.0.1"
closure = "0.3.0"

View File

@ -1,180 +1,119 @@
#![feature(receiver_trait)]
use std::io::{Write, Read};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::env;
use serialport::{SerialPort, StopBits, Parity, FlowControl, DataBits};
#[derive(Copy, Clone)]
struct PortConfig {
baud_rate: u32,
data_bits: DataBits,
parity: Parity,
flow_control: FlowControl,
stopbit: StopBits,
timeout: u32,
}
mod port;
use closure::closure;
use std::time::Duration;
enum Message {
UiUpdateLog(String),
UiUpdateReceiveMsg(String),
UiCleanReceiveMsg,
UiCleanLog,
UiShowReceive,
UiHideReceive,
MainCmdOpen(String),
MainCmdClose,
MainCmdSend(String),
MainCmdSet(Vec<String>),
PortCmdClose,
PortCmdSend(String),
PortCloseSucceed,
PortHaveData(Vec<u8>),
PortError(String),
}
enum Error {
PortOpenFailed(String),
}
use gtk4::prelude::*;
use gtk4::{Application, ApplicationWindow, CssProvider, StyleContext, STYLE_PROVIDER_PRIORITY_APPLICATION, Orientation, ScrolledWindow, ScrollablePolicy, WrapMode};
use gtk4::gdk::Display;
use gtk::{AboutDialog, Inhibit, TextView};
use gtk::{gio, glib};
use gtk::prelude::{GtkApplicationExt, GtkWindowExt, BuilderExtManual, GtkMenuItemExt, WidgetExt, WidgetExtManual, EntryExt, TextBufferExt};
use gio::prelude::{ApplicationExt, ApplicationExtManual};
use std::sync::mpsc::{Sender, Receiver, channel};
use serialport::{StopBits, FlowControl, Parity, DataBits};
use crate::port::*;
use gtk::prelude::TextViewExt;
fn main() {
let app = Application::builder()
.application_id("org.example.HelloWorld")
.build();
app.connect_activate(|app| {
let provider = CssProvider::new();
provider.load_from_data(include_bytes!("style.css"));
StyleContext::add_provider_for_display(
&Display::default().expect("Error initializing gtk css provider."),
&provider,
STYLE_PROVIDER_PRIORITY_APPLICATION,
let application = gtk::Application::new(
Some("com.github.gtk-rs.examples.menu_bar_system"),
Default::default(),
);
// application.connect_startup(|app| {
// });
application.connect_activate(build_ui);
let ui_main_window = ApplicationWindow::builder()
.application(app)
.default_width(320)
.default_height(200)
.title("hello world!")
.build();
let ui_layout_main_box = gtk4::Box::new(Orientation::Vertical, 1);
let ui_main_scroller_window = ScrolledWindow::builder().build();
let ui_command_editor = gtk4::Entry::new();
let ui_log_view = gtk4::TextView::new();
ui_log_view.set_editable(false);
ui_log_view.set_wrap_mode(WrapMode::Char);
ui_log_view.set_css_classes(&["textview1"]);
ui_log_view.set_vexpand(true);
ui_main_scroller_window.set_child(Some(&ui_log_view));
ui_main_window.set_child(Some(&ui_layout_main_box));
ui_layout_main_box.append(&ui_main_scroller_window);
ui_layout_main_box.append(&ui_command_editor);
ui_command_editor.add_css_class("entry1");
ui_command_editor.show();
ui_layout_main_box.show();
ui_log_view.show();
let ui_receive_windows = ApplicationWindow::builder()
.default_width(350)
.default_height(450)
.title("log")
.build();
ui_receive_windows.set_hide_on_close(true);
let ui_receive_box = gtk4::Box::new(Orientation::Vertical, 1);
let menu_bar = gtk4::PopoverMenuBar::builder().build();
let ui_receive_scroll_window = ScrolledWindow::builder().build();
let ui_receive_view = gtk4::TextView::new();
let menu_item_first = gtk4::MenuButton::new();
menu_item_first.set_label("hello");
menu_bar.add_child(&menu_item_first,"first");
menu_bar.show();
ui_receive_box.append(&menu_bar);
ui_receive_box.append(&ui_receive_scroll_window);
ui_receive_scroll_window.set_child(Some(&ui_receive_view));
ui_receive_view.set_vexpand(true);
ui_receive_view.set_vscroll_policy(ScrollablePolicy::Natural);
ui_receive_view.set_editable(false);
ui_receive_view.show();
// ui_receive_windows.set_child(Some(&ui_receive_scroll_window));
ui_receive_windows.set_child(Some(&ui_receive_box));
ui_receive_windows.show();
ui_main_window.show();
// add short cut to open command panel.
// ui_receive_windows.
let trigger = gtk4::ShortcutTrigger::parse_string("<Control>P").unwrap();
let shortcut = gtk4::Shortcut::builder().trigger(&trigger).build();
application.run();
}
fn build_ui(application: &gtk::Application) {
let builder = gtk::Builder::from_string(include_str!("test.ui"));
let main_window: gtk::ApplicationWindow = builder.object("main_window").expect("Can not get window!");
main_window.set_application(Some(application));
let menu_view_command: gtk::MenuItem = builder.object("view_command").expect("Can not get command item");
let command_entry: gtk::Entry = builder.object("command_entry").expect("Can not get command entry");
let tmp = command_entry.clone();
menu_view_command.connect_activate(move |_| {
if WidgetExt::is_visible(&tmp) {
tmp.hide();
} else {
tmp.show();
tmp.set_has_focus(true);
}
});
let log_window: gtk::Window = builder.object("log_window").expect("Can not get log view");
let menu_log_command:gtk::MenuItem = builder.object("log_command").expect("Can not get log command");
let ui_receive_view:TextView = builder.object("receive_view").expect("can not get receive view");
log_window.show();
let ui_log_view:TextView = builder.object("log_view").unwrap();
log_window.connect_delete_event(|a,_|{
a.hide();
Inhibit(true)
});
let tmp = main_window.clone();
menu_log_command.connect_activate(move |_| {
if log_window.is_visible() {
log_window.hide();
}
else {
log_window.show();
// tmp.show();
// tmp.set_has_focus(true);
tmp.present();
tmp.grab_focus();
}
});
let (sender_ui_upd, receiver_ui_upd) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
receiver_ui_upd.attach(None, move |msg|{
// 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();
let buf = ui_log_view.buffer().unwrap();
// buf.insert()
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();
let buf = ui_receive_view.buffer().unwrap();
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);
ui_receive_view.scroll_to_mark(&buf.get_insert().unwrap(), 0.0, true, 0.5, 0.5);
}
Message::UiCleanReceiveMsg => {
let buf = ui_receive_view.buffer();
let buf = ui_receive_view.buffer().unwrap();
// buf.set_text(Option::from(""));
buf.set_text("");
}
Message::UiCleanLog => {
let buf = ui_log_view.buffer();
let buf = ui_log_view.buffer().unwrap();
buf.set_text("");
// buf.set_text(Option::from(""));
}
Message::UiShowReceive => {
ui_receive_windows.show();
// ui_receive_windows.show();
}
Message::UiHideReceive => {
ui_receive_windows.hide();
// ui_receive_windows.hide();
}
_ => {}
}
// ui_log_view.pango_context().set_font_description(&font);
glib::Continue(true)
});
let to_ui = sender_ui_upd.clone();
let (gui2main_tx, gui2main_rx) = channel::<Message>();
std::thread::spawn(closure!(clone gui2main_tx, clone sender_ui_upd, || {main_proc(gui2main_tx, gui2main_rx, sender_ui_upd)}));
ui_command_editor.connect_activate(move |x| {
let to_ui = sender_ui_upd.clone();
command_entry.connect_activate(move |x| {
let command_buf = x.buffer();
let command = command_buf.text();
command_buf.set_text("");
process_cmd(command, to_ui.clone(), gui2main_tx.clone());
});
});
app.run();
main_window.show();
}
fn process_cmd(command: String, to_ui: glib::Sender<Message>, gui2main_tx: Sender<Message>) {
let command_split: Vec<&str> = command.split_whitespace().collect();
if command_split.len() != 0 {
@ -370,73 +309,3 @@ fn main_proc(to_main_tx: Sender<Message>, rx: Receiver<Message>, ui_upd: glib::S
}
}
}
fn port_open(port: String, config: PortConfig) -> Result<Box<dyn SerialPort>, Error> {
let mut prelude = "";
if env::consts::OS == "linux" {
prelude = "/dev/tty";
} else if env::consts::OS == "windows" {
prelude = ""
}
let port_builder = serialport::new(prelude.to_owned() + &port, config.baud_rate)
.data_bits(config.data_bits)
.parity(config.parity)
.flow_control(config.flow_control)
.stop_bits(config.stopbit)
.timeout(Duration::from_millis(config.timeout as u64));
match port_builder.open() {
Ok(port) => { return Ok(port); }
Err(e) => {
let err_msg = format!("Open port failed with error {}\n", e).to_string();
return Err(Error::PortOpenFailed(err_msg));
}
}
}
fn port_proc(mut port: Box<dyn SerialPort>, to_main: Sender<Message>, from_main: Receiver<Message>) {
let mut buf: Vec<u8> = vec![0; 128];
loop {
if let Ok(msg) = from_main.try_recv() {
match msg {
Message::PortCmdClose => {
to_main.send(Message::PortCloseSucceed).unwrap();
break;
}
Message::PortCmdSend(msg) => {
match port.write(msg.as_bytes()) {
Err(e) => {
to_main.send(Message::PortError(format!("{}", e).to_string())).unwrap();
}
_ => {}
}
}
_ => {}
}
}
match port.read(buf.as_mut_slice()) {
Ok(size) => to_main.send(Message::PortHaveData(buf[0..size].to_owned())).unwrap(),
Err(e) => {
if e.kind() != std::io::ErrorKind::TimedOut {
to_main.send(Message::PortError(format!("{}", e).to_string())).unwrap();
break;
}
}
}
}
}
fn list_available_ports() -> String {
let mut ret = String::new();
match serialport::available_ports() {
Ok(ports) => {
for p in ports {
ret += &*String::from(format!("{:?}\n", p));
}
}
Err(err) => {
ret = format!("{}", err);
}
}
ret
}

105
src/port.rs Normal file
View File

@ -0,0 +1,105 @@
use std::sync::mpsc::{Sender, Receiver};
use std::env;
use serialport::{SerialPort, DataBits, Parity, FlowControl, StopBits};
use std::time::Duration;
pub enum Message {
UiUpdateLog(String),
UiUpdateReceiveMsg(String),
UiCleanReceiveMsg,
UiCleanLog,
UiShowReceive,
UiHideReceive,
MainCmdOpen(String),
MainCmdClose,
MainCmdSend(String),
MainCmdSet(Vec<String>),
PortCmdClose,
PortCmdSend(String),
PortCloseSucceed,
PortHaveData(Vec<u8>),
PortError(String),
}
pub enum Error {
PortOpenFailed(String),
}
#[derive(Copy, Clone)]
pub struct PortConfig {
pub baud_rate: u32,
pub data_bits: DataBits,
pub parity: Parity,
pub flow_control: FlowControl,
pub stopbit: StopBits,
pub timeout: u32,
}
pub fn port_open(port: String, config: PortConfig) -> Result<Box<dyn SerialPort>, Error> {
let mut prelude = ""; if env::consts::OS == "linux" { prelude = "/dev/tty"; }
else if env::consts::OS == "windows" { prelude = "" }
let port_builder = serialport::new(prelude.to_owned() + &port, config.baud_rate)
.data_bits(config.data_bits)
.parity(config.parity)
.flow_control(config.flow_control)
.stop_bits(config.stopbit)
.timeout(Duration::from_millis(config.timeout as u64));
match port_builder.open() {
Ok(port) => { return Ok(port); }
Err(e) => {
let err_msg = format!("Open port failed with error {}\n", e).to_string();
return Err(Error::PortOpenFailed(err_msg));
}
}
}
pub fn port_proc(mut port: Box<dyn SerialPort>, to_main: Sender<Message>, from_main: Receiver<Message>) {
let mut buf: Vec<u8> = vec![0; 128];
loop {
if let Ok(msg) = from_main.try_recv() {
match msg {
Message::PortCmdClose => {
to_main.send(Message::PortCloseSucceed).unwrap();
break;
}
Message::PortCmdSend(msg) => {
match port.write(msg.as_bytes()) {
Err(e) => {
to_main.send(Message::PortError(format!("{}", e).to_string())).unwrap();
}
_ => {}
}
}
_ => {}
}
}
match port.read(buf.as_mut_slice()) {
Ok(size) => to_main.send(Message::PortHaveData(buf[0..size].to_owned())).unwrap(),
Err(e) => {
if e.kind() != std::io::ErrorKind::TimedOut {
to_main.send(Message::PortError(format!("{}", e).to_string())).unwrap();
break;
}
}
}
}
}
pub(crate) fn list_available_ports() -> String {
let mut ret = String::new();
match serialport::available_ports() {
Ok(ports) => {
for p in ports {
ret += &*String::from(format!("{:?}\n", p));
}
}
Err(err) => {
ret = format!("{}", err);
}
}
ret
}

242
src/test.ui Normal file
View File

@ -0,0 +1,242 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkWindow" id="log_window">
<property name="can-focus">False</property>
<child>
<object class="GtkTextView" id="log_view">
<property name="visible">True</property>
<property name="can-focus">True</property>
</object>
</child>
</object>
<object class="GtkApplicationWindow" id="main_window">
<property name="can-focus">False</property>
<property name="default-width">300</property>
<property name="default-height">400</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkMenuBar" id="menu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_File</property>
<property name="use-underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-new</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-open</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-save</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-save-as</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-quit</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_Edit</property>
<property name="use-underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-cut</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-copy</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-paste</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-delete</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_View</property>
<property name="use-underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkMenuItem" id="log_command">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">log</property>
<accelerator key="l" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
<object class="GtkMenuItem" id="view_command">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">command</property>
<accelerator key="p" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">hex</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">_Help</property>
<property name="use-underline">True</property>
<child type="submenu">
<object class="GtkMenu">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkImageMenuItem">
<property name="label">gtk-about</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="use-underline">True</property>
<property name="use-stock">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="command_entry">
<property name="visible">True</property>
<property name="can-focus">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="vexpand">True</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkTextView" id="receive_view">
<property name="visible">True</property>
<property name="can-focus">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
</interface>