better textedit and other stuff
This commit is contained in:
1
bin/dune
1
bin/dune
@ -1,6 +1,7 @@
|
|||||||
(executables
|
(executables
|
||||||
(names main example lumppile)
|
(names main example lumppile)
|
||||||
(modes byte)
|
(modes byte)
|
||||||
|
(link_flags (-linkall))
|
||||||
(libraries komm tsdl tgls.tgles2 wall irmin-unix compiler-libs.common compiler-libs.bytecomp compiler-libs.toplevel ocaml-compiler-libs.common ocaml-compiler-libs.toplevel zed))
|
(libraries komm tsdl tgls.tgles2 wall irmin-unix compiler-libs.common compiler-libs.bytecomp compiler-libs.toplevel ocaml-compiler-libs.common ocaml-compiler-libs.toplevel zed))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
117
bin/main.ml
117
bin/main.ml
@ -98,66 +98,62 @@ module Display = struct
|
|||||||
| Ok x -> x
|
| Ok x -> x
|
||||||
| Error (`Msg msg) -> failwith msg
|
| Error (`Msg msg) -> failwith msg
|
||||||
|
|
||||||
|
|
||||||
|
type keymod = Shift | Ctrl | Meta | Fn
|
||||||
type key = {
|
type key = {
|
||||||
char:char;
|
char:char;
|
||||||
uchar:CamomileLibrary.UChar.t;
|
uchar:CamomileLibrary.UChar.t;
|
||||||
keycode:Sdl.keycode;
|
keycode:Sdl.keycode;
|
||||||
scancode:Sdl.scancode;
|
scancode:Sdl.scancode;
|
||||||
shift:bool;
|
mods:keymod list}
|
||||||
ctrl:bool;
|
|
||||||
meta:bool;
|
|
||||||
fn:bool; }
|
|
||||||
type mouse = (int * int)
|
type mouse = (int * int)
|
||||||
type event = [ `Key_down of key
|
type event = [ `Key_down of key
|
||||||
| `Key_up of key
|
| `Key_up of key
|
||||||
|
| `Text_editing of string
|
||||||
|
| `Text_input of string
|
||||||
| `Mouse of mouse
|
| `Mouse of mouse
|
||||||
| `Quit
|
| `Quit
|
||||||
| `Fullscreen of bool
|
| `Fullscreen of bool
|
||||||
| `None ]
|
| `None ]
|
||||||
|
|
||||||
let prev_key = ref {char='\x00'; uchar=(CamomileLibrary.UChar.of_int 0);
|
let str_of_key k = Printf.sprintf "(char=%C;uchar=%C;keycode=%x;scancode=%x;name=%s;(%s%s%s%s))"
|
||||||
keycode=0; scancode=0;
|
k.char (CamomileLibrary.UChar.char_of k.uchar) k.keycode k.scancode
|
||||||
shift=false; ctrl=false; meta=false; fn=false}
|
(Sdl.get_key_name k.keycode) (if List.mem Shift k.mods then "shift" else "")
|
||||||
|
(if List.mem Ctrl k.mods then "ctrl" else "") (if List.mem Meta k.mods then "meta" else "")
|
||||||
|
(if List.mem Fn k.mods then " fn" else "")
|
||||||
|
|
||||||
let event_of_sdlevent ev =
|
let event_of_sdlevent ev =
|
||||||
match Sdl.Event.enum (Sdl.Event.get ev Sdl.Event.typ) with
|
match Sdl.Event.enum (Sdl.Event.get ev Sdl.Event.typ) with
|
||||||
|
| `Text_editing -> F.epr "event_of_sdlevent: `Text_editing\n\twindow_id=%d\n\ttext=%s\n\tstart=%d\n\tlength=%d@."
|
||||||
|
(Sdl.Event.get ev Sdl.Event.text_editing_window_id)
|
||||||
|
(Sdl.Event.get ev Sdl.Event.text_editing_text)
|
||||||
|
(Sdl.Event.get ev Sdl.Event.text_editing_start)
|
||||||
|
(Sdl.Event.get ev Sdl.Event.text_editing_length); `None
|
||||||
|
|
||||||
|
| `Text_input -> `Text_input (Sdl.Event.get ev Sdl.Event.text_input_text)
|
||||||
| `Key_down | `Key_up as w ->
|
| `Key_down | `Key_up as w ->
|
||||||
let km = Sdl.Event.get ev Sdl.Event.keyboard_keymod in
|
let km = Sdl.Event.get ev Sdl.Event.keyboard_keymod in
|
||||||
let keycode = Sdl.Event.get ev Sdl.Event.keyboard_keycode in
|
let keycode = Sdl.Event.get ev Sdl.Event.keyboard_keycode in
|
||||||
let uchar = CamomileLibrary.UChar.of_int (if keycode land Sdl.K.scancode_mask > 0 then 0 else keycode) in
|
let uchar = CamomileLibrary.UChar.of_int (if keycode land Sdl.K.scancode_mask > 0 then 0 else keycode) in
|
||||||
|
let mods = List.filter_map (fun (m, v) -> if (km land m)>0 then Some v else None)
|
||||||
|
Sdl.Kmod.[(shift, Shift); (ctrl, Ctrl); (alt, Meta); (gui, Fn);] in
|
||||||
let k = { char=(UChar.char_of uchar); uchar; keycode;
|
let k = { char=(UChar.char_of uchar); uchar; keycode;
|
||||||
scancode=Sdl.Event.get ev Sdl.Event.keyboard_scancode;
|
scancode=Sdl.Event.get ev Sdl.Event.keyboard_scancode; mods} in
|
||||||
shift = (km land Sdl.Kmod.shift)>0;
|
|
||||||
ctrl = (km land Sdl.Kmod.ctrl)>0;
|
|
||||||
meta = (km land Sdl.Kmod.alt)>0;
|
|
||||||
fn = (km land Sdl.Kmod.gui)>0; } in
|
|
||||||
(match w with `Key_down -> F.epr "key_down: " | `Key_up -> F.epr "key_up: ");
|
(match w with `Key_down -> F.epr "key_down: " | `Key_up -> F.epr "key_up: ");
|
||||||
F.epr "keycode=%x uchar=%C scancode=%x keyname=%s (%s %s %s %s)\n" keycode
|
F.epr "%s@." (str_of_key k);
|
||||||
(CamomileLibrary.UChar.char_of k.uchar) k.scancode
|
let repeat = (Sdl.Event.get ev Sdl.Event.keyboard_repeat) in
|
||||||
(Sdl.get_key_name keycode)
|
F.epr "\tkeyboard_repeat=%d\n" repeat ;
|
||||||
(if k.shift then " shift" else "")
|
if repeat < 1 then (match w with `Key_down -> `Key_down k | `Key_up -> `Key_up k) else `None
|
||||||
(if k.ctrl then " ctrl" else "")
|
|
||||||
(if k.meta then " meta" else "")
|
|
||||||
(if k.fn then " fn" else "");
|
|
||||||
(match w with `Key_down -> `Key_down k | `Key_up -> `Key_up k)
|
|
||||||
| `Mouse_motion ->
|
| `Mouse_motion ->
|
||||||
let _, mouse_xy = Tsdl.Sdl.get_mouse_state () in `Mouse mouse_xy
|
let _, mouse_xy = Tsdl.Sdl.get_mouse_state () in `Mouse mouse_xy
|
||||||
| `Quit -> F.epr "Quit Event\n"; `Quit
|
| `Quit -> F.epr "Quit Event\n"; `Quit
|
||||||
| _ -> F.epr "Unknown Event@." ; `None
|
| _ -> F.epr "Unknown Event@." ; `None
|
||||||
|
|
||||||
let str_of_scancode = Sdl.get_key_name
|
let key_up : Sdl.keycode = 0x40000052
|
||||||
let key_shift_map =
|
let key_down : Sdl.keycode = 0x40000051
|
||||||
[('1','!');('2','@');('3','#');('4','$');('5','%');
|
let key_left : Sdl.keycode = 0x40000050
|
||||||
('6','^');('7','&');('8','*');('9','(');('0',')');
|
let key_right : Sdl.keycode = 0x4000004f
|
||||||
('`','~');('-','_');('+','+');('[','{');(']','}');
|
|
||||||
('\\','|');(';',':');('\'','"');(',','<');('.','>');
|
|
||||||
('/','?')]
|
|
||||||
|
|
||||||
let key_to_uchar k : UChar.t =
|
|
||||||
match (List.assoc_opt k.char key_shift_map), k with
|
|
||||||
| _, {char='\x00'; _} -> (UChar.of_char '\x00')
|
|
||||||
| Some k, {shift=true; _} -> (UChar.of_char k)
|
|
||||||
| None, {shift=true; _} -> (UChar.of_char (Char.uppercase_ascii k.char))
|
|
||||||
| _, {shift=false; _} -> k.uchar
|
|
||||||
|
|
||||||
let handle_keyevents (el:event list) f = List.iter f el
|
let handle_keyevents (el:event list) f = List.iter f el
|
||||||
|
|
||||||
@ -177,7 +173,7 @@ module Display = struct
|
|||||||
mutable quit: bool;
|
mutable quit: bool;
|
||||||
mutable fullscreen: bool; }
|
mutable fullscreen: bool; }
|
||||||
|
|
||||||
let ticks () = (Int32.to_float (Sdl.get_ticks ())) /. 1000.0
|
let ticks () = (Int32.to_float (Sdl.get_ticks ())) /. 1000.
|
||||||
|
|
||||||
let on_failure ~cleanup result = begin
|
let on_failure ~cleanup result = begin
|
||||||
match result with
|
match result with
|
||||||
@ -192,6 +188,7 @@ module Display = struct
|
|||||||
Sdl.create_window ~w ~h title
|
Sdl.create_window ~w ~h title
|
||||||
Sdl.Window.(opengl + allow_highdpi + resizable (*+ input_grabbed*))
|
Sdl.Window.(opengl + allow_highdpi + resizable (*+ input_grabbed*))
|
||||||
>>= fun sdl_win ->
|
>>= fun sdl_win ->
|
||||||
|
Sdl.set_window_title sdl_win title;
|
||||||
ignore (Sdl.gl_set_swap_interval (-1));
|
ignore (Sdl.gl_set_swap_interval (-1));
|
||||||
ignore (Sdl.gl_set_attribute Sdl.Gl.stencil_size 1);
|
ignore (Sdl.gl_set_attribute Sdl.Gl.stencil_size 1);
|
||||||
on_failure (
|
on_failure (
|
||||||
@ -223,9 +220,9 @@ module Display = struct
|
|||||||
else Sdl.Window.windowed)
|
else Sdl.Window.windowed)
|
||||||
: _ result)); None
|
: _ result)); None
|
||||||
| `Key_up a -> Some (`Key_up a)
|
| `Key_up a -> Some (`Key_up a)
|
||||||
| `Key_down _ -> (*Some (`Key_up a)*) None
|
| `Key_down a -> Some (`Key_down a)
|
||||||
| `Mouse a -> Some (`Mouse a)
|
| `Mouse a -> Some (`Mouse a)
|
||||||
| _ -> None
|
| a -> Some a
|
||||||
(*| a -> Some a*)) !el;
|
(*| a -> Some a*)) !el;
|
||||||
if (List.length !el) > 0 then begin
|
if (List.length !el) > 0 then begin
|
||||||
F.epr "Passing in %d events\n" (List.length !el);
|
F.epr "Passing in %d events\n" (List.length !el);
|
||||||
@ -245,7 +242,7 @@ module Display = struct
|
|||||||
let width = float width and height = float height in
|
let width = float width and height = float height in
|
||||||
Wall.Renderer.render frame.wall ~width ~height image;
|
Wall.Renderer.render frame.wall ~width ~height image;
|
||||||
Sdl.gl_swap_window frame.sdl_win;
|
Sdl.gl_swap_window frame.sdl_win;
|
||||||
F.epr "event loop took %0.2fms?\n" (ticks () -. tstart); Ok () end
|
F.epr "event loop took %0.6f seconds\n" (ticks () -. tstart); Ok () end
|
||||||
else Ok ()
|
else Ok ()
|
||||||
|
|
||||||
let run frame render () =
|
let run frame render () =
|
||||||
@ -314,7 +311,6 @@ let pane_vbox (subpanes:Display.pane list) (so:Display.state) =
|
|||||||
List.fold_left
|
List.fold_left
|
||||||
(fun (sp, (_, ip)) (pane:Display.pane) ->
|
(fun (sp, (_, ip)) (pane:Display.pane) ->
|
||||||
let sr, (br, ir) = pane sp in
|
let sr, (br, ir) = pane sp in
|
||||||
F.epr "pane_vbox: %s\n" (str_of_box br);
|
|
||||||
let _, (_, sir) = path_box (Color.v 0.125 0.125 1.0 0.125) br sp in
|
let _, (_, sir) = path_box (Color.v 0.125 0.125 1.0 0.125) br sp in
|
||||||
({sr with box = (Box2.of_pts (Box2.tl_pt br) (Box2.max sp.box))}, (br, Image.seq [ ip; sir; ir])))
|
({sr with box = (Box2.of_pts (Box2.tl_pt br) (Box2.max sp.box))}, (br, Image.seq [ ip; sir; ir])))
|
||||||
(so, (so.box, Image.empty)) subpanes
|
(so, (so.box, Image.empty)) subpanes
|
||||||
@ -370,7 +366,6 @@ type Format.stag += Color_bg of Wall.color
|
|||||||
type Format.stag += Color_fg of Wall.color
|
type Format.stag += Color_fg of Wall.color
|
||||||
type Format.stag += Cursor of Wall.color
|
type Format.stag += Cursor of Wall.color
|
||||||
let draw_pp height fpp (s:Display.state) =
|
let draw_pp height fpp (s:Display.state) =
|
||||||
F.epr "draw_pp: %s\n" (str_of_box s.box);
|
|
||||||
let node, sc, box = ref I.empty, ref s, ref Box2.zero in
|
let node, sc, box = ref I.empty, ref s, ref Box2.zero in
|
||||||
let push (s, (b, i)) = node := I.stack !node i; sc := s; box := b in
|
let push (s, (b, i)) = node := I.stack !node i; sc := s; box := b in
|
||||||
let f = Text.Font.make ~size:height (Lazy.force font_sans) in
|
let f = Text.Font.make ~size:height (Lazy.force font_sans) in
|
||||||
@ -442,27 +437,27 @@ let make_textedit () = let z = Zed_edit.create () in {ze = z; zc = Zed_edit.new_
|
|||||||
let draw_textedit (te:textedit) height (s:Display.state) =
|
let draw_textedit (te:textedit) height (s:Display.state) =
|
||||||
let ctx = Zed_edit.context te.ze te.zc in
|
let ctx = Zed_edit.context te.ze te.zc in
|
||||||
List.iter (function
|
List.iter (function
|
||||||
| `Key_up (k:Display.key) ->
|
| `Key_down (k:Display.key) ->
|
||||||
(match k with
|
(match k with
|
||||||
| {keycode=0x40000052; _}(*up*) -> ignore (Zed_edit.prev_line ctx)
|
| {keycode=kc;mods=[]; _} when kc = Display.key_up -> Zed_edit.prev_line ctx
|
||||||
| {keycode=0x40000051; _}(*down*) -> ignore (Zed_edit.next_line ctx)
|
| {keycode=kc;mods=[]; _} when kc = Display.key_down -> Zed_edit.next_line ctx
|
||||||
| {keycode=0x40000050; _}(*left*) -> ignore (Zed_edit.prev_char ctx)
|
| {keycode=kc;mods=[]; _} when kc = Display.key_left -> Zed_edit.prev_char ctx
|
||||||
| {keycode=0x4000004f; _}(*right*)-> ignore (Zed_edit.next_char ctx)
|
| {keycode=kc;mods=[]; _} when kc = Display.key_right-> Zed_edit.next_char ctx
|
||||||
| {char='\r'; ctrl=false; shift=false; meta=false; fn=false; _} -> Zed_edit.newline ctx
|
| {char='\r'; mods=[]; _} -> Zed_edit.newline ctx
|
||||||
| {char='b'; ctrl=true; shift=false; meta=false; fn=false; _} -> Zed_edit.prev_char ctx
|
| {char='b'; mods=[Ctrl]; _} -> Zed_edit.prev_char ctx
|
||||||
| {char='f'; ctrl=true; shift=false; meta=false; fn=false; _} -> Zed_edit.next_char ctx
|
| {char='f'; mods=[Ctrl]; _} -> Zed_edit.next_char ctx
|
||||||
| {char='a'; ctrl=true; shift=false; meta=false; fn=false; _} -> Zed_edit.goto_bol ctx
|
| {char='a'; mods=[Ctrl]; _} -> Zed_edit.goto_bol ctx
|
||||||
| {char='e'; ctrl=true; shift=false; meta=false; fn=false; _} -> Zed_edit.goto_eol ctx
|
| {char='e'; mods=[Ctrl]; _} -> Zed_edit.goto_eol ctx
|
||||||
| {char='d'; ctrl=true; shift=false; meta=false; fn=false; _} -> Zed_edit.remove_next ctx 1
|
| {char='d'; mods=[Ctrl]; _} -> Zed_edit.remove_next ctx 1
|
||||||
| {char='d'; ctrl=false; shift=false; meta=true; fn=false; _} -> Zed_edit.kill_next_word ctx
|
| {char='d'; mods=[Meta]; _} -> Zed_edit.kill_next_word ctx
|
||||||
| {char='\b'; ctrl=false; shift=false; meta=false; fn=false; _} -> Zed_edit.remove_prev ctx 1
|
| {char='\b'; mods=[]; _} -> Zed_edit.remove_prev ctx 1
|
||||||
| {char='\b'; ctrl=false; shift=false; meta=true; fn=false; _} -> Zed_edit.kill_prev_word ctx
|
| {char='\b'; mods=[Meta]; _} -> Zed_edit.kill_prev_word ctx
|
||||||
| {char='\t'; ctrl=false; shift=false; meta=false; fn=false; _} -> Zed_edit.insert_char ctx (CamomileLibrary.UChar.of_char '\t')
|
| {char='\t'; mods=[]; _} -> Zed_edit.insert_char ctx (CamomileLibrary.UChar.of_char '\t')
|
||||||
| {char='k'; ctrl=true; shift=false; meta=false; fn=false; _} -> Zed_edit.kill_next_line ctx
|
| {char='k'; mods=[Ctrl]; _} -> Zed_edit.kill_next_line ctx
|
||||||
| _ ->
|
| _ -> ())
|
||||||
let c = Display.key_to_uchar k in
|
| `Key_up _ -> ()
|
||||||
if Zed_char.is_printable c then Zed_edit.insert_char ctx (Display.key_to_uchar k); ())
|
| `Text_input s -> F.epr "draw_textedit: `Text_input %s@." s;
|
||||||
| `Key_down _ -> ()
|
Zed_edit.insert ctx (Zed_rope.of_string (Zed_string.of_utf8 s)); ()
|
||||||
| _ -> ()) s.events;
|
| _ -> ()) s.events;
|
||||||
draw_pp height (fun pp ->
|
draw_pp height (fun pp ->
|
||||||
let zrb, zra = Zed_rope.break (Zed_edit.text te.ze) (Zed_cursor.get_position te.zc) in
|
let zrb, zra = Zed_rope.break (Zed_edit.text te.ze) (Zed_cursor.get_position te.zc) in
|
||||||
@ -518,7 +513,7 @@ let draw_top (t:top) height (s:Display.state) =
|
|||||||
| Some e -> e in
|
| Some e -> e in
|
||||||
Display.handle_keyevents s.events
|
Display.handle_keyevents s.events
|
||||||
(function
|
(function
|
||||||
| `Key_up {char='\r'; ctrl=true; shift=false; meta=false; fn=false; _} ->
|
| `Key_up {char='\r'; mods=[Ctrl]; _} ->
|
||||||
Buffer.clear t.res; eval (Format.formatter_of_buffer t.res) (str_of_textedit t.te);
|
Buffer.clear t.res; eval (Format.formatter_of_buffer t.res) (str_of_textedit t.te);
|
||||||
ignore (Lwt_main.run (Store.tree t.storeview.s >>= (fun tree ->
|
ignore (Lwt_main.run (Store.tree t.storeview.s >>= (fun tree ->
|
||||||
Store.Tree.add tree t.path (str_of_textedit t.te))));
|
Store.Tree.add tree t.path (str_of_textedit t.te))));
|
||||||
|
|||||||
Reference in New Issue
Block a user