A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs139
1 files changed, 106 insertions, 33 deletions
diff --git a/src/main.rs b/src/main.rs
index e9ade1c..08ffb50 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -43,7 +43,7 @@ mod winit_app;
fn main() {
entry(EventLoop::new().unwrap())
}
-
+#[derive(Debug)]
struct Hist {
pub history: Vec<Diff>,
pub redo_history: Vec<Diff>,
@@ -52,7 +52,7 @@ struct Hist {
pub changed: bool,
}
impl Hist {
- pub fn push(&mut self, x: &TextArea) {
+ fn push(&mut self, x: &TextArea) {
let d = diff_match_patch_rs::DiffMatchPatch::new();
self.history.push(Diff {
changes: (
@@ -72,35 +72,56 @@ impl Hist {
(x.cursor, x.column, x.vo),
],
});
+ println!("push {}", self.history.last().unwrap());
self.redo_history.clear();
self.last = x.clone();
+ self.last_edit = Instant::now();
self.changed = false;
}
- pub fn undo(&mut self) -> Option<Diff> {
+ fn undo_(&mut self) -> Option<Diff> {
self.history.pop().map(|x| {
self.redo_history.push(x.clone());
x
})
}
- pub fn redo(&mut self) -> Option<Diff> {
+ fn redo_(&mut self) -> Option<Diff> {
self.redo_history.pop().map(|x| {
self.history.push(x.clone());
x
})
}
- pub fn test_push(&mut self, x: &TextArea) {
- if self.last_edit.elapsed().as_millis() > 500 && self.changed {
+ pub fn undo(&mut self, t: &mut TextArea) {
+ self.push_if_changed(&t);
+ self.undo_().map(|x| {
+ x.apply(t, false);
+ self.last = t.clone();
+ });
+ }
+ pub fn redo(&mut self, t: &mut TextArea) {
+ self.redo_().map(|x| {
+ x.apply(t, true);
+ self.last = t.clone();
+ });
+ }
+ pub fn push_if_changed(&mut self, x: &TextArea) {
+ if self.changed || x.rope != self.last.rope {
self.push(x);
}
}
- pub fn record(&mut self, x: &TextArea) {
- self.test_push(x);
+ pub fn test_push(&mut self, x: &TextArea) {
+ if self.last_edit.elapsed().as_millis() > 500 {
+ self.push_if_changed(x);
+ }
+ }
+ pub fn record(&mut self, _: &TextArea) {
+ // self.test_push(x);
self.last_edit = Instant::now();
self.changed = true;
}
}
static mut MODIFIERS: ModifiersState = ModifiersState::empty();
+static mut CLICKING: bool = false;
const BG: [u8; 3] = [31, 36, 48];
const FG: [u8; 3] = [204, 202, 194];
@@ -257,8 +278,8 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
&text,
);
- println!("cell=");
- dbg!(now.elapsed());
+ // println!("cell=");
+ // dbg!(now.elapsed());
let now = Instant::now();
unsafe {
dsb::render(
@@ -272,8 +293,8 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
i.as_mut(),
)
};
- eprint!("rend=");
- dbg!(now.elapsed());
+ // eprint!("rend=");
+ // dbg!(now.elapsed());
let met = FONT.metrics(&[]);
let fac = ppem / met.units_per_em as f32;
let now = Instant::now();
@@ -301,7 +322,7 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
);
}
};
- eprint!("conv = ");
+ // eprint!("conv = ");
// }
let buffer = surface.buffer_mut().unwrap();
@@ -316,7 +337,7 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
.as_chunks_unchecked_mut::<4>()
},
);
- dbg!(now.elapsed());
+ // dbg!(now.elapsed());
buffer.present().unwrap();
}
}
@@ -337,13 +358,37 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
(position.x / (fw) as f64).round() as usize,
(position.y / (fh + ls * fac) as f64).floor()
as usize,
- )
+ );
+ match state
+ .consume(Action::C(cursor_position))
+ .unwrap()
+ {
+ Some(Do::ExtendSelectionToMouse) => {
+ *state.sel() = text.extend_selection_to(
+ text.index_at(cursor_position),
+ state.sel().clone(),
+ );
+ window.request_redraw();
+ }
+ Some(Do::StartSelection) => {
+ let x = text.index_at(cursor_position);
+ hist.last.cursor = x;
+ text.cursor = x;
+ *state.sel() = x..x;
+ }
+ None => {}
+ x => unreachable!("{x:?}"),
+ }
}
+
Event::WindowEvent {
event:
WindowEvent::MouseInput { state: bt, button, .. },
..
} if bt.is_pressed() => {
+ if button == MouseButton::Left {
+ unsafe { CLICKING = true };
+ }
match state.consume(Action::M(button)).unwrap() {
Some(Do::MoveCursor) => {
text.cursor = text.index_at(cursor_position);
@@ -357,6 +402,7 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
}
Some(Do::StartSelection) => {
let x = text.index_at(cursor_position);
+ hist.last.cursor = x;
*state.sel() = text.extend_selection_to(
x,
text.cursor..text.cursor,
@@ -367,6 +413,14 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
}
}
Event::WindowEvent {
+ event:
+ WindowEvent::MouseInput {
+ button: MouseButton::Left,
+ ..
+ },
+ ..
+ } => unsafe { CLICKING = false },
+ Event::WindowEvent {
window_id: _,
event:
WindowEvent::MouseWheel {
@@ -425,17 +479,20 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
save!();
}
Some(Do::Edit) => {
+ hist.test_push(&text);
handle2(event.logical_key, &mut text);
text.scroll_to_cursor();
hist.record(&text);
}
Some(Do::Undo) => {
hist.test_push(&text);
- hist.undo().map(|x| x.apply(&mut text, false));
+ hist.undo(&mut text);
+ bar.last_action = "undid".to_string();
}
Some(Do::Redo) => {
hist.test_push(&text);
- hist.redo().map(|x| x.apply(&mut text, true));
+ hist.redo(&mut text);
+ bar.last_action = "redid".to_string();
}
Some(Do::Quit) => elwt.exit(),
Some(Do::StartSelection) => {
@@ -456,31 +513,35 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
text.scroll_to_cursor();
}
Some(Do::Insert((x, c))) => {
- hist.push(&text);
+ hist.push_if_changed(&text);
text.rope.remove(x.clone());
text.cursor = x.start;
text.setc();
text.insert_(c);
+ hist.push_if_changed(&text);
}
Some(Do::Delete(x)) => {
- hist.push(&text);
+ hist.push_if_changed(&text);
text.cursor = x.start;
text.rope.remove(x);
+ hist.push_if_changed(&text);
}
Some(Do::Copy(x)) => {
clipp::copy(text.rope.slice(x).to_string());
}
Some(Do::Cut(x)) => {
- hist.push(&text);
+ hist.push_if_changed(&text);
clipp::copy(
text.rope.slice(x.clone()).to_string(),
);
text.rope.remove(x.clone());
text.cursor = x.start;
+ hist.push_if_changed(&text);
}
Some(Do::Paste) => {
- hist.push(&text);
+ hist.push_if_changed(&text);
text.insert(&clipp::paste());
+ hist.push_if_changed(&text);
}
Some(
Do::MoveCursor | Do::ExtendSelectionToMouse,
@@ -583,6 +644,8 @@ Default => {
K(Key::Named(NamedKey::ArrowUp | NamedKey::ArrowLeft | NamedKey::ArrowDown | NamedKey::ArrowRight | NamedKey::Home | NamedKey::End) if shift()) => Selection(Range<usize> => 0..0) [StartSelection],
M(MouseButton => MouseButton::Left if shift()) => Selection(Range<usize> => 0..0) [StartSelection],
M(MouseButton => MouseButton::Left) => Default [MoveCursor],
+ C((usize, usize) => _ if unsafe { CLICKING }) => Selection(0..0) [StartSelection],
+ C(_) => Default,
K(_) => Default [Edit],
M(_) => Default,
},
@@ -591,6 +654,8 @@ Selection(x if shift()) => {
M(MouseButton => MouseButton::Left) => Selection(x) [ExtendSelectionToMouse],
},
Selection(x) => {
+ C(y if unsafe { CLICKING }) => Selection(x) [ExtendSelectionToMouse],
+ C(_) => Selection(x),
M(MouseButton => MouseButton::Left) => Default [MoveCursor],
K(Key::Named(NamedKey::Backspace)) => Default [Delete(Range<usize> => x)],
K(Key::Character(y) if y == "x" && ctrl()) => Default [Cut(Range<usize> => x)],
@@ -606,16 +671,24 @@ InputFname(t) => K(Key::Named(NamedKey::Enter)) => Default [SaveTo(String => t.r
InputFname(t) => K(k) => InputFname(TextArea => handle(k, t)),
}
#[test]
-fn x() {
- let d = diff_match_patch_rs::DiffMatchPatch::new();
- let diffs = d
- .diff_main::<Efficient>("previous state th", "previous state")
- .unwrap();
- dbg!(&diffs);
-
- let patch = d.patch_make(PatchInput::new_diffs(&diffs)).unwrap();
- let x = d.patch_apply(&patch, "previous state th").unwrap().0;
- assert_eq!(x, "previous state");
- // diff = -th
- // undo = previous state
+fn history_test() {
+ let mut t = TextArea::default();
+ let mut h = Hist {
+ history: vec![],
+ redo_history: vec![],
+ last: t.clone(),
+ last_edit: Instant::now(),
+ changed: false,
+ };
+ t.insert("echo");
+ h.push(&t);
+ t.insert(" test");
+ h.push(&t);
+ h.undo(&mut t);
+ h.redo(&mut t);
+ h.undo(&mut t);
+ t.insert(" good");
+ h.push(&t);
+ h.undo(&mut t);
+ assert_eq!(t.rope.to_string(), "echo");
}