···11open Notty
22open Lwd_utils
33+(* test comment *)
34module Log = (val Logs.src_log (Logs.Src.create "nottui"))
4556module Focus : sig
···264265end
265266266267module Ui = struct
268268+ (** convinience method to take a str and turn it into a unicode char*)
269269+ let make_uchar str =
270270+ let a = String.get_utf_8_uchar str 0 in
271271+ if a |> Uchar.utf_decode_is_valid
272272+ then a |> Uchar.utf_decode_uchar
273273+ else failwith "not a unicode string"
274274+ ;;
275275+276276+ module Border = struct
277277+ type style =
278278+ { tl : Uchar.t
279279+ ; tr : Uchar.t
280280+ ; bl : Uchar.t
281281+ ; br : Uchar.t
282282+ ; h : Uchar.t
283283+ ; v : Uchar.t
284284+ }
285285+286286+ let ascii =
287287+ { tl = make_uchar "+"
288288+ ; tr = make_uchar "+"
289289+ ; bl = make_uchar "+"
290290+ ; br = make_uchar "+"
291291+ ; h = make_uchar "-"
292292+ ; v = make_uchar "|"
293293+ }
294294+ ;;
295295+296296+ let unicode =
297297+ { tl = make_uchar "┌"
298298+ ; tr = make_uchar "┐"
299299+ ; bl = make_uchar "└"
300300+ ; br = make_uchar "┘"
301301+ ; h = make_uchar "─"
302302+ ; v = make_uchar "│"
303303+ }
304304+ let unicode_double =
305305+ { tl = make_uchar "╔"
306306+ ; tr = make_uchar "╗"
307307+ ; bl = make_uchar "╚"
308308+ ; br = make_uchar "╝"
309309+ ; h = make_uchar "═"
310310+ ; v = make_uchar "║"
311311+ }
312312+ let unicode_rounded =
313313+ { tl = make_uchar "╭"
314314+ ; tr = make_uchar "╮"
315315+ ; bl = make_uchar "╰"
316316+ ; br = make_uchar "╯"
317317+ ; h = make_uchar "─"
318318+ ; v = make_uchar "│"
319319+ }
320320+ ;;
321321+322322+ (** Convenience focused styles *)
323323+ let unicode_bold =
324324+ { tl = make_uchar "┏"
325325+ ; tr = make_uchar "┓"
326326+ ; bl = make_uchar "┗"
327327+ ; br = make_uchar "┛"
328328+ ; h = make_uchar "━"
329329+ ; v = make_uchar "┃"
330330+ }
331331+ ;;
332332+ end
333333+334334+ type border =
335335+ { attr : A.t
336336+ ; thick : int
337337+ ; pad_w : int (** left/right padding columns *)
338338+ ; pad_h : int (** top/bottom padding rows *)
339339+ ; style : Border.style
340340+ ; focus_attr : A.t option (** attribute when focused, None means use attr *)
341341+ ; focus_style : Border.style option (** style when focused, None means use style *)
342342+ ; label_top : string option (** Optional text shown in the top border *)
343343+ ; label_bottom : string option (** Optional text shown in the bottom border *)
344344+ }
345345+267346 type mouse_handler =
268347 x:int
269348 -> y:int
···407486 { vx : Interval.t
408487 ; vy : Interval.t
409488 ; image : image
489489+ ; focused : bool (** Whether the UI had focus when this cache was created. This is needed to adjust the bord style based on focus status *)
410490 }
411491412492 and desc =
···422502 | X of t * t
423503 | Y of t * t
424504 | Z of t * t
505505+ | Border of t * border
425506426507 let layout_spec t : layout_spec =
427508 { w = t.w; h = t.h; sw = t.sw; sh = t.sh; mw = t.mw; mh = t.mh }
···433514 let layout_stretch_height t = t.sh
434515 let layout_max_width t = t.mw
435516 let layout_max_height t = t.mh
436436- let cache : cache = { vx = Interval.zero; vy = Interval.zero; image = I.empty }
517517+ let cache : cache = { vx = Interval.zero; vy = Interval.zero; image = I.empty; focused = false }
437518438519 let empty : t =
439520 { w = 0
···595676 let zcat xs = Lwd_utils.reduce pack_z xs
596677 let has_focus t = Focus.has_focus t.focus
597678679679+ let border ?(thick = 1) ?pad ?pad_w ?pad_h
680680+ ?label_top ?label_bottom
681681+ ?(attr = A.empty) ?(style = Border.unicode)
682682+ ?focus_attr ?focus_style t =
683683+ (* Derive horizontal and vertical pad values *)
684684+ let pad_base = match pad with Some p -> p | None -> 0 in
685685+ let pad_w = match pad_w with Some pw -> pw | None -> pad_base in
686686+ let pad_h = match pad_h with Some ph -> ph | None -> pad_base in
687687+ let dw = 2 * (thick + pad_w) in
688688+ let dh = 2 * (thick + pad_h) in
689689+ { w = t.w + dw
690690+ ; h = t.h + dh
691691+ ; sw = t.sw
692692+ ; sh = t.sh
693693+ ; mw = t.mw + dw
694694+ ; mh = t.mh + dh
695695+ ; flags = t.flags
696696+ ; focus = t.focus
697697+ ; desc =
698698+ Border
699699+ ( t
700700+ , { attr
701701+ ; thick
702702+ ; pad_w
703703+ ; pad_h
704704+ ; style
705705+ ; focus_attr
706706+ ; focus_style
707707+ ; label_top
708708+ ; label_bottom
709709+ } )
710710+ ; sensor_cache = None
711711+ ; cache
712712+ }
713713+ ;;
714714+598715 let rec pp ppf t =
599716 Format.fprintf
600717 ppf
···627744 | Focus_area (n, _) -> Format.fprintf ppf "Focus_area (@[%a,@ _@])" pp n
628745 | Shift_area (n, _, _) -> Format.fprintf ppf "Shift_area (@[%a,@ _@])" pp n
629746 | Event_filter (n, _) -> Format.fprintf ppf "Event_filter (@[%a,@ _@])" pp n
747747+ | Border (n, _) -> Format.fprintf ppf "Border (@[%a,@ _@])" pp n
630748 | X (a, b) -> Format.fprintf ppf "X (@[%a,@ %a@])" pp a pp b
631749 | Y (a, b) -> Format.fprintf ppf "Y (@[%a,@ %a@])" pp a pp b
632750 | Z (a, b) -> Format.fprintf ppf "Z (@[%a,@ %a@])" pp a pp b
···646764 | X (a, b) | Y (a, b) | Z (a, b) ->
647765 f a;
648766 f b
649649- ;;
767767+ | Border (u, _) -> f u
650768end
651769652770type ui = Ui.t
···763881 let dx, rw = pack ~max:t.mw ~fixed:t.w ~stretch:t.sw sw (h (p1 g)) (h (p2 g)) in
764882 let dy, rh = pack ~max:t.mh ~fixed:t.h ~stretch:t.sh sh (v (p1 g)) (v (p2 g)) in
765883 update_sensors (ox + dx) (oy + dy) rw rh mw mh t
884884+ | Border (t, b) ->
885885+ let shift_x = b.thick + b.pad_w in
886886+ let shift_y = b.thick + b.pad_h in
887887+ let dw = 2 * shift_x in
888888+ let dh = 2 * shift_y in
889889+ update_sensors (ox + shift_x) (oy + shift_y) (sw - dw) (sh - dh) (mw - dw) (mh - dh) t
766890 | Shift_area (t, sx, sy) -> update_sensors (ox - sx) (oy - sy) sw sh mw mh t
767891 | X (a, b) ->
768892 let aw, bw = split ~a:a.w ~sa:a.sw ~b:b.w ~sb:b.sw ~mA:a.mw ~mB:b.mw sw in
···774898 update_sensors ox (oy + ah) sw bh mw mh b
775899 | Z (a, b) ->
776900 update_sensors ox oy sw sh mw mh a;
777777- update_sensors ox oy sw sh mw mh b)
901901+ update_sensors ox oy sw sh mw mh b
902902+)
778903 ;;
779904780905 (** goes through all focuses and attempts to resolve any that have changed*)
···805930 match t.desc with
806931 | Atom _ -> false
807932 | X (a, b) ->
808808- let aw, bw = split ~a:a.w ~sa:a.sw ~b:b.w ~sb:b.sw ~mA:a.mh ~mB:b.mh sw in
933933+ let aw, bw = split ~a:a.w ~sa:a.sw ~b:b.w ~sb:b.sw ~mA:a.mw ~mB:b.mw sw in
809934 if x - ox < aw then aux ox oy aw sh a else aux (ox + aw) oy bw sh b
810935 | Y (a, b) ->
811936 let ah, bh = split ~a:a.h ~sa:a.sh ~b:b.h ~sb:b.sh ~mA:a.mh ~mB:b.mh sh in
···829954 let dx, rw = pack ~max:t.mw ~fixed:t.w ~stretch:t.sw sw (h (p1 g)) (h (p2 g)) in
830955 let dy, rh = pack ~max:t.mh ~fixed:t.h ~stretch:t.sh sh (v (p1 g)) (v (p2 g)) in
831956 aux (ox + dx) (oy + dy) rw rh t
832832- | Event_filter (n, f) ->
957957+ | Border (t, b) ->
958958+ let shift_x = b.thick + b.pad_w in
959959+ let shift_y = b.thick + b.pad_h in
960960+ let dw = 2 * shift_x in
961961+ let dh = 2 * shift_y in
962962+ aux (ox + shift_x) (oy + shift_y) (sw - dw) (sh - dh) t
963963+ | Event_filter (t, f) ->
833964 (match f (`Mouse (`Press btn, (x, y), [])) with
834965 | `Handled -> true
835835- | `Unhandled -> aux ox oy sw sh n
966966+ | `Unhandled -> aux ox oy sw sh t
836967 | `Remap _ -> failwith "Cannot remap mouse events")
837968 in
838969 aux 0 0 w h t
···8811012 let same_size w h image = w = I.width image && h = I.height image
88210138831014 let rec render_node vx1 vy1 vx2 vy2 sw sh t : cache =
10151015+ let is_focused = has_focus t in
8841016 if
8851017 let cache = t.cache in
8861018 vx1 >= Interval.fst cache.vx
···8881020 && vx2 <= Interval.snd cache.vx
8891021 && vy2 <= Interval.snd cache.vy
8901022 && same_size sw sh cache.image
10231023+ && cache.focused = is_focused
8911024 then t.cache
8921025 else if vx2 < 0 || vy2 < 0 || sw < vx1 || sh < vy1
8931026 then (
8941027 let vx = Interval.make vx1 vx2
8951028 and vy = Interval.make vy1 vy2 in
896896- { vx; vy; image = I.void sw sh })
10291029+ { vx; vy; image = I.void sw sh; focused = is_focused })
8971030 else (
8981031 let cache =
8991032 match t.desc with
···9011034 { vx = Interval.make 0 sw
9021035 ; vy = Interval.make 0 sh
9031036 ; image = resize_canvas sw sh image
10371037+ ; focused = is_focused
9041038 }
9051039 | Size_sensor (desc, handler) ->
9061040 handler ~w:sw ~h:sh;
···9161050 let vx = Interval.make vx1 vx2
9171051 and vy = Interval.make vy1 vy2 in
9181052 let image = resize_canvas sw sh (I.crop ~l:sx ~t:sy cache.image) in
919919- { vx; vy; image }
10531053+ { vx; vy; image; focused = is_focused }
9201054 | X (a, b) ->
9211055 let aw, bw = split ~a:a.w ~sa:a.sw ~b:b.w ~sb:b.sw ~mA:a.mw ~mB:b.mw sw in
9221056 let ca = render_node vx1 vy1 vx2 vy2 aw sh a in
···9301064 (maxi (Interval.fst ca.vy) (Interval.fst cb.vy))
9311065 (mini (Interval.snd ca.vy) (Interval.snd cb.vy))
9321066 and image = resize_canvas sw sh (I.( <|> ) ca.image cb.image) in
933933- { vx; vy; image }
10671067+ { vx; vy; image; focused = is_focused }
9341068 | Y (a, b) ->
9351069 let ah, bh = split ~a:a.h ~sa:a.sh ~b:b.h ~sb:b.sh ~mA:a.mh ~mB:b.mh sh in
9361070 let ca = render_node vx1 vy1 vx2 vy2 sw ah a in
···9441078 (maxi (Interval.fst ca.vy) (Interval.fst cb.vy + ah))
9451079 (mini (Interval.snd ca.vy) (Interval.snd cb.vy + ah))
9461080 and image = resize_canvas sw sh (I.( <-> ) ca.image cb.image) in
947947- { vx; vy; image }
10811081+ { vx; vy; image; focused = is_focused }
9481082 | Z (a, b) ->
9491083 let ca = render_node vx1 vy1 vx2 vy2 sw sh a in
9501084 let cb = render_node vx1 vy1 vx2 vy2 sw sh b in
···9571091 (maxi (Interval.fst ca.vy) (Interval.fst cb.vy))
9581092 (mini (Interval.snd ca.vy) (Interval.snd cb.vy))
9591093 and image = resize_canvas sw sh (I.( </> ) cb.image ca.image) in
960960- { vx; vy; image }
10941094+ { vx; vy; image; focused = is_focused }
10951095+ | Border (t, b) ->
10961096+ let open Border in
10971097+ let open I in
10981098+ (*if the border is 0 we just render the content and pad it*)
10991099+ if b.thick = 0
11001100+ then (
11011101+ let shift_x = b.pad_w in
11021102+ let shift_y = b.pad_h in
11031103+ let rw = sw - (2 * shift_x) in
11041104+ let rh = sh - (2 * shift_y) in
11051105+ let c =
11061106+ render_node
11071107+ (vx1 - shift_x)
11081108+ (vy1 - shift_y)
11091109+ (vx2 - shift_x)
11101110+ (vy2 - shift_y)
11111111+ rw
11121112+ rh
11131113+ t
11141114+ in
11151115+ let padded_image =
11161116+ if b.pad_w = 0 && b.pad_h = 0
11171117+ then c.image
11181118+ else I.pad ~l:b.pad_w ~t:b.pad_h ~r:b.pad_w ~b:b.pad_h c.image
11191119+ in
11201120+ { vx = Interval.shift c.vx shift_x
11211121+ ; vy = Interval.shift c.vy shift_y
11221122+ ; image = resize_canvas sw sh padded_image
11231123+ ; focused = is_focused
11241124+ })
11251125+ else (
11261126+ let truncate_string len str =
11271127+ if String.length str > len then (
11281128+ if len <= 3 then "" else String.sub str 0 (len - 3) ^ "..."
11291129+ ) else str
11301130+ in
11311131+ let make_label max_w txt =
11321132+ let txt = truncate_string (max_w - 2) txt in
11331133+ I.strf " %s " txt
11341134+ in
11351135+ (* Determine shifts and inner area size *)
11361136+ let shift_x = b.thick + b.pad_w in
11371137+ let shift_y = b.thick + b.pad_h in
11381138+11391139+ let rw = sw - 2 * shift_x in
11401140+ let rh = sh - 2 * shift_y in
11411141+11421142+ let c =
11431143+ render_node
11441144+ (vx1 - shift_x)
11451145+ (vy1 - shift_y)
11461146+ (vx2 - shift_x)
11471147+ (vy2 - shift_y)
11481148+ rw
11491149+ rh
11501150+ t
11511151+ in
11521152+11531153+ (* Select attributes and style based on focus state *)
11541154+ let attr =
11551155+ if is_focused then Option.value ~default:b.attr b.focus_attr else b.attr
11561156+ in
11571157+ let style =
11581158+ if is_focused then Option.value ~default:b.style b.focus_style else b.style
11591159+ in
11601160+11611161+ (* Total interior dims inside border glyphs (content + padding) *)
11621162+ let inner_w = rw + (2 * b.pad_w) in
11631163+ let inner_h = rh + (2 * b.pad_h) in
11641164+11651165+ (* border glyph primitives *)
11661166+ let horiz = I.uchar attr style.h inner_w 1 in
11671167+ let vert h = I.uchar attr style.v 1 h in
11681168+11691169+ (* pad content *)
11701170+ let padded_image =
11711171+ if b.pad_w = 0 && b.pad_h = 0 then c.image
11721172+ else I.pad ~l:b.pad_w ~t:b.pad_h ~r:b.pad_w ~b:b.pad_h c.image
11731173+ in
11741174+11751175+ (* Build top border, optionally with label. *)
11761176+ let frame_top_base =
11771177+ I.(uchar attr style.tl 1 1 <|> horiz <|> uchar attr style.tr 1 1)
11781178+ in
11791179+ let frame_top =
11801180+ match b.label_top with
11811181+ | None -> frame_top_base
11821182+ | Some txt ->
11831183+ let lbl = make_label inner_w txt in
11841184+ let lbl =
11851185+ if I.width lbl > inner_w - 2 then I.empty else I.hpad 2 0 lbl
11861186+ in
11871187+ if I.width lbl = 0 then frame_top_base else I.zcat [ lbl; frame_top_base; lbl ]
11881188+ in
11891189+11901190+ (* Build bottom border, optionally with label. *)
11911191+ let frame_bot_base =
11921192+ I.(uchar attr style.bl 1 1 <|> horiz <|> uchar attr style.br 1 1)
11931193+ in
11941194+ let frame_bot =
11951195+ match b.label_bottom with
11961196+ | None -> frame_bot_base
11971197+ | Some txt ->
11981198+ let lbl = make_label inner_w txt in
11991199+ let lbl_width = I.width lbl in
12001200+ let lbl =
12011201+ if lbl_width > inner_w - 2 then I.empty
12021202+ else I.hpad (inner_w - lbl_width - 1) 0 lbl
12031203+ in
12041204+ if I.width lbl = 0 then frame_bot_base else I.zcat [ lbl; frame_bot_base; lbl ]
12051205+ in
12061206+12071207+ let frame_mid = I.(vert inner_h <|> padded_image <|> vert inner_h) in
12081208+ let frame = I.(frame_top <-> frame_mid <-> frame_bot) in
12091209+12101210+ { vx = Interval.shift c.vx shift_x
12111211+ ; vy = Interval.shift c.vy shift_y
12121212+ ; image = resize_canvas sw sh frame
12131213+ ; focused = is_focused
12141214+ })
9611215 | Resize (t, g, bg) ->
9621216 let open Gravity in
9631217 let dx, rw = pack ~max:t.mw ~fixed:t.w ~stretch:t.sw sw (h (p1 g)) (h (p2 g)) in
···9671221 let image = if bg != A.empty then I.(image </> char bg ' ' sw sh) else image in
9681222 let vx = Interval.shift c.vx dx in
9691223 let vy = Interval.shift c.vy dy in
970970- { vx; vy; image }
12241224+ { vx; vy; image; focused = is_focused }
9711225 | Event_filter (t, _f) -> render_node vx1 vy1 vx2 vy2 sw sh t
9721226 in
9731227 t.cache <- cache;
···10141268 | Permanent_sensor (t, _)
10151269 | Shift_area (t, _, _)
10161270 | Resize (t, _, _) -> iter (t :: tl)
12711271+ | Border (t, _) -> iter (t :: tl)
10171272 | Event_filter (t, f) ->
10181273 (match f (`Key key) with
10191274 | `Unhandled -> iter (t :: tl)
···11111366 if Focus.has_focus a.focus
11121367 then dispatch_focus a dir
11131368 else dispatch_focus b dir || dispatch_focus a dir
13691369+ | Border (t, _) -> dispatch_focus t dir
11141370 ;;
1115137111161372 let rec dispatch_key st key =
+30
forks/nottui/lib/nottui/nottui_main.mli
···107107 (** Printing UI element *)
108108 val pp : Format.formatter -> t -> unit
109109110110+ module Border : sig
111111+ type style = { tl:Uchar.t;tr:Uchar.t;bl:Uchar.t;br:Uchar.t;h:Uchar.t;v:Uchar.t }
112112+ val ascii : style
113113+ val unicode : style
114114+ val unicode_double : style
115115+ val unicode_rounded : style
116116+ val unicode_bold : style
117117+ end
118118+110119 (** {1 Layout specifications} *)
111120112121 (** The type of layout specifications.
···268277 val permanent_sensor : frame_sensor -> t -> t
269278270279 (** {1 Composite images} *)
280280+281281+ (** Add a border around a UI element.
282282+ - [thick]: thickness of the border (default 1).
283283+ - [attr]: attributes for the border characters (default empty).
284284+ - [style]: the characters to use for drawing the border (default [unicode]).
285285+ - [focus_attr]: attributes for the border when focused (default [attr]).
286286+ - [focus_style]: border style when focused (default [style]).
287287+ bounds, otherwise it is drawn outside, increasing the element's size. *)
288288+ val border
289289+ : ?thick:int
290290+ -> ?pad:int
291291+ -> ?pad_w:int
292292+ -> ?pad_h:int
293293+ -> ?label_top:string
294294+ -> ?label_bottom:string
295295+ -> ?attr:A.t
296296+ -> ?style:Border.style
297297+ -> ?focus_attr:A.t
298298+ -> ?focus_style:Border.style
299299+ -> t
300300+ -> t
271301272302 (** Override the layout specification of the ui with provided [w](width), [h](height),
273303 [sw](stretch width) or [sh](stretch height)
+1-5
forks/nottui/lib/nottui/widgets/border_box.mli
···11111212(** Creates a bordered box around the given [input] widget. This box will change colour when focused
13131414- @param scaling
1515- Controls how the input widget is sized within the border box. Can be:
1616- - [`Static] - The input widget is not resized.
1717- - [`Expand sw] - The input widget is allowed to expand to fill the available space, with a stretch width [sw].
1818- - [`Shrinkable (min_width, sw)] - The input widget is allowed to shrink to a minimum width of [min_width], and expand with a stretch width [sw].
1414+1915 @param pad The padding around the input widget within the border box.
2016 @param pad_w The horizontal padding around the input widget.
2117 @param pad_h The vertical padding around the input widget.
+8-1
jj_tui/widget-test/main.ml
···1818let w_0 =
1919 W.hbox
2020 [
2121+ Ui.border ~thick:2 ~style:Ui.Border.unicode ~label_top:"top" (Ui.vcat [W.string "hi this is a ui element with a\n border"; W.string "hi"])|>Lwd.pure;
2222+ Ui.border ~thick:0 ~pad_w:2 ~pad_h:1 ~style:Ui.Border.unicode_double ~label_bottom:"bottom" (Ui.vcat [W.string "hi this is a ui element with a\n border"; W.string "hi"])|>Lwd.pure;
2323+ Ui.border ~thick:1 ~style:Ui.Border.unicode_rounded ~label_top:"top" ~label_bottom:"bottom" (Ui.vcat [W.string "hi this is a ui element with a\n border"; W.string "hi"])|>Lwd.pure;
2424+2525+ Ui.border ~focus_attr: (A.fg A.red) ~focus_style:Ui.Border.unicode_double ~thick: 2 ~pad_w:2 ~pad_h:1 ~style:Ui.Border.unicode (Ui.vcat [W.string "hi this is a ui element with a\n border"; W.string "hi"])|>Lwd.pure;
2626+2727+ W.Box.box ~pad_w:2 ~pad_h:1 (Ui.vcat [W.string "hi this is a ui element with an\n old style border box"; W.string "hi"]|>Lwd.pure);
2128 (* pString " |" *)
2229 (* ; (let og = *)
2330 (* Ui.vcat *)
···3340 (* |>$ Ui.resize ~sh:1 ~mh:1000 *)
3441 (* |> W.size_logger) *)
3542 (* ; pString "| " *)
3636- test_input
4343+ test_input|>$ Ui.border ~focus_attr: (A.fg A.red) ~focus_style:Ui.Border.unicode_double ~thick:1 ~pad:1 ~style:Ui.Border.unicode
3744 ]
3845;;
3946
+59
widget-test/main.ml
···11+let test_input=
22+ let inp_var =("hi there",5)|>Lwd.var in
33+ let inp_text= inp_var|>Lwd.get in
44+55+ W.edit_field inp_text ~on_change:(fun x->Lwd.set inp_var x) ~on_submit:(fun x->())
66+77+let test_focused_border =
88+ let focus = Focus.make () in
99+ let content = W.string "Click to focus this border" in
1010+ content
1111+ |> Lwd.pure
1212+ |> Lwd.map ~f:(fun ui ->
1313+ ui
1414+ |> Ui.keyboard_area ~focus:(Focus.status focus) (fun _ -> `Unhandled)
1515+ |> Ui.border
1616+ ~thick:1
1717+ ~pad_w:2
1818+ ~pad_h:1
1919+ ~attr:(A.fg A.white)
2020+ ~style:Ui.Border.unicode
2121+ ~focus_attr:(A.fg A.blue)
2222+ ~focus_style:Ui.Border.unicode_bold
2323+ |> Ui.mouse_area (fun ~x:_ ~y:_ _ ->
2424+ Focus.request focus;
2525+ `Handled))
2626+2727+let w_0 =
2828+ W.vbox
2929+ [
3030+ W.hbox
3131+ [
3232+ Ui.border ~thick:1 ~style:Ui.Border.unicode (Ui.vcat [W.string "hi this is a ui element with a\n border"; W.string "hi"])|>Lwd.pure;
3333+ Ui.border ~thick:1 ~style:Ui.Border.unicode_double (Ui.vcat [W.string "hi this is a ui element with a\n border"; W.string "hi"])|>Lwd.pure;
3434+ Ui.border ~thick:0 ~style:Ui.Border.unicode_rounded (Ui.vcat [W.string "hi this is a ui element with a\n border"; W.string "hi"])|>Lwd.pure;
3535+3636+ Ui.border ~thick: 2 ~pad_w:2 ~pad_h:1 ~style:Ui.Border.unicode (Ui.vcat [W.string "hi this is a ui element with a\n border"; W.string "hi"])|>Lwd.pure;
3737+3838+ W.Box.box ~pad_w:2 ~pad_h:1 (Ui.vcat [W.string "hi this is a ui element with an\n old style border box"; W.string "hi"]|>Lwd.pure);
3939+ (* pString " |" *)
4040+ (* ; (let og = *)
4141+ (* Ui.vcat *)
4242+ (* [ *)
4343+ (* W.string "123456789000000000000000000000000000000000000000000000000000end" *)
4444+ (* ; W.string "123456789000000000000000000000000000000000000000000000000000end" *)
4545+ (* ] *)
4646+ (* in *)
4747+ (* og *)
4848+ (* |> Lwd.pure *)
4949+ (* |> W.Scroll.area *)
5050+ (* |> W.Box.box *)
5151+ (* |>$ Ui.resize ~sh:1 ~mh:1000 *)
5252+ (* |> W.size_logger) *)
5353+ (* ; pString "| " *)
5454+ test_input|>$ Ui.border ~thick:1 ~pad:1 ~style:Ui.Border.unicode
5555+ ]
5656+ ; W.string " " |> Lwd.pure
5757+ ; W.string "Test focused border (click to focus):" |> Lwd.pure
5858+ ; test_focused_border
5959+ ]