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)] #[derive(Debug, Clone)]
pub struct MouseKeyboardState { pub struct MouseKeyboardState {
pub mouse_state: MouseState, 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, viewport: &ViewPort,
) -> bool { ) -> bool {
let viewport_size = viewport.size(); let viewport_size = viewport.size();
// let shift_key = state.keyboard_state[imgui::Key::LeftShift as usize]; let shift_key = state.keyboard_state[1];
// let ctrl_key = state.keyboard_state[imgui::Key::LeftCtrl as usize]; let ctrl_key = state.keyboard_state[0];
let shift_key = false;
let ctrl_key = false;
match &state.mouse_state { match &state.mouse_state {
MouseState::Drag { from, delta } => { MouseState::Drag { from, delta } => {

View File

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

View File

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

View File

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

View File

@ -62,7 +62,9 @@ pub enum FileIOType {
pub enum AppMsg { pub enum AppMsg {
Refresh, Refresh,
FileIO { typ: FileIOType }, FileIO { typ: FileIOType },
IO { key: u32, pressed: bool },
OpenDialog { widget: Widget }, OpenDialog { widget: Widget },
OpenFile(PathBuf),
CloseDialog, CloseDialog,
OpenAlert { body: String, title: String }, OpenAlert { body: String, title: String },
CloseAlert, CloseAlert,
@ -232,7 +234,7 @@ impl Component for AppModel {
sidebar_sender, sidebar_sender,
move |model_message| match model_message { move |model_message| match model_message {
MonitorOutputMsg::Attached(new_module) => { MonitorOutputMsg::Attached(new_module) => {
sidebar_sender.emit(SideBarInputMsg::Package(new_module)); sidebar_sender.emit(SideBarInputMsg::Packages(new_module));
AppMsg::CloseDialog AppMsg::CloseDialog
} }
MonitorOutputMsg::Dialog(widget) => { MonitorOutputMsg::Dialog(widget) => {
@ -272,21 +274,7 @@ impl Component for AppModel {
move |response| match response { move |response| match response {
OpenDialogResponse::Accept(path) => { OpenDialogResponse::Accept(path) => {
info!("path: {:?}", path); info!("path: {:?}", path);
match data_pool.borrow_mut().get_or_load(path) { AppMsg::OpenFile(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::Close, _ => 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 { let model = AppModel {
render, render,
setting, setting,
@ -307,6 +311,35 @@ impl Component for AppModel {
let render = model.render.widget(); let render = model.render.widget();
let sidebar = model.sidebar.widget(); let sidebar = model.sidebar.widget();
let widgets = view_output!(); 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(); let mut group = RelmActionGroup::<FileActionGroup>::new();
relm4::main_application().set_accelerators_for_action::<OpenAction>(&["<primary>O"]); relm4::main_application().set_accelerators_for_action::<OpenAction>(&["<primary>O"]);
let action: RelmAction<OpenAction> = { let action: RelmAction<OpenAction> = {
@ -343,6 +376,18 @@ impl Component for AppModel {
AppMsg::CloseDialog => { AppMsg::CloseDialog => {
widgets.dialog.close(); 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 } => { AppMsg::OpenAlert { body, title } => {
widgets.alert_dialog.set_body(&body); widgets.alert_dialog.set_body(&body);
widgets.alert_dialog.set_title(&title); widgets.alert_dialog.set_title(&title);
@ -354,6 +399,25 @@ impl Component for AppModel {
widgets.alert_dialog.present(Some(root)); 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 { AppMsg::FileIO {
typ: FileIOType::Open(data), typ: FileIOType::Open(data),
} => self.render.emit(MonitorInputMsg::PushData(data)), } => self.render.emit(MonitorInputMsg::PushData(data)),

View File

@ -1,6 +1,6 @@
use epoxy::S; use epoxy::S;
use gi::pg::ModuleRefs; use gi::pg::ModuleRefs;
use gtk::Widget; use gtk::{SingleSelection, Widget};
use radarg_core::Data; use radarg_core::Data;
use std::collections::HashMap; use std::collections::HashMap;
@ -9,7 +9,7 @@ use relm4::{
factory::FactoryVecDeque, factory::FactoryVecDeque,
gtk::{ gtk::{
self, self,
glib::{clone, *}, glib::{self, clone, *},
prelude::*, prelude::*,
}, },
prelude::*, prelude::*,
@ -31,17 +31,26 @@ pub struct ItemInfo {
#[derive(Debug)] #[derive(Debug)]
pub enum DialogOutput { pub enum DialogOutput {
Cancel, Cancel,
Open(usize), Open(Vec<usize>),
} }
#[tracker::track]
pub struct Dialog { 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)] #[relm4::component(pub)]
impl SimpleComponent for Dialog { impl SimpleComponent for Dialog {
type Widgets = DialogWidgets; type Widgets = DialogWidgets;
type Init = HashMap<(usize, String), Vec<ItemInfo>>; type Init = HashMap<(usize, String), Vec<ItemInfo>>;
type Input = (); type Input = DialogInput;
type Output = DialogOutput; type Output = DialogOutput;
view! { view! {
@ -84,6 +93,11 @@ impl SimpleComponent for Dialog {
}, },
gtk::Button{ gtk::Button{
set_label:"Open", 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 { let model = Self {
list_view_wrapper: list_view, list_view_wrapper: list_view,
selected: Vec::with_capacity(10),
tracker: 0,
}; };
let list = &model.list_view_wrapper.view; let list = &model.list_view_wrapper.view;
let selection = list.model().unwrap(); let selection = list.model().unwrap();
selection.connect_selection_changed(|a, b, c| {
println!("Selection changed");
println!(" b: {}, c: {}", b, c);
});
let widgets = view_output!(); 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 { ComponentParts {
model: model, model: model,
widgets, 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)] #[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 { pub enum MonitorInputMsg {
PushData(Value<Data>), PushData(Value<Data>),
Draw(Arc<Data>), Draw(Arc<Data>),
Prepare(Vec<Arc<Data>>),
KeyPress(u32),
KeyRelease(u32),
QueueDraw, QueueDraw,
None, None,
} }
@ -18,6 +21,11 @@ impl Debug for MonitorInputMsg {
MonitorInputMsg::Draw(data) => { MonitorInputMsg::Draw(data) => {
write!(f, "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::PushData(data) => write!(f, "MonitorInputMsg::PushData({:?})", data),
MonitorInputMsg::None => write!(f, "MonitorInputMsg::None"), MonitorInputMsg::None => write!(f, "MonitorInputMsg::None"),
} }
@ -26,7 +34,7 @@ impl Debug for MonitorInputMsg {
#[derive(Debug)] #[derive(Debug)]
pub enum MonitorOutputMsg { pub enum MonitorOutputMsg {
Attached(Rc<RefCell<ModulePackage>>), Attached(Vec<(String, Rc<RefCell<ModulePackage>>)>),
Dialog(Widget), Dialog(Widget),
DialogClose, DialogClose,
Alert(String, String), Alert(String, String),

View File

@ -39,7 +39,9 @@ pub struct MonitorModel {
render_cfg: RenderConfig, render_cfg: RenderConfig,
sidebar_open: bool, sidebar_open: bool,
sidebar_width: i32, 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] #[do_not_track]
mainload: MainLoadAttach, mainload: MainLoadAttach,
} }
@ -73,7 +75,7 @@ impl Component for MonitorModel {
let scale = r.scale(); let scale = r.scale();
}, },
#[track = "model.changed(MonitorModel::module_packages())"] #[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{ add_overlay=&gtk::Button{
@ -121,8 +123,11 @@ impl Component for MonitorModel {
sender.input_sender(), sender.input_sender(),
move |msg| match msg { move |msg| match msg {
DialogOutput::Open(index) => { DialogOutput::Open(index) => {
let data = data.iter().find(|d| *d.0 == index).unwrap(); let prepare_datas = index.into_iter().map(|i| {
MonitorInputMsg::Draw(data.1.clone()) let data = data.iter().find(|d| *d.0 == i).unwrap();
data.1.clone()
});
MonitorInputMsg::Prepare(prepare_datas.collect())
} }
DialogOutput::Cancel => { DialogOutput::Cancel => {
new_sender.output(MonitorOutputMsg::DialogClose); 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)); sender.output(MonitorOutputMsg::Dialog(widget));
} }
@ -141,25 +154,65 @@ impl Component for MonitorModel {
MonitorInputMsg::QueueDraw => { MonitorInputMsg::QueueDraw => {
widgets.renderer.queue_draw(); 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) { match gi.program().ppi().load_data(data.into(), &SETTING) {
Ok(package) => { Ok(package) => {
let package = Rc::new(RefCell::new(package.into())); let package = Rc::new(RefCell::new(package.into()));
self.set_module_packages(vec![package.clone()]); packages.push((data.description.clone(), package));
sender.output(MonitorOutputMsg::Attached(package));
} }
Err(e) => { Err(e) => {
error!("Error loading data: {:?}", e); error!("Error loading data: {:?}", e);
sender.output(MonitorOutputMsg::Alert(e.to_string(), format!("Close"))); 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); 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 => {} MonitorInputMsg::None => {}
_ => {} _ => {}
@ -186,6 +239,7 @@ impl Component for MonitorModel {
module_packages: vec![], module_packages: vec![],
sidebar_open: true, sidebar_open: true,
sidebar_width: 400, sidebar_width: 400,
controller: None,
tracker: 0, tracker: 0,
}; };

View File

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

View File

@ -167,6 +167,9 @@ impl GLAreaImpl for Render {
unsafe { unsafe {
gl.clear_color(0.0, 0.0, 0.0, 1.0); gl.clear_color(0.0, 0.0, 0.0, 1.0);
gl.clear(glow::COLOR_BUFFER_BIT | glow::DEPTH_BUFFER_BIT); 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() { 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 scale_acc = Arc::new(Mutex::new(0.0));
let dpi = this.scale_factor() as f32; let dpi = this.scale_factor() as f32;
this.set_has_depth_buffer(true);
let pointer_location_detecture = gtk::EventControllerMotion::new(); let pointer_location_detecture = gtk::EventControllerMotion::new();
let dpi = this.scale_factor() as f32; let dpi = this.scale_factor() as f32;
@ -166,6 +168,30 @@ impl Render {
self.imp().window_size().unwrap() 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>>>) { pub fn draw(&self, packages: &Vec<Rc<RefCell<ModulePackage>>>) {
let mut modules = self.imp().modules.borrow_mut(); let mut modules = self.imp().modules.borrow_mut();
*(&mut *modules) = packages.clone(); *(&mut *modules) = packages.clone();