canvas-element-enum #3

Merged
enrico merged 11 commits from canvas-element-enum into master 2020-11-08 15:44:20 +01:00
5 changed files with 52 additions and 291 deletions
Showing only changes of commit 49f5cd7e4d - Show all commits

32
Cargo.lock generated
View File

@ -772,25 +772,6 @@ dependencies = [
"version_check", "version_check",
] ]
[[package]]
name = "input"
version = "0.5.0"
source = "git+https://github.com/Smithay/input.rs#2b2f372101cbb165f5f92e8d6b05ca1be9e4fefe"
dependencies = [
"bitflags",
"input-sys",
"libc",
"udev 0.4.0",
]
[[package]]
name = "input-sys"
version = "1.15.0"
source = "git+https://github.com/Smithay/input.rs#2b2f372101cbb165f5f92e8d6b05ca1be9e4fefe"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "instant" name = "instant"
version = "0.1.7" version = "0.1.7"
@ -1360,9 +1341,8 @@ dependencies = [
"gio", "gio",
"gtk", "gtk",
"im", "im",
"input",
"libc", "libc",
"udev 0.2.0", "udev",
] ]
[[package]] [[package]]
@ -1507,16 +1487,6 @@ dependencies = [
"libudev-sys", "libudev-sys",
] ]
[[package]]
name = "udev"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24953d50a3bce0f5f5a9a2766567072dc9af8096f8c40ea81815da651066bc9f"
dependencies = [
"libc",
"libudev-sys",
]
[[package]] [[package]]
name = "unic-bidi" name = "unic-bidi"
version = "0.9.0" version = "0.9.0"

View File

@ -7,7 +7,6 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
input = { git = "https://github.com/Smithay/input.rs" }
udev = "0.2" udev = "0.2"
libc = "0.2" libc = "0.2"
errno = "0.2" errno = "0.2"

View File

@ -1,158 +0,0 @@
use std::vec::Vec;
use std::cell::RefCell;
use std::rc::Rc;
use gtk::prelude::*;
use gio::prelude::*;
use gtk::{Application, ApplicationWindow, DrawingArea, Box, Button, CheckButton, HeaderBar};
struct AppState {
draw_lines: bool,
do_draw: bool,
point_buffer: Vec<(f64, f64)>,
}
fn main() {
let application = Application::new(
Some("team.acqua.enrico.styluscapture"),
Default::default(),
).expect("failed to initialize GTK application");
application.connect_activate(|app| {
let app_state = Rc::new(RefCell::new(AppState{
draw_lines: false,
do_draw: false,
point_buffer: Vec::new(),
}));
let drawing_area = DrawingArea::new();
let state_clone_1 = Rc::clone(&app_state);
drawing_area.set_size_request(100, 100);
drawing_area.connect_draw(move |widget, cr| {
let style_context = widget.get_style_context();
let wa = widget.get_allocation();
gtk::render_background(
&style_context,
&cr,
wa.x as f64,
wa.y as f64,
wa.width as f64,
wa.height as f64
);
let state = state_clone_1.borrow();
if state.point_buffer.len() > 0 {
cr.set_source_rgb(1.0, 0.0, 0.0);
if state.draw_lines {
let (x, y) = state.point_buffer[0];
cr.move_to(x - wa.x as f64, y - wa.y as f64);
for pt in &state.point_buffer[1..] {
cr.line_to(pt.0 - wa.x as f64, pt.1 - wa.y as f64);
}
cr.set_line_width(3.);
cr.stroke();
} else {
for pt in &state.point_buffer[1..] {
use std::f64::consts::PI;
cr.arc(pt.0 - wa.x as f64, pt.1 - wa.y as f64, 3., 0., 2. * PI);
cr.fill();
}
}
}
gtk::Inhibit(false)
});
let save_button = Button::from_icon_name(Some("document-save-symbolic"), gtk::IconSize::Menu);
let clear_button = Button::from_icon_name(Some("edit-clear-all-symbolic"), gtk::IconSize::Menu);
let check_button = CheckButton::with_label("Join Points");
let header = HeaderBar::new();
header.pack_start(&save_button);
header.pack_start(&clear_button);
header.pack_start(&check_button);
let w_box = Box::new(gtk::Orientation::Vertical, 10);
w_box.pack_start(&header, false, false, 0);
w_box.pack_end(&drawing_area, true, true, 0);
let window = Rc::new(ApplicationWindow::new(app));
window.set_title("Stylus Capture");
window.set_default_size(500, 500);
let state_clone_3 = Rc::clone(&app_state);
let win_clone = Rc::clone(&window);
clear_button.connect_clicked(move |_| {
state_clone_3.borrow_mut().point_buffer.clear();
win_clone.queue_draw();
});
let state_clone_4 = Rc::clone(&app_state);
save_button.connect_clicked(move |_| {
let writer = csv::Writer::from_path("acquired_data.csv");
if let Ok(mut wrt) = writer {
wrt.write_record(&["x", "y"]).expect("write error");
for pt in &state_clone_4.borrow().point_buffer {
wrt.write_record(&[pt.0.to_string(), pt.1.to_string()]).expect("write error");
}
wrt.flush().unwrap();
}
});
let state_clone_3 = Rc::clone(&app_state);
let win_clone_2 = Rc::clone(&window);
check_button.connect_clicked(move |_| {
let mut borrow = state_clone_3.borrow_mut();
borrow.draw_lines = ! borrow.draw_lines;
win_clone_2.queue_draw();
});
let state_clone_2 = Rc::clone(&app_state);
window.connect_event(move |widget, event| {
let mut capture_event = false;
if event.get_device_tool()
.map(|tool| tool.get_tool_type() == gdk::DeviceToolType::Pen) == Some(true) {
match event.get_event_type() {
gdk::EventType::ProximityOut => {
std::println!("pen out of proximity");
},
gdk::EventType::ProximityIn => {
std::println!("pen in proximity");
},
gdk::EventType::MotionNotify => {
let mut state = state_clone_2.borrow_mut();
if state.do_draw {
state.point_buffer.push(event.get_coords().unwrap());
widget.queue_draw();
}
},
gdk::EventType::ButtonPress | gdk::EventType::ButtonRelease => {
std::println!("evt: {:#?}, tool: {:#?}", event, event.get_device_tool());
state_clone_2.borrow_mut().do_draw = event.get_event_type() == gdk::EventType::ButtonPress;
capture_event = true;
},
_ => {
std::println!("{:#?}", event);
}
}
}
std::println!("{:#?}\n", event.get_device_tool().map(|tool| tool.get_tool_type()));
gtk::Inhibit(capture_event)
//std::println!("{:#?}",event.get_event_type());
//std::println!("{:#?}", event.get_source_device().and_then(|d| d.get_property_tool()).map(|t| t.get_tool_type()));
//std::println!("{:#?}", event.get_device().and_then(|d| d.get_property_tool()).map(|t| t.get_tool_type()));
});
window.add(&w_box);
window.show_all();
});
application.run(&[]);
}

View File

@ -1,67 +0,0 @@
use input::{Libinput, LibinputInterface};
use input::event::Event;
use input::event::tablet_tool::{TabletToolEvent, TabletToolEventTrait};
use std::time;
use std::ffi::CString;
use std::path::Path;
use std::os::unix::io::{RawFd};
struct SimpleLibinputInterface;
impl LibinputInterface for SimpleLibinputInterface {
fn open_restricted(&mut self, path: &Path, flags: i32) -> Result<RawFd, i32> {
let c_path = path.to_str()
.map(|s| CString::new(s).unwrap())
.unwrap();
let fd = unsafe {
libc::open64(c_path.as_ptr(), flags)
};
if fd < 0 {
let err: i32 = errno::errno().into();
std::println!("{:?}, flags({}), fd({})", path, flags, fd);
Err(-err)
} else {
Ok(fd)
}
}
fn close_restricted(&mut self, fd: RawFd) {
unsafe { libc::close(fd); }
}
}
fn main() {
let libinput_interface = SimpleLibinputInterface{};
let mut libinput_ctx = Libinput::new_with_udev(libinput_interface);
libinput_ctx.udev_assign_seat("seat0").unwrap();
let mut csv_writer = csv::Writer::from_path("acquired_data.csv").unwrap();
csv_writer.write_record(&["x", "y", "pressure", "time_usec"]).expect("write error");
loop {
while let Some(event) = libinput_ctx.next() {
if let Event::Tablet(tablet_evt) = event {
if let TabletToolEvent::Axis(axis_evt) = tablet_evt {
if axis_evt.pressure() > 1e-3 {
let pressure = axis_evt.pressure();
let x_t = axis_evt.x_transformed(1080);
let y_t = axis_evt.y_transformed(1920);
let time_usec = axis_evt.time_usec();
std::println!(
"(x, y) = ({}, {})\npressure = {}\n(tilt_x, tilt_y) = ({}, {})\n",
x_t,
y_t,
pressure,
axis_evt.tilt_x(),
axis_evt.tilt_y());
csv_writer.write_record(&[x_t.to_string(), y_t.to_string(), pressure.to_string(), time_usec.to_string()]).expect("write error");
csv_writer.flush().expect("write error");
}
}
}
}
libinput_ctx.dispatch().unwrap();
}
}

View File

@ -14,17 +14,16 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
use std::rc::Rc;
use druid::im::{vector, Vector}; use druid::im::{vector, Vector};
use druid::kurbo::BezPath; use druid::kurbo::BezPath;
use druid::widget::prelude::*; use druid::widget::prelude::*;
use druid::{ use druid::{AppLauncher, Color, Data, Event, LocalizedString, Rect, WindowDesc};
AppLauncher, Color, Data, Event, LocalizedString, Rect, WindowDesc, use std::rc::Rc;
};
mod stiletto { mod stiletto {
use druid::widget::prelude::*; use druid::widget::prelude::*;
pub trait CanvasElement { //: CanvasElementData { pub trait CanvasElement {
//: CanvasElementData {
/// returns the axis-aligned bounding box /// returns the axis-aligned bounding box
fn bounding_box(&self) -> druid::Rect; fn bounding_box(&self) -> druid::Rect;
@ -85,8 +84,6 @@ mod stiletto {
ctx.stroke(&self.kurbo_path, &stroke_color, 2.0); ctx.stroke(&self.kurbo_path, &stroke_color, 2.0);
} }
} }
} }
struct CanvasWidget; struct CanvasWidget;
@ -98,33 +95,44 @@ struct CanvasData {
} }
impl Widget<CanvasData> for CanvasWidget { impl Widget<CanvasData> for CanvasWidget {
fn event<'a>(&mut self, _ctx: &mut EventCtx, event: &Event, data: &'a mut CanvasData, _env: &Env) { fn event<'a>(
&mut self,
_ctx: &mut EventCtx,
event: &Event,
data: &'a mut CanvasData,
_env: &Env,
) {
match event { match event {
Event::MouseDown(mouse_event) => { Event::MouseDown(mouse_event) => {
if true /*&& mouse_event.pointer_type == druid::PointerType::Stylus || mouse_event.pointer_type == druid::PointerType::Mouse*/ { if true
/*&& mouse_event.pointer_type == druid::PointerType::Stylus || mouse_event.pointer_type == druid::PointerType::Mouse*/
{
data.is_drawing = true; data.is_drawing = true;
let mut kurbo_path = BezPath::new(); let mut kurbo_path = BezPath::new();
kurbo_path.move_to((mouse_event.pos.x, mouse_event.pos.y)); kurbo_path.move_to((mouse_event.pos.x, mouse_event.pos.y));
let new_path = Rc::new(stiletto::CanvasPath { kurbo_path }); let new_path = Rc::new(stiletto::CanvasPath { kurbo_path });
data.elements.push_back(new_path); data.elements.push_back(new_path);
} }
}, }
Event::MouseMove(mouse_event) => { Event::MouseMove(mouse_event) => {
if data.is_drawing /*&& (mouse_event.pointer_type == druid::PointerType::Stylus || mouse_event.pointer_type == druid::PointerType::Mouse)*/ { if data.is_drawing
let ptr: &'a mut dyn stiletto::CanvasElement = Rc::get_mut(data.elements.back_mut().unwrap()).unwrap(); /*&& (mouse_event.pointer_type == druid::PointerType::Stylus || mouse_event.pointer_type == druid::PointerType::Mouse)*/
{
let ptr: &'a mut dyn stiletto::CanvasElement =
Rc::get_mut(data.elements.back_mut().unwrap()).unwrap();
let last_canvas_path: &'a mut stiletto::CanvasPath = ptr.get_path().unwrap(); let last_canvas_path: &'a mut stiletto::CanvasPath = ptr.get_path().unwrap();
last_canvas_path.kurbo_path.line_to((mouse_event.pos.x, mouse_event.pos.y)); last_canvas_path
.kurbo_path
.line_to((mouse_event.pos.x, mouse_event.pos.y));
}
} }
},
Event::MouseUp(_) => { Event::MouseUp(_) => {
if data.is_drawing { if data.is_drawing {
data.is_drawing = false; data.is_drawing = false;
} }
}, }
_ => {} _ => {}
} }
} }
@ -137,7 +145,13 @@ impl Widget<CanvasData> for CanvasWidget {
) { ) {
} }
fn update(&mut self, ctx: &mut UpdateCtx, _old_data: &CanvasData, _data: &CanvasData, _env: &Env) { fn update(
&mut self,
ctx: &mut UpdateCtx,
_old_data: &CanvasData,
_data: &CanvasData,
_env: &Env,
) {
ctx.request_paint_rect(Rect::new(0., 0., 200., 200.)); ctx.request_paint_rect(Rect::new(0., 0., 200., 200.));
} }
@ -179,7 +193,10 @@ impl Widget<CanvasData> for CanvasWidget {
pub fn main() { pub fn main() {
let window = WindowDesc::new(|| CanvasWidget {}) let window = WindowDesc::new(|| CanvasWidget {})
//.window_size((1024.0, 1400.0)) //.window_size((1024.0, 1400.0))
.title(LocalizedString::new("custom-widget-demo-window-title").with_placeholder("Fancy Colors")); .title(
LocalizedString::new("custom-widget-demo-window-title")
.with_placeholder("Fancy Colors"),
);
let canvas_data = CanvasData { let canvas_data = CanvasData {
elements: vector![], elements: vector![],
is_drawing: false, is_drawing: false,