From a0974323c4ba279aaf93b95e949fbf89b93f2b04 Mon Sep 17 00:00:00 2001 From: Yatao Li Date: Fri, 10 Sep 2021 19:22:52 +0800 Subject: [PATCH] sign indicators for scrollbar OK! --- ViewModels/GridViewModel.fs | 17 +++++++++-- Views/Grid.xaml.fs | 56 ++++++++++++++++++++++++++----------- def.fs | 20 +++++++++++++ fvim.vim | 15 ++++++++++ model.fs | 15 ++++++++++ 5 files changed, 104 insertions(+), 19 deletions(-) diff --git a/ViewModels/GridViewModel.fs b/ViewModels/GridViewModel.fs index 97c3505..84ab4f5 100644 --- a/ViewModels/GridViewModel.fs +++ b/ViewModels/GridViewModel.fs @@ -78,6 +78,7 @@ and GridViewModel(_gridid: int, ?_parent: GridViewModel, ?_gridsize: GridSize) a let mutable m_scrollbar_row = 0 let mutable m_scrollbar_col = 0 let mutable m_scrollbar_linecount = 0 + let mutable m_signs = [||] let m_gridComparer = GridViewModel.MakeGridComparer() :> IComparer let raiseInputEvent id e = m_input_ev.Trigger(id, e) @@ -397,6 +398,7 @@ and GridViewModel(_gridid: int, ?_parent: GridViewModel, ?_gridsize: GridSize) a | PopupMenuHide -> hidePopupMenu () | WinExternalPos(_,win) -> setWinExternalPos win | WinViewport(id, win, top, bot, row, col, lc) -> setWinViewport win top bot row col lc + | SignUpdate(bufnr, signs) -> if bufnr = m_bufnr then m_signs <- signs | x -> trace _gridid "unimplemented command: %A" x let fontConfig() = @@ -476,6 +478,7 @@ and GridViewModel(_gridid: int, ?_parent: GridViewModel, ?_gridsize: GridSize) a ) rpc.register.notify "OnBufWinEnter" this.OnBufWinEnter + rpc.register.notify "OnSignUpdate" this.OnSignUpdate ] interface IGridUI with @@ -625,12 +628,21 @@ and GridViewModel(_gridid: int, ?_parent: GridViewModel, ?_gridsize: GridSize) a // TODO mark more precisely? markDirty oldRegion - member __.OnBufWinEnter [| String(bufnr); ObjArray(wins) |] = - let bufnr = int bufnr + member __.OnBufWinEnter [| bufnr; ObjArray(wins) |] = + let bufnr = + match bufnr with + | String bufnr -> int bufnr + | Integer32 bufnr -> bufnr if Array.exists (function | Integer32(w) when w = m_winhnd -> true | _ -> false) wins then trace _gridid "bufnr updated to %d" bufnr m_bufnr <- bufnr + member __.OnSignUpdate [| Integer32 bufnr; signs |] = + if bufnr <> m_bufnr then () + else + let signs = parseBufferSignPlacements signs + trace _gridid "OnSignUpdate: my = %d bufnr = %d signs = %A" m_bufnr bufnr signs + (******************* Exposed properties ***********************) member __.Item with get(row, col) = m_gridbuffer.[row, col] @@ -695,6 +707,7 @@ and GridViewModel(_gridid: int, ?_parent: GridViewModel, ?_gridsize: GridSize) a member __.ScrollbarData = m_scrollbar_top,m_scrollbar_bot,m_scrollbar_row,m_scrollbar_col,m_scrollbar_linecount member __.IsFloat = m_is_float member __.IsMsg = m_is_msg + member __.Signs = m_signs static member MakeGridComparer() = { new IComparer with diff --git a/Views/Grid.xaml.fs b/Views/Grid.xaml.fs index 4d4beee..a84bcb3 100644 --- a/Views/Grid.xaml.fs +++ b/Views/Grid.xaml.fs @@ -49,6 +49,7 @@ type Grid() as this = let mutable m_debug = false let mutable m_me_focus = false let mutable m_scrollbar_fg, m_scrollbar_bg, _, _ = theme.getSemanticHighlightGroup SemanticHighlightGroup.PmenuSbar + let mutable m_gadget_enable = true let mutable m_gadget_pen = Pen() let mutable m_gadget_brush = SolidColorBrush() let m_gridComparer = GridViewModel.MakeGridComparer() @@ -330,6 +331,7 @@ type Grid() as this = |> (fun c -> Pen(c.ToUint32(), thickness = 1.0)) let y = float abs_r * grid_vm.GlyphHeight + 0.5 grid_dc.DrawLine(pen, Point(0.0,y), Point(grid_fb.Size.Width, y)) + m_gadget_enable <- false // hide gadgets to avoid overlapping... vm.DrawOps.Count <> 0 /// draw add-ons attached to the grids. for example: @@ -351,27 +353,46 @@ type Grid() as this = float top, float bot, float row, float lc let bar_w = 8.0 let slide_w = 7.0 + let sign_w = 4.0 + // -- bg let bar_x = vm_x + vm_w - bar_w let c = m_scrollbar_bg.ToUint32() ||| 0xff000000u m_gadget_brush.Color <- Color.FromUInt32(c) m_gadget_brush.Opacity <- 1.0 ctx.DrawRectangle(m_gadget_brush, m_gadget_pen, RoundedRect(Rect(bar_x, vm_y, bar_w, vm_h))) - if bot <= top || lc <= 0.0 then () - else - let bot = min bot lc - let slide_x = vm_x + vm_w - (bar_w + slide_w) / 2.0 - let slide_p1, slide_p2 = top / lc, bot / lc - let slide_h = (slide_p2 - slide_p1) * vm_h - let slide_y = slide_p1 * vm_h - m_gadget_brush.Color <- m_scrollbar_fg - m_gadget_brush.Opacity <- 1.0 - ctx.DrawRectangle(m_gadget_brush, m_gadget_pen, RoundedRect(Rect(slide_x, vm_y + slide_y, slide_w, slide_h))) - let cur_y = row / lc * vm_h - let cur_h = 2.0 - m_gadget_brush.Color <- vm.CursorInfo.bg - m_gadget_brush.Opacity <- 1.0 - ctx.DrawRectangle(m_gadget_brush, m_gadget_pen, RoundedRect(Rect(bar_x, vm_y + cur_y, bar_w, cur_h))) - () + // -- fg + if bot > top && lc > 0.0 then + let bot = min bot lc + let slide_x = vm_x + vm_w - (bar_w + slide_w) / 2.0 + let slide_p1, slide_p2 = top / lc, bot / lc + let slide_h = (slide_p2 - slide_p1) * vm_h + let slide_y = slide_p1 * vm_h + m_gadget_brush.Color <- m_scrollbar_fg + m_gadget_brush.Opacity <- 1.0 + ctx.DrawRectangle(m_gadget_brush, m_gadget_pen, RoundedRect(Rect(slide_x, vm_y + slide_y, slide_w, slide_h))) + // -- cursor + if lc > 0.0 then + let cur_y = row / lc * vm_h + let cur_h = 2.0 + m_gadget_brush.Color <- vm.CursorInfo.bg + m_gadget_brush.Opacity <- 1.0 + ctx.DrawRectangle(m_gadget_brush, m_gadget_pen, RoundedRect(Rect(bar_x, vm_y + cur_y, bar_w, cur_h))) + // -- signs + if lc > 0.0 then + let sign_h = vm_h / lc + let xl = vm_x + vm_w - bar_w + let xr = vm_x + vm_w - sign_w + for {line=line;kind=kind} in vm.Signs do + let color,sx = match kind with + | SignKind.Warning -> Colors.Green,xr + | SignKind.Error -> Colors.Red,xr + | SignKind.Add -> Colors.LightGreen,xl + | SignKind.Delete -> Colors.Gray,xl + | SignKind.Change -> Colors.Yellow,xl + | _ -> Colors.Transparent,xl + let sy = float line / lc * vm_h + m_gadget_brush.Color <- color + ctx.DrawRectangle(m_gadget_brush, m_gadget_pen, RoundedRect(Rect(sx, vm_y + sy, sign_w, sign_h))) do this.Watch @@ -421,6 +442,7 @@ type Grid() as this = #endif _drawnRegions.Clear() _drawVMs.Clear() + m_gadget_enable <- true scanDrawVMs grid_vm _drawVMs.Sort(m_gridComparer) let mutable drawn = false @@ -443,7 +465,7 @@ type Grid() as this = let dc = ctx.PlatformImpl for vm in _drawVMs do // do not draw gadgets for the root grid / floating windows (borders only) - if vm.GridId <> 1 && not vm.IsFloat && not vm.IsMsg then + if vm.GridId <> 1 && not vm.IsFloat && not vm.IsMsg && m_gadget_enable then drawGadgets vm dc gw gh #if DEBUG diff --git a/def.fs b/def.fs index c38c7bb..3a1b109 100644 --- a/def.fs +++ b/def.fs @@ -292,6 +292,20 @@ type SemanticHighlightGroup = | MsgSeparator = 47 | NormalFloat = 48 +type SignKind = + | Add = 0 + | Change = 1 + | Delete = 2 + | Warning = 3 + | Error = 4 + | Other = 5 + +type SignPlacement = + { + line: int + kind: SignKind + } + type RedrawCommand = /// -- global -- | SetOption of UiOption[] @@ -385,6 +399,7 @@ type RedrawCommand = | UnknownCommand of data: obj /// --------- Custom messages ----------- | MultiRedrawCommand of xs: RedrawCommand [] +| SignUpdate of bufnr: int * signs: SignPlacement[] type EventParseException(data: obj) = inherit exn() @@ -801,4 +816,9 @@ let backgroundCompositionToString = | Acrylic -> "acrylic" | Transparent -> "transparent" +let parseBufferSignPlacements (ObjArray [| FindKV("signs") (ObjArray signs) |]) = + signs + |> Array.choose (function + | FindKV("lnum")(Integer32 num) & FindKV("name")(String name) -> Some(num,name) + | _ -> None) diff --git a/fvim.vim b/fvim.vim index 1385ee7..4e8e50d 100644 --- a/fvim.vim +++ b/fvim.vim @@ -56,6 +56,21 @@ function! s:fvim_on_bufwinenter() call rpcnotify(g:fvim_channel, 'OnBufWinEnter', l:bufnr, l:wins) endfunction +function! s:fvim_on_winenter() + let l:win=nvim_get_current_win() + let l:bufnr=nvim_win_get_buf(l:win) + call rpcnotify(g:fvim_channel, 'OnBufWinEnter', l:bufnr, [l:win]) +endfunction + +function! s:fvim_on_cursorhold() + let l:bufnr=nvim_get_current_buf() + let l:signs=sign_getplaced(l:bufnr, {'group': '*'}) + call rpcnotify(g:fvim_channel, 'OnSignUpdate', l:bufnr, l:signs) +endfunction + augroup FVim autocmd BufWinEnter * call fvim_on_bufwinenter() + autocmd WinEnter * call fvim_on_winenter() + autocmd CursorHold * call fvim_on_cursorhold() + autocmd CursorHoldI * call fvim_on_cursorhold() augroup END diff --git a/model.fs b/model.fs index 5d1d2c9..d98ca34 100644 --- a/model.fs +++ b/model.fs @@ -147,6 +147,20 @@ module private ModelImpl = trace "Grid #%d resized to %d %d" gridui.Id gridui.GridWidth gridui.GridHeight ignore <| nvim.grid_resize gridui.Id gridui.GridWidth gridui.GridHeight + let onSignUpdate [| Integer32 bufnr; signs |] = + let signs = parseBufferSignPlacements signs + |> Array.map (fun (ln,name) -> + let kind = + if name.Contains("Warning") then SignKind.Warning + elif name.Contains("Error") then SignKind.Error + elif name.Contains("Add") then SignKind.Add + elif name.Contains("Delete") then SignKind.Delete + elif name.Contains("Change") then SignKind.Change + else SignKind.Other + { line = ln; kind = kind } + ) + broadcast (SignUpdate(bufnr, signs)) + let private _appLifetime = lazy(Avalonia.Application.Current.ApplicationLifetime :?> Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime) let Shutdown code = try _appLifetime.Value.Shutdown code @@ -345,6 +359,7 @@ let Start (serveropts, norc) = rpc.register.watch "ui" ev_uiopt.Trigger rpc.register.watch "font" theme.fontConfig rpc.register.watch "font" ui.InvalidateFontCache + rpc.register.notify "OnSignUpdate" onSignUpdate ] rpc.register.request "set-clipboard" (fun [| P(|String|_|)lines; String regtype |] -> task {