add droptarget

This commit is contained in:
Tsuki 2024-09-03 13:57:27 +08:00
parent 61c0eb3f52
commit 71ac338c1d
12 changed files with 310 additions and 102 deletions

View File

@ -143,5 +143,5 @@ pub enum MouseState {
#[derive(Debug, Clone)]
pub struct MouseKeyboardState {
pub mouse_state: MouseState,
pub keyboard_state: [bool; 652],
pub keyboard_state: [bool; 4],
}

View File

@ -56,11 +56,8 @@ impl AttachWithIO for PlaneTrans {
viewport: &ViewPort,
) -> bool {
let viewport_size = viewport.size();
// let shift_key = state.keyboard_state[imgui::Key::LeftShift as usize];
// let ctrl_key = state.keyboard_state[imgui::Key::LeftCtrl as usize];
let shift_key = false;
let ctrl_key = false;
let shift_key = state.keyboard_state[1];
let ctrl_key = state.keyboard_state[0];
match &state.mouse_state {
MouseState::Drag { from, delta } => {

View File

@ -38,7 +38,8 @@ static MODULE_PACKAGE_ID: AtomicUsize = AtomicUsize::new(0);
#[derive(Debug)]
pub enum SideBarInputMsg {
Package(Rc<RefCell<ModulePackage>>),
Packages(Vec<(String, Rc<RefCell<ModulePackage>>)>),
SwitchTo(gtk::glib::GString),
Refresh,
None,
}

View File

@ -573,7 +573,7 @@ impl SimpleComponent for PPIModuleConfigComponent {
set_adjustment=&gtk::Adjustment::new(
init_config.layer as f64 + 1.0,
1.0,
init_config.max_layer as f64,
init_config.max_layer as f64 + 1.0,
1.0,
1.0,
1.0

View File

@ -11,12 +11,12 @@ pub struct MouseIO {
#[derive(Debug)]
pub struct KeyboardIO {
pub keys: [bool; 652], // 键盘按键状态
pub keys: [bool; 4], // 键盘按键状态
}
impl Default for KeyboardIO {
fn default() -> Self {
Self { keys: [false; 652] }
Self { keys: [false; 4] }
}
}

View File

@ -62,7 +62,9 @@ pub enum FileIOType {
pub enum AppMsg {
Refresh,
FileIO { typ: FileIOType },
IO { key: u32, pressed: bool },
OpenDialog { widget: Widget },
OpenFile(PathBuf),
CloseDialog,
OpenAlert { body: String, title: String },
CloseAlert,
@ -232,7 +234,7 @@ impl Component for AppModel {
sidebar_sender,
move |model_message| match model_message {
MonitorOutputMsg::Attached(new_module) => {
sidebar_sender.emit(SideBarInputMsg::Package(new_module));
sidebar_sender.emit(SideBarInputMsg::Packages(new_module));
AppMsg::CloseDialog
}
MonitorOutputMsg::Dialog(widget) => {
@ -272,21 +274,7 @@ impl Component for AppModel {
move |response| match response {
OpenDialogResponse::Accept(path) => {
info!("path: {:?}", path);
match data_pool.borrow_mut().get_or_load(path) {
Ok(data) => {
info!("data: {}", data);
AppMsg::FileIO {
typ: FileIOType::Open(data),
}
}
Err(e) => {
error!("Failed to load data, cause: {:?}", e);
AppMsg::OpenAlert {
body: format!("Failed to load data, cause: {:?}", e),
title: "Error".to_string(),
}
}
}
AppMsg::OpenFile(path)
}
_ => AppMsg::Close,
}
@ -294,6 +282,22 @@ impl Component for AppModel {
)
};
// Drop Target
let drop_target =
gtk::DropTarget::new(gtk::gio::File::static_type(), gtk::gdk::DragAction::COPY);
let drop_sender = sender.clone();
drop_target.connect_drop(move |_drop_target, value, _x, _y| {
if let Ok(file) = value.get::<gtk::gio::File>() {
if let Some(path) = file.path() {
drop_sender.input(AppMsg::OpenFile(path));
}
}
true
});
let model = AppModel {
render,
setting,
@ -307,6 +311,35 @@ impl Component for AppModel {
let render = model.render.widget();
let sidebar = model.sidebar.widget();
let widgets = view_output!();
// Key Detector
let key_detector = gtk::EventControllerKey::new();
key_detector.connect_key_pressed(clone!(
#[strong]
sender,
move |_, key, code, modifier| {
sender.input(AppMsg::IO {
key: key.to_value().get_owned().unwrap(),
pressed: true,
});
gtk::glib::Propagation::Proceed
}
));
key_detector.connect_key_released(clone!(
#[strong]
sender,
move |_, key, code, modifier| {
sender.input(AppMsg::IO {
key: key.to_value().get_owned().unwrap(),
pressed: false,
});
}
));
widgets.main_window.add_controller(key_detector);
widgets.main_window.add_controller(drop_target);
let mut group = RelmActionGroup::<FileActionGroup>::new();
relm4::main_application().set_accelerators_for_action::<OpenAction>(&["<primary>O"]);
let action: RelmAction<OpenAction> = {
@ -343,6 +376,18 @@ impl Component for AppModel {
AppMsg::CloseDialog => {
widgets.dialog.close();
}
AppMsg::IO { key, pressed } => {
// Skip the key event if it is the ESC key
if key == 16777215 {
return;
}
if pressed {
self.render.emit(MonitorInputMsg::KeyPress(key));
} else {
self.render.emit(MonitorInputMsg::KeyRelease(key));
}
}
AppMsg::OpenAlert { body, title } => {
widgets.alert_dialog.set_body(&body);
widgets.alert_dialog.set_title(&title);
@ -354,6 +399,25 @@ impl Component for AppModel {
widgets.alert_dialog.present(Some(root));
}
AppMsg::OpenFile(path) => {
let mut datapool = self.file_pool.borrow_mut();
match datapool.get_or_load(path) {
Ok(data) => {
info!("data: {}", data);
_sender.input(AppMsg::FileIO {
typ: FileIOType::Open(data),
});
}
Err(e) => {
error!("Failed to load data, cause: {:?}", e);
_sender.input(AppMsg::OpenAlert {
body: format!("Failed to load data, cause: {:?}", e),
title: "Error".to_string(),
});
}
}
}
AppMsg::FileIO {
typ: FileIOType::Open(data),
} => self.render.emit(MonitorInputMsg::PushData(data)),

View File

@ -1,6 +1,6 @@
use epoxy::S;
use gi::pg::ModuleRefs;
use gtk::Widget;
use gtk::{SingleSelection, Widget};
use radarg_core::Data;
use std::collections::HashMap;
@ -9,7 +9,7 @@ use relm4::{
factory::FactoryVecDeque,
gtk::{
self,
glib::{clone, *},
glib::{self, clone, *},
prelude::*,
},
prelude::*,
@ -31,17 +31,26 @@ pub struct ItemInfo {
#[derive(Debug)]
pub enum DialogOutput {
Cancel,
Open(usize),
Open(Vec<usize>),
}
#[tracker::track]
pub struct Dialog {
list_view_wrapper: TypedColumnView<DataRow, gtk::SingleSelection>,
#[do_not_track]
list_view_wrapper: TypedColumnView<DataRow, gtk::MultiSelection>,
selected: Vec<usize>,
}
#[derive(Debug)]
pub enum DialogInput {
Selected(Vec<u32>),
Open,
}
#[relm4::component(pub)]
impl SimpleComponent for Dialog {
type Widgets = DialogWidgets;
type Init = HashMap<(usize, String), Vec<ItemInfo>>;
type Input = ();
type Input = DialogInput;
type Output = DialogOutput;
view! {
@ -84,6 +93,11 @@ impl SimpleComponent for Dialog {
},
gtk::Button{
set_label:"Open",
#[track = "model.changed(Dialog::selected())"]
set_sensitive: !model.selected.is_empty(),
connect_clicked[sender] => move |_| {
sender.input(DialogInput::Open);
},
},
},
}
@ -115,25 +129,71 @@ impl SimpleComponent for Dialog {
let model = Self {
list_view_wrapper: list_view,
selected: Vec::with_capacity(10),
tracker: 0,
};
let list = &model.list_view_wrapper.view;
let selection = list.model().unwrap();
selection.connect_selection_changed(|a, b, c| {
println!("Selection changed");
println!(" b: {}, c: {}", b, c);
});
let widgets = view_output!();
selection.connect_selection_changed(clone!(
#[strong]
sender,
move |this, from, num| {
let selection = this.selection();
let iter = gtk::BitsetIter::init_first(&selection);
if let Some((iter, first)) = iter {
if !iter.is_valid() {
return;
} else {
let mut selected = vec![first];
selected.extend(iter.map(|i| i));
sender.input(DialogInput::Selected(selected));
}
}
// this.selected().map(|selected| {
// sender.input(DialogInput::Selected(Some(selected)));
// });
// let selection: &gtk::MultiSelection = this.downcast_ref().unwrap();
// let selected = selection.
// let selected = selection.selected();
// sender.input(DialogInput::Selected(Some(selected)));
}
));
ComponentParts {
model: model,
widgets,
}
}
fn update(&mut self, message: Self::Input, sender: ComponentSender<Self>) {}
fn update(&mut self, message: Self::Input, sender: ComponentSender<Self>) {
self.reset();
match message {
DialogInput::Selected(selected) => {
let s = selected
.into_iter()
.map(|s| {
let item = self.list_view_wrapper.get(s);
item
})
.filter(|item| item.is_some())
.map(|item| item.unwrap().borrow().id)
.collect::<Vec<_>>();
self.update_selected(|_s| {
_s.clear();
_s.extend(s);
});
}
DialogInput::Open => {
sender.output(DialogOutput::Open(self.selected.clone()));
}
}
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]

View File

@ -7,6 +7,9 @@ use std::{cell::RefCell, fmt::Debug, rc::Rc, sync::Arc};
pub enum MonitorInputMsg {
PushData(Value<Data>),
Draw(Arc<Data>),
Prepare(Vec<Arc<Data>>),
KeyPress(u32),
KeyRelease(u32),
QueueDraw,
None,
}
@ -18,6 +21,11 @@ impl Debug for MonitorInputMsg {
MonitorInputMsg::Draw(data) => {
write!(f, "MonitorInputMsg::Draw({:?})", data)
}
MonitorInputMsg::Prepare(data) => {
write!(f, "MonitorInputMsg::Prepare({:?})", data)
}
MonitorInputMsg::KeyPress(key) => write!(f, "MonitorInputMsg::Key({:?})", key),
MonitorInputMsg::KeyRelease(key) => write!(f, "MonitorInputMsg::KeyRelease({:?})", key),
MonitorInputMsg::PushData(data) => write!(f, "MonitorInputMsg::PushData({:?})", data),
MonitorInputMsg::None => write!(f, "MonitorInputMsg::None"),
}
@ -26,7 +34,7 @@ impl Debug for MonitorInputMsg {
#[derive(Debug)]
pub enum MonitorOutputMsg {
Attached(Rc<RefCell<ModulePackage>>),
Attached(Vec<(String, Rc<RefCell<ModulePackage>>)>),
Dialog(Widget),
DialogClose,
Alert(String, String),

View File

@ -39,7 +39,9 @@ pub struct MonitorModel {
render_cfg: RenderConfig,
sidebar_open: bool,
sidebar_width: i32,
module_packages: Vec<Rc<RefCell<ModulePackage>>>,
#[do_not_track]
controller: Option<Controller<Dialog>>,
module_packages: Vec<(String, Rc<RefCell<ModulePackage>>)>,
#[do_not_track]
mainload: MainLoadAttach,
}
@ -73,7 +75,7 @@ impl Component for MonitorModel {
let scale = r.scale();
},
#[track = "model.changed(MonitorModel::module_packages())"]
draw: &model.module_packages,
draw: &model.module_packages.iter().map(|m| m.1.clone()).collect(),
},
add_overlay=&gtk::Button{
@ -121,8 +123,11 @@ impl Component for MonitorModel {
sender.input_sender(),
move |msg| match msg {
DialogOutput::Open(index) => {
let data = data.iter().find(|d| *d.0 == index).unwrap();
MonitorInputMsg::Draw(data.1.clone())
let prepare_datas = index.into_iter().map(|i| {
let data = data.iter().find(|d| *d.0 == i).unwrap();
data.1.clone()
});
MonitorInputMsg::Prepare(prepare_datas.collect())
}
DialogOutput::Cancel => {
new_sender.output(MonitorOutputMsg::DialogClose);
@ -132,7 +137,15 @@ impl Component for MonitorModel {
},
);
let widget = dialog.widget().to_owned().upcast();
self.controller.replace(dialog);
let widget = self
.controller
.as_ref()
.unwrap()
.widget()
.to_owned()
.upcast();
sender.output(MonitorOutputMsg::Dialog(widget));
}
@ -141,25 +154,65 @@ impl Component for MonitorModel {
MonitorInputMsg::QueueDraw => {
widgets.renderer.queue_draw();
}
MonitorInputMsg::Draw(ref data) => {
widgets.renderer.get_gi(|gi| {
let data: &Data = &*data;
// MonitorInputMsg::KeyPress(key) => {
// widgets.renderer.set_key_pressed(key);
// }
// MonitorInputMsg::KeyRelease(key) => {
// widgets.renderer.set_key_released(key);
// }
MonitorInputMsg::Prepare(datas) => widgets.renderer.get_gi(|gi| {
let mut packages: Vec<(String, Rc<RefCell<ModulePackage>>)> = vec![];
for data in datas {
let data = &*data;
match gi.program().ppi().load_data(data.into(), &SETTING) {
Ok(package) => {
let package = Rc::new(RefCell::new(package.into()));
self.set_module_packages(vec![package.clone()]);
sender.output(MonitorOutputMsg::Attached(package));
packages.push((data.description.clone(), package));
}
Err(e) => {
error!("Error loading data: {:?}", e);
sender.output(MonitorOutputMsg::Alert(e.to_string(), format!("Close")));
break;
}
}
}
sender.input(MonitorInputMsg::QueueDraw);
self.update_module_packages(|p| {
p.clear();
p.extend(packages);
});
sender.output(MonitorOutputMsg::Attached(self.module_packages.clone()));
sender.output(MonitorOutputMsg::DialogClose);
}),
MonitorInputMsg::Draw(ref data) => {
// widgets.renderer.get_gi(|gi| {
// let data: &Data = &*data;
// match gi.program().ppi().load_data(data.into(), &SETTING) {
// Ok(package) => {
// let package = Rc::new(RefCell::new(package.into()));
// self.set_module_packages(vec![package.clone()]);
// sender.output(MonitorOutputMsg::Attached(package));
// }
// Err(e) => {
// error!("Error loading data: {:?}", e);
// sender.output(MonitorOutputMsg::Alert(e.to_string(), format!("Close")));
// }
// }
// sender.input(MonitorInputMsg::QueueDraw);
// });
// sender.output(MonitorOutputMsg::DialogClose);
}
MonitorInputMsg::KeyPress(key) => {
widgets.renderer.set_key_pressed(key);
}
MonitorInputMsg::KeyRelease(key) => {
widgets.renderer.set_key_released(key);
}
MonitorInputMsg::None => {}
_ => {}
@ -186,6 +239,7 @@ impl Component for MonitorModel {
module_packages: vec![],
sidebar_open: true,
sidebar_width: 400,
controller: None,
tracker: 0,
};

View File

@ -32,7 +32,7 @@ use super::{
};
pub struct SideBarModel {
components: Option<Components>,
components: Vec<Components>,
}
#[derive(Debug)]
@ -52,48 +52,30 @@ impl Component for SideBarModel {
#[root]
gtk::Box {
set_orientation: gtk::Orientation::Vertical,
set_spacing: 5,
set_margin_all: 5,
#[name="container"]
gtk::Box {
gtk::Button {
set_orientation: gtk::Orientation::Vertical,
set_spacing: 5,
set_margin_end:10,
set_margin_top:5,
#[name="dropdown"]
gtk::DropDown {
connect_selected_item_notify[sender] => move |this| {
let item = this.selected_item();
item.map(|item| {
let item:gtk::StringObject = item.downcast().unwrap();
let name = item.string();
sender.input(SideBarInputMsg::SwitchTo(name));
});
}
},
#[name="stack"]
gtk::Stack{
set_transition_type:gtk::StackTransitionType::SlideLeftRight,
set_transition_duration:200,
set_hexpand:true,
set_label: "Refresh",
connect_clicked[sender] => move |_| {
view! {
widget=adw::BreakpointBin{
set_width_request: 800,
set_height_request:600,
#[wrap(Some)]
set_child=&adw::ToolbarView{
set_hexpand:true,
set_vexpand:true,
add_top_bar=&adw::HeaderBar{
#[wrap(Some)]
set_title_widget=&gtk::Label{
set_label: "Header",
},
},
#[wrap(Some)]
set_content=&gtk::Box{
gtk::Button{
set_label:"Expanders",
},
gtk::Button{
set_label:"Expanders",
}
}
}
}
};
sender.output(SideBarOutputMsg::Dialog(widget.upcast()));
}
}
}
},
@ -105,8 +87,9 @@ impl Component for SideBarModel {
root: Self::Root,
sender: ComponentSender<Self>,
) -> ComponentParts<Self> {
let app = relm4::main_application();
let mut model = SideBarModel { components: None };
let mut model = SideBarModel {
components: Vec::with_capacity(10),
};
let widgets = view_output!();
ComponentParts { model, widgets }
}
@ -119,19 +102,31 @@ impl Component for SideBarModel {
root: &Self::Root,
) {
match message {
SideBarInputMsg::Package(package) => {
SideBarInputMsg::Packages(package) => {
let names = package.iter().map(|v| v.0.as_str()).collect::<Vec<_>>();
let model = gtk::StringList::new(&names);
widgets.dropdown.set_model(Some(&model));
for (name, package) in package {
let package = package.borrow();
let input_sender = sender.input_sender();
let components = package
let components =
package
.component_builder()
.build(&package, root, input_sender);
self.components.push(components);
self.components = Some(components);
widgets.stack.add_titled(
&self.components.last().unwrap().widget(),
Some(&name),
&name,
);
}
}
widgets.container.remove_all();
widgets
.container
.append(&self.components.as_ref().unwrap().widget());
SideBarInputMsg::SwitchTo(name) => {
widgets.stack.set_visible_child_name(&name);
}
SideBarInputMsg::Refresh => {

View File

@ -167,6 +167,9 @@ impl GLAreaImpl for Render {
unsafe {
gl.clear_color(0.0, 0.0, 0.0, 1.0);
gl.clear(glow::COLOR_BUFFER_BIT | glow::DEPTH_BUFFER_BIT);
gl.enable(glow::DEPTH_TEST);
// gl.enable(glow::BLEND);
// gl.blend_func(glow::SRC_ALPHA, glow::ONE_MINUS_SRC_ALPHA);
}
if let Some(gi) = gi.as_mut() {

View File

@ -42,6 +42,8 @@ impl Render {
let scale_acc = Arc::new(Mutex::new(0.0));
let dpi = this.scale_factor() as f32;
this.set_has_depth_buffer(true);
let pointer_location_detecture = gtk::EventControllerMotion::new();
let dpi = this.scale_factor() as f32;
@ -166,6 +168,30 @@ impl Render {
self.imp().window_size().unwrap()
}
pub fn set_key_pressed(&self, key: u32) {
let io = &self.imp().io;
let mut io_mut = io.borrow_mut();
match key {
65507 => io_mut.keyboard.keys[0] = true,
65505 => io_mut.keyboard.keys[1] = true,
65506 => io_mut.keyboard.keys[2] = true,
65508 => io_mut.keyboard.keys[3] = true,
_ => {}
}
}
pub fn set_key_released(&self, key: u32) {
let io = &self.imp().io;
let mut io_mut = io.borrow_mut();
match key {
65507 => io_mut.keyboard.keys[0] = false,
65505 => io_mut.keyboard.keys[1] = false,
65506 => io_mut.keyboard.keys[2] = false,
65508 => io_mut.keyboard.keys[3] = false,
_ => {}
}
}
pub fn draw(&self, packages: &Vec<Rc<RefCell<ModulePackage>>>) {
let mut modules = self.imp().modules.borrow_mut();
*(&mut *modules) = packages.clone();