diff --git a/Cargo.lock b/Cargo.lock
index 4b20a72..026fdcd 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -433,6 +433,12 @@ dependencies = [
"thiserror",
]
+[[package]]
+name = "glib-build-tools"
+version = "0.17.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a65d79efe318ef2cbbbb37032b125866fd82c34ea44c816132621bbc552e716"
+
[[package]]
name = "glib-macros"
version = "0.17.10"
@@ -971,6 +977,7 @@ name = "rsproject"
version = "0.1.0"
dependencies = [
"chrono",
+ "glib-build-tools",
"gtk4",
"libadwaita",
"relm4",
diff --git a/Cargo.toml b/Cargo.toml
index eb589c2..486c0bf 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,3 +12,6 @@ relm4 = { version = "0.6.2", features = ["libadwaita"]}
relm4-icons = { version = "0.6.0", features = ["add-filled"] }
chrono = "0.4.34"
tracker = "0.2.1"
+
+[build-dependencies]
+glib-build-tools = "0.17.0"
\ No newline at end of file
diff --git a/build.rs b/build.rs
new file mode 100644
index 0000000..ac6db38
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,8 @@
+fn main() {
+ glib_build_tools::compile_resources(
+ &["data"],
+ // "src/resources/resources.gresource.xml",
+ "data/css.gresource.xml",
+ "css.gresource",
+ );
+}
diff --git a/data/css.gresource.xml b/data/css.gresource.xml
new file mode 100644
index 0000000..fcf0d5d
--- /dev/null
+++ b/data/css.gresource.xml
@@ -0,0 +1,6 @@
+
+
+
+ css/main.css
+
+
diff --git a/data/css/main.css b/data/css/main.css
new file mode 100644
index 0000000..ba92bd8
--- /dev/null
+++ b/data/css/main.css
@@ -0,0 +1,34 @@
+.rb {
+ border-radius: 10px;
+}
+
+paned>separator {
+ color: transparent;
+}
+
+.h1 {
+ font-size: 25px;
+ font-weight: bold;
+ line-height: 1.25;
+}
+
+.h2 {
+ font-size: 20px;
+ font-weight: bold;
+ line-height: 1.25;
+}
+
+.h3 {
+ font-size: 15px;
+ font-weight: bold;
+ line-height: 1.25;
+ color: #666;
+}
+
+.content {
+ font-size: 14px;
+}
+
+.lv {
+ background: transparent;
+}
\ No newline at end of file
diff --git a/src/components/app.rs b/src/components/app.rs
index b91bd49..ef44994 100644
--- a/src/components/app.rs
+++ b/src/components/app.rs
@@ -12,6 +12,7 @@ use std::{
rc::Rc,
sync::{Arc, Mutex},
};
+use gtk::Widget;
relm4::new_action_group!(FileActionGroup, "file");
relm4::new_stateless_action!(OpenAction, FileActionGroup, "open");
@@ -45,27 +46,33 @@ impl Component for AppModel {
set_default_height: 900,
set_focus_on_click:true,
connect_close_request[sender] => move |_| {
+ let app = relm4::main_application();
+ app.quit();
gtk::Inhibit(true)
},
gtk::Box{
set_orientation: gtk::Orientation::Vertical,
set_valign:gtk::Align::Fill,
set_spacing:2,
- gtk::HeaderBar{},
+ // gtk::HeaderBar{},
gtk::Box{
set_hexpand: true,
set_vexpand: true,
#[name="stack"]
- gtk::Stack{
- set_transition_type:gtk::StackTransitionType::SlideUp,
- set_transition_duration:300,
+ adw::NavigationView{
set_hexpand:true,
set_vexpand:true,
},
+
}
}
},
- home_page = adw::Clamp{
+ home_page = adw::NavigationPage{
+ #[wrap(Some)]
+ set_child=&adw::ToolbarView{
+ add_top_bar=&adw::HeaderBar{},
+ #[wrap(Some)]
+ set_content=&adw::Clamp{
set_maximum_size: 1000,
gtk::Box{
set_orientation: gtk::Orientation::Vertical,
@@ -84,9 +91,21 @@ impl Component for AppModel {
},
},
}
+ }
+ }
+ },
+ new_page = adw::NavigationPage{
+ set_title: "New Project",
+ set_tag: Some("new_page"),
+ #[wrap(Some)]
+ set_child=&adw::ToolbarView{
+ add_top_bar=&adw::HeaderBar{},
+ #[wrap(Some)]
+ set_content=model.new_page_model.widget() -> &adw::NavigationSplitView {}
+ }
},
- home_stack_page = stack.add_titled(&home_page, Some("home"), "Home") -> gtk::StackPage{},
- new_project_page = stack.add_titled(model.new_page_model.widget(),Some("new_page"), "New") -> gtk::StackPage{},
+ stack.add(&home_page),
+ stack.add(&new_page),
}
menu! {
@@ -137,7 +156,8 @@ impl Component for AppModel {
) {
match msg {
AppMsg::NewProject => {
- widgets.stack.set_visible_child_name("new_page");
+ // widgets.stack.set_visible_child_name("new_page");
+ widgets.stack.push_by_tag("new_page");
}
}
}
diff --git a/src/components/new_project.rs b/src/components/new_project.rs
index 0d9fa94..0a8cc64 100644
--- a/src/components/new_project.rs
+++ b/src/components/new_project.rs
@@ -1,25 +1,33 @@
+use crate::components::setting_item::{SettingItem, SettingType};
+use crate::config::CommonConfig;
use adw::prelude::*;
use gtk::glib::clone;
use gtk::prelude::{BoxExt, ButtonExt, GtkWindowExt, OrientableExt, ToggleButtonExt};
-use relm4::{prelude::*, view};
-use std::path::PathBuf;
-use std::rc::Rc;
use gtk::ResponseType::No;
use gtk::Widget;
use relm4::factory::FactoryVecDeque;
-use crate::components::setting_item::{SettingItem, SettingType};
-use crate::config::CommonConfig;
+use relm4::{prelude::*, view};
+use std::cell::RefCell;
+use std::path::PathBuf;
+use std::rc::Rc;
+#[tracker::track]
#[derive(Debug)]
pub struct NewPageModel {
- common_setting: CommonConfig
+ project_name: String,
+ common_setting: CommonConfig,
+}
+
+#[derive(Debug)]
+pub enum NewPageMsg{
+ ChangeName(String)
}
#[relm4::component(pub)]
impl SimpleComponent for NewPageModel {
type Init = ();
type Output = ();
- type Input = ();
+ type Input = NewPageMsg;
view! {
#[root]
@@ -46,11 +54,28 @@ impl SimpleComponent for NewPageModel {
common_setting = gtk::Box{
set_orientation: gtk::Orientation::Vertical,
+ set_valign: gtk::Align::Center,
+
adw::PreferencesPage{
set_title: "Common",
add=&adw::PreferencesGroup{
+ add=>k::Label {
+ set_halign: gtk::Align::Start,
+ #[track = "model.changed(NewPageModel::project_name())"]
+ set_text: &model.project_name,
+ add_css_class: "h1"
+ }
+ },
+ add=&adw::PreferencesGroup{
+ set_title: "Common",
+ add=&adw::EntryRow{
+ set_title: "Project Name",
+ connect_text_notify[sender] => move |s| {
+ sender.input(NewPageMsg::ChangeName(s.text().to_string()));
+ }
+ },
#[iterate]
- add: model.common_setting.to_settings().iter_mut().map(|v| v.to_widget()).collect::>().iter()
+ add: model.common_setting.to_settings().iter_mut().map(|v| v.widget()).collect::>().iter()
}
}
},
@@ -64,10 +89,21 @@ impl SimpleComponent for NewPageModel {
sender: relm4::ComponentSender,
) -> relm4::ComponentParts {
let config = CommonConfig::default();
- let model = NewPageModel { common_setting: config };
+ let mut model = NewPageModel {
+ project_name: format!("Project {}", 0),
+ common_setting: config,
+ tracker: 0,
+ };
let widgets = view_output!();
ComponentParts { model, widgets }
}
- fn update(&mut self, msg: Self::Input, _sender: ComponentSender) {}
+ fn update(&mut self, msg: Self::Input, _sender: ComponentSender) {
+ self.reset();
+ match msg {
+ NewPageMsg::ChangeName(name) => {
+ self.set_project_name(name);
+ }
+ }
+ }
}
diff --git a/src/components/setting_item/mod.rs b/src/components/setting_item/mod.rs
index 96e71c7..0665cdf 100644
--- a/src/components/setting_item/mod.rs
+++ b/src/components/setting_item/mod.rs
@@ -1,7 +1,8 @@
+use std::cell::{Cell, RefCell};
use adw::prelude::*;
use gtk::prelude::*;
use gtk::{StringList, Widget};
-use relm4::{factory::FactoryView, gtk, prelude::*, FactorySender};
+use relm4::{factory::FactoryView, gtk, prelude::*, FactorySender, RelmObjectExt};
use std::rc::Rc;
#[derive(Debug)]
@@ -11,11 +12,11 @@ pub enum Msg {}
pub enum OutputMsg {}
pub enum SettingType {
- Select(Vec),
+ Select(Vec, Option>>),
Action,
- Entry(Option, Option bool>>),
- Switch(bool),
- Spin(f64, f64, f64, f64),
+ Entry(Option, Option bool>>, Option>>),
+ Switch(bool, Option>>),
+ Spin(f64, f64, f64, f64, Option>>),
}
pub struct SettingItem {
@@ -27,10 +28,17 @@ impl SettingItem {
pub fn new(title: String, _type: SettingType) -> Self {
Self { title, _type }
}
- pub fn to_widget(&mut self) -> Widget {
+ pub fn widget(&mut self) -> Widget {
(match &mut self._type {
- SettingType::Select(selects) => {
+ SettingType::Select(selects, selected) => {
let w = adw::ComboRow::builder().title(&self.title).build();
+ if let Some(selected) = selected {
+ let selected = selected.clone();
+ w.connect_selected_item_notify(|s| {
+ // println!("{}", text);
+ // selected.set(text.to_string());
+ });
+ }
let model = StringList::new(
selects
.iter()
@@ -45,37 +53,54 @@ impl SettingItem {
.title(&self.title)
.build()
.upcast::(),
- SettingType::Entry(text, f) => {
+ SettingType::Entry(text, f, buffer) => {
let w = adw::EntryRow::new();
w.set_title(&self.title);
- let f = f.take();
- if let Some(f) = f {
- println!("test");
- w.connect_text_notify(move |s| {
- let text = s.text();
- if !f(&text) {
- s.set_text("");
- }
- });
- }
if let Some(text) = text {
w.set_text(text);
}
+
+ let f = f.take();
+ let buffer = buffer.clone();
+ if let Some(buffer) = buffer {
+ w.connect_text_notify(move |s| {
+ let text = s.text();
+ if let Some(f) = f.as_ref(){
+ if !f(&text) {
+ s.set_text("");
+ return;
+ }
+ }
+ *buffer.borrow_mut() = text.to_string();
+ });
+ }
w.upcast::()
}
- SettingType::Switch(t) => {
+ SettingType::Switch(t, v) => {
let w = adw::SwitchRow::new();
w.set_title(&self.title);
w.set_active(*t);
+ if let Some(v) = v {
+ let v = v.clone();
+ w.connect_active_notify(move |s| {
+ v.set(s.is_active());
+ });
+ }
w.upcast::()
}
- SettingType::Spin(min, max, clamb, value) => {
+ SettingType::Spin(min, max, clamb, value, v) => {
let w = adw::SpinRow::new(
Some(>k::Adjustment::new(*value, *min, *max, *clamb, 0.0, 0.0)),
*clamb,
0,
);
w.set_numeric(true);
+ if let Some(v) = v {
+ let v = v.clone();
+ w.connect_value_notify(move |s| {
+ v.set(s.value());
+ });
+ }
// w.set_range(*min, *max);
w.set_value(*value);
w.set_title(&self.title);
diff --git a/src/config.rs b/src/config.rs
index 2590d5e..43a33ab 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -1,15 +1,18 @@
+use std::cell::{Cell, Ref, RefCell};
use std::collections::HashMap;
+use std::rc::Rc;
use crate::components::{SettingItem, SettingType};
-#[derive(Clone, Debug, Default)]
+#[derive(Clone, Debug, Default, PartialOrd, PartialEq)]
pub struct CommonConfig{
- pub name: String,
- pub version: String,
+ pub name: Rc>,
+ pub version: Rc>,
+ radar_lens: Rc| >,
pub radars: Vec,
pub algorithms: Vec,
}
-#[derive( Clone, Debug)]
+#[derive( Clone, Debug, PartialOrd, PartialEq)]
pub struct RadarConfig{
pub name: String,
pub _type: String,
@@ -21,35 +24,28 @@ pub struct RadarConfig{
r_limit: f64,
}
-#[derive( Clone, Debug)]
+#[derive( Clone, Debug, PartialOrd, PartialEq)]
pub struct AlgorithmConfig {
name: String,
version: String,
- info: HashMap
+ // info: HashMap
}
impl CommonConfig{
pub fn to_settings(&self) -> Vec{
let mut settings = Vec::new();
- settings.push(SettingItem::new("Name".to_string(), SettingType::Entry(Some(self.name.clone()), None)));
- settings.push(SettingItem::new("Version".to_string(), SettingType::Entry(Some(self.version.clone()), None)));
- settings.push(SettingItem::new("Radar Num".to_string(), SettingType::Spin(0.0, 0.0, 100.0, 1.0)));
+ // settings.push(SettingItem::new("Name".to_string(), SettingType::Entry(Some(self.name.borrow().clone()), None, Some(self.name.clone()))));
+ settings.push(SettingItem::new("Version".to_string(), SettingType::Entry(Some(self.version.borrow().clone()), None, Some(self.version.clone()))));
+ settings.push(SettingItem::new("Radar Num".to_string(), SettingType::Spin(0.0, 0.0, 100.0, 1.0, Some(self.radar_lens.clone()))));
for radar in self.radars.iter(){
- settings.push(SettingItem::new("Name".to_string(), SettingType::Entry(Some(radar.name.clone()), None)));
- settings.push(SettingItem::new("Type".to_string(), SettingType::Entry(Some(radar._type.clone()), None)));
- settings.push(SettingItem::new("Location".to_string(), SettingType::Entry(Some(format!("{},{},{}", radar.loc[0], radar.loc[1], radar.loc[2])), None)));
- settings.push(SettingItem::new("Azimuth Beam Width".to_string(), SettingType::Entry(Some(radar.az_beam_width.to_string()), None)));
- settings.push(SettingItem::new("Elevation Beam Width".to_string(), SettingType::Entry(Some(radar.el_beam_width.to_string()), None)));
- settings.push(SettingItem::new("Azimuth Method".to_string(), SettingType::Select(vec!["1".to_string(), "2".to_string(), "3".to_string()])));
- settings.push(SettingItem::new("Elevation Method".to_string(), SettingType::Select(vec!["1".to_string(), "2".to_string(), "3".to_string()])));
- settings.push(SettingItem::new("Range Limit".to_string(), SettingType::Entry(Some(radar.r_limit.to_string()), None)));
- }
- for algorithm in self.algorithms.iter(){
- settings.push(SettingItem::new("Name".to_string(), SettingType::Entry(Some(algorithm.name.clone()), None)));
- settings.push(SettingItem::new("Version".to_string(), SettingType::Entry(Some(algorithm.version.clone()), None)));
- for (k, v) in algorithm.info.iter(){
- settings.push(SettingItem::new(k.clone(), SettingType::Entry(Some(v.clone()), None)));
- }
+ settings.push(SettingItem::new("Name".to_string(), SettingType::Entry(Some(radar.name.clone()), None, None)));
+ settings.push(SettingItem::new("Type".to_string(), SettingType::Entry(Some(radar._type.clone()), None, None)));
+ settings.push(SettingItem::new("Location".to_string(), SettingType::Entry(Some(format!("{},{},{}", radar.loc[0], radar.loc[1], radar.loc[2])), None, None)));
+ settings.push(SettingItem::new("Azimuth Beam Width".to_string(), SettingType::Entry(Some(radar.az_beam_width.to_string()), None, None)));
+ settings.push(SettingItem::new("Elevation Beam Width".to_string(), SettingType::Entry(Some(radar.el_beam_width.to_string()), None, None)));
+ settings.push(SettingItem::new("Azimuth Method".to_string(), SettingType::Select(vec!["1".to_string(), "2".to_string(), "3".to_string()], None)));
+ settings.push(SettingItem::new("Elevation Method".to_string(), SettingType::Select(vec!["1".to_string(), "2".to_string(), "3".to_string()], None)));
+ settings.push(SettingItem::new("Range Limit".to_string(), SettingType::Entry(Some(radar.r_limit.to_string()), None, None)));
}
settings
}
diff --git a/src/main.rs b/src/main.rs
index 7cb4c14..1f2d629 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -9,26 +9,27 @@ mod components;
mod config;
use components::AppModel;
-const APP_ID: &str = "org.tsuki.radar_g";
+const APP_ID: &str = "org.tsuki.rsproject";
fn main() {
// Load GL pointers from epoxy (GL context management library used by GTK).
let relm = relm4::RelmApp::new(APP_ID);
+
+ initialize_custom_css();
relm.run::(());
- // initialize_custom_css();
}
-// fn initialize_custom_css() {
-// gio::resources_register_include!("css.gresource").unwrap();
-// // Load the CSS file and add it to the provider
-// let provider = gtk::CssProvider::new();
-// // provider.load_from_string();
-// provider.load_from_resource("/org/tsuki/radar_g/css/main.css");
-// use gtk::gdk::Display;
-// // Add the provider to the default screen
-// gtk::style_context_add_provider_for_display(
-// &Display::default().expect("Could not connect to a display."),
-// &provider,
-// gtk::STYLE_PROVIDER_PRIORITY_APPLICATION,
-// );
-// }
+fn initialize_custom_css() {
+ gio::resources_register_include!("css.gresource").unwrap();
+ // Load the CSS file and add it to the provider
+ let provider = gtk::CssProvider::new();
+ // provider.load_from_string();
+ provider.load_from_resource("/org/tsuki/rsproject/css/main.css");
+ use gtk::gdk::Display;
+ // Add the provider to the default screen
+ gtk::style_context_add_provider_for_display(
+ &Display::default().expect("Could not connect to a display."),
+ &provider,
+ gtk::STYLE_PROVIDER_PRIORITY_APPLICATION,
+ );
+}
|