Skip to content

Commit

Permalink
merge with windows branch, mainly refactoring.
Browse files Browse the repository at this point in the history
  • Loading branch information
Yatao Li committed Jul 8, 2021
2 parents 13d2264 + c7ec611 commit c599ecf
Show file tree
Hide file tree
Showing 21 changed files with 511 additions and 443 deletions.
8 changes: 1 addition & 7 deletions App.xaml.fs
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,16 @@ open System

open log

type IViewModelContainer =
abstract Target: obj

type ViewLocator() =
interface IDataTemplate with
member this.Build(data: obj): Avalonia.Controls.IControl =
match data with
| :? IViewModelContainer as container -> (this :> IDataTemplate).Build(container.Target)
| _ ->
let _name = data.GetType().FullName.Replace("ViewModel", "");
let _type = Type.GetType(_name);
if _type <> null
then Activator.CreateInstance(_type) :?> IControl;
else TextBlock( Text = "Not Found: " + _name ) :> IControl
member this.Match(data: obj): bool =
data :? ViewModelBase || data :? IViewModelContainer
data :? ViewModelBase
//member this.SupportsRecycling: bool = false

type App() =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ open Avalonia.Media
open Avalonia.Controls
open Avalonia.Media.Imaging

type EditorSampleData() =
type GridSampleData() =
member this.BackgroundBrush = Brushes.DarkGray
member this.BufferWidth = 400.0
member this.BufferHeight = 300.0
2 changes: 1 addition & 1 deletion DesignTime/MainWindowSampleData.fs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ type MainWindowSampleData() =
member __.UseCustomTitleBar = true
member __.CustomTitleBarHeight = GridLength 26.0
member __.BorderSize = GridLength 1.0
//member __.MainGrid = EditorSampleData()
//member __.MainGrid = GridSampleData()
11 changes: 6 additions & 5 deletions Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ open Avalonia.Controls.ApplicationLifetimes
open MessagePack
open MessagePack.Resolvers

open def
open getopt
open common
open shell
Expand Down Expand Up @@ -64,12 +65,12 @@ let startMainWindow app serveropts =
let workspace = cfg.Workspace |> Array.tryFind(fun w -> w.Path = cwd)
workspace
>>= fun workspace -> workspace.Mainwin.BackgroundComposition
>>= fun comp -> states.parseBackgroundComposition(box comp)
>>= fun comp -> parseBackgroundComposition(box comp)
>>= fun comp -> states.background_composition <- comp; None
|> ignore

let mainwinVM = new MainWindowViewModel(workspace)
let mainwin = MainWindow(DataContext = mainwinVM)
let mainwinVM = new FrameViewModel(workspace)
let mainwin = Frame(DataContext = mainwinVM)
// sometimes the metrics will just go off...
// see #136
let screenBounds =
Expand All @@ -94,14 +95,14 @@ let startMainWindow app serveropts =
app <| mainwin
boundcheck()
let x, y, w, h = (int mainwinVM.X), (int mainwinVM.Y), (int mainwinVM.Width), (int mainwinVM.Height)
config.save cfg x y w h (mainwinVM.WindowState.ToString()) (states.backgroundCompositionToString states.background_composition) mainwinVM.CustomTitleBar
config.save cfg x y w h (mainwinVM.WindowState.ToString()) (backgroundCompositionToString states.background_composition) mainwinVM.CustomTitleBar
0

let startCrashReportWindow app ex =
let app = app()
trace "displaying crash dialog"
trace "exception: %O" ex
let code, msgs = states.get_crash_info()
let code, msgs = model.get_crash_info()
let crash = new CrashReportViewModel(ex, code, msgs)
let win = new CrashReport(DataContext = crash)
// there may be messages already posted into the sync context,
Expand Down
4 changes: 4 additions & 0 deletions Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
"fvim": {
"commandName": "Project"
},
"multigrid": {
"commandName": "Project",
"commandLineArgs": "--debug-multigrid"
},
"norc": {
"commandName": "Project",
"commandLineArgs": "-u NORC"
Expand Down
2 changes: 1 addition & 1 deletion ViewModels/CursorViewModel.fs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type CursorViewModel(cursorMode: int option) =
inherit ViewModelBase(None, None, Some 1.0, Some 1.0)

member val enabled: bool = true with get,set
member val ingrid: bool = false with get,set
member val focused: bool = false with get,set // true if a cursorGoto message is sent to the current grid
member val row: int = 0 with get,set
member val col: int = 0 with get,set
member val modeidx: int = _d -1 cursorMode with get,set
Expand Down
43 changes: 29 additions & 14 deletions ViewModels/MainWindowViewModel.fs → ViewModels/FrameViewModel.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,43 @@

open log
open common
open ui
open model

open ReactiveUI
open Avalonia
open Avalonia.Controls
open System
open System.IO
open ui
open Avalonia.Media.Imaging
open Avalonia.Media
open Avalonia.Layout

#nowarn "0025"

/// <summary>
/// A MainWindow is a top-level container that holds a main grid as the root.
/// Other grids may be anchored to the main grid as children.
/// A Frame is a top-level OS Window, and contains one or more nvim windows.
///
/// It also contains one (or more, TBD) cursor widget that can jump around in
/// the frame, between multiple nvim windows.
///
/// It also contains a completion popup window that can be anchored to a grid
/// position.
///
/// There are multiple ways to organize the nvim windows inside the frame.
/// - The classic "linegrid" model: there is a single nvim grid, the MainGrid.
/// All nvim windows live in this grid, and the Frame knows nothing about them.
/// - The "multigrid" model: the MainGrid is the root (and background), and
/// each nvim window lives in its own grid, attached to the main grid.
/// - The "windows" model: Each nvim window lives in its own grid, and there is no
/// root grid -- the window management methods are delegated to the frame, and
/// the frame should organize the grids.
/// </summary>
type MainWindowViewModel(cfg: config.ConfigObject.Workspace option, ?_maingrid: EditorViewModel) as this =
type FrameViewModel(cfg: config.ConfigObject.Workspace option, ?_maingrid: GridViewModel) as this =
inherit ThemableViewModelBase(Some 300.0, Some 300.0, Some 800.0, Some 600.0)

let mainGrid =
if _maingrid.IsNone then EditorViewModel(1)
if _maingrid.IsNone then GridViewModel(1)
else _maingrid.Value

let mutable m_windowState = WindowState.Normal
Expand All @@ -42,7 +57,7 @@ type MainWindowViewModel(cfg: config.ConfigObject.Workspace option, ?_maingrid:
let toggleFullScreen(gridid: int) =
if gridid = mainGrid.GridId then
this.Fullscreen <- not this.Fullscreen
trace (sprintf "MainWindowVM #%d" mainGrid.GridId) "ToggleFullScreen %A" this.Fullscreen
trace (sprintf "FrameVM #%d" mainGrid.GridId) "ToggleFullScreen %A" this.Fullscreen

let updateBackgroundImage() =
try
Expand All @@ -53,7 +68,7 @@ type MainWindowViewModel(cfg: config.ConfigObject.Workspace option, ?_maingrid:
path.[2..])
else
path
trace (sprintf "MainWindowVM #%d" mainGrid.GridId) "%s" path
trace (sprintf "FrameVM #%d" mainGrid.GridId) "%s" path
let new_img = new Bitmap(path)
ignore <| this.RaiseAndSetIfChanged(&m_bgimg_src, new_img, "BackgroundImage")
ignore <| this.RaiseAndSetIfChanged(&m_bgimg_w, m_bgimg_src.Size.Width, "BackgroundImageW")
Expand All @@ -80,13 +95,13 @@ type MainWindowViewModel(cfg: config.ConfigObject.Workspace option, ?_maingrid:
| _ -> ()
| None -> ()
this.Watch [
states.register.notify "ToggleFullScreen" (fun [| Integer32(gridid) |] -> toggleFullScreen gridid )
states.register.notify "CustomTitleBar" (fun [| Bool(v) |] -> this.CustomTitleBar <- v )
states.register.watch "background.image" (fun _ -> updateBackgroundImage())
rpc.register.notify "ToggleFullScreen" (fun [| Integer32(gridid) |] -> toggleFullScreen gridid )
rpc.register.notify "CustomTitleBar" (fun [| Bool(v) |] -> this.CustomTitleBar <- v )
rpc.register.watch "background.image" (fun _ -> updateBackgroundImage())
]
model.OnWindowReady this
model.OnFrameReady this

member __.MainGrid = mainGrid
member __.MainGrid = mainGrid :> IGridUI

member this.Title
with get() = m_title
Expand Down Expand Up @@ -132,8 +147,8 @@ type MainWindowViewModel(cfg: config.ConfigObject.Workspace option, ?_maingrid:
member __.BackgroundImageOpacity with get(): float = m_bgimg_opacity
member __.BackgroundImageStretch with get(): Stretch = m_bgimg_stretch

interface IWindow with
member __.RootId = this.MainGrid.GridId
interface IFrame with
member __.MainGrid = this.MainGrid
member __.Title
with get() = this.Title
and set (v: string): unit =
Expand Down
51 changes: 30 additions & 21 deletions ViewModels/EditorViewModel.fs → ViewModels/GridViewModel.fs
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,26 @@ open FSharp.Control.Reactive

open System
open System.Collections.ObjectModel
open model

#nowarn "0025"

module private EditorViewModelHelper =
module private GridViewModelHelper =
let inline trace id fmt =
FVim.log.trace (sprintf "editorvm #%d" id) fmt

open EditorViewModelHelper
open GridViewModelHelper

[<Struct>]
type GridDrawOperation =
| Scroll of int * int * int * int * int * int
| Put of GridRect

type EditorViewModel(_gridid: int, ?parent: EditorViewModel, ?_gridsize: GridSize, ?_measuredsize: Size, ?_gridscale: float,
/// <summary>
/// A Grid is a 2D surface for characters, and central to
/// the Frame-Grid-Window hierarchy.
/// </summary>
type GridViewModel(_gridid: int, ?parent: GridViewModel, ?_gridsize: GridSize, ?_measuredsize: Size, ?_gridscale: float,
?_cursormode: int, ?_anchorX: float, ?_anchorY: float) as this =
inherit ViewModelBase(_anchorX, _anchorY, _measuredsize)

Expand Down Expand Up @@ -86,7 +91,9 @@ type EditorViewModel(_gridid: int, ?parent: EditorViewModel, ?_gridsize: GridSiz
// do not use the default colors for cursor
let colorf = if hlid = 0 then GetReverseColor else id
let fg, bg, sp = colorf fg, colorf bg, colorf sp
let chksum = m_cursor_vm.VisualChecksum()

if _gridid = 1 && states.ui_multigrid then () else

m_cursor_vm.typeface <- theme.guifont
m_cursor_vm.wtypeface <- theme.guifontwide
m_cursor_vm.fontSize <- m_fontsize
Expand All @@ -107,9 +114,8 @@ type EditorViewModel(_gridid: int, ?parent: EditorViewModel, ?_gridsize: GridSiz
m_cursor_vm.Y <- origin.Y
m_cursor_vm.Width <- width
m_cursor_vm.Height <- m_glyphsize.Height
if chksum <> m_cursor_vm.VisualChecksum() then
m_cursor_vm.RenderTick <- m_cursor_vm.RenderTick + 1
trace _gridid "set cursor info, color = %A %A %A" fg bg sp
m_cursor_vm.RenderTick <- m_cursor_vm.RenderTick + 1
trace _gridid "set cursor info, color = %A %A %A" fg bg sp

let clearBuffer preserveContent =
let oldgrid = m_gridbuffer
Expand Down Expand Up @@ -187,11 +193,14 @@ type EditorViewModel(_gridid: int, ?parent: EditorViewModel, ?_gridsize: GridSiz
putBuffer line

let cursorGoto id row col =
m_cursor_vm.ingrid <- (id = _gridid)
if id = _gridid then
m_cursor_vm.focused <- true
m_cursor_vm.row <- row
m_cursor_vm.col <- col
cursorConfig()
cursorConfig()
elif m_cursor_vm.focused then
m_cursor_vm.focused <- false
m_cursor_vm.RenderTick <- m_cursor_vm.RenderTick + 1

let changeMode (name: string) (index: int) =
m_cursor_vm.modeidx <- index
Expand All @@ -205,8 +214,6 @@ type EditorViewModel(_gridid: int, ?parent: EditorViewModel, ?_gridsize: GridSiz
trace _gridid "neovim: busy: %A" v
m_busy <- v
setCursorEnabled <| not v
//if v then this.Cursor <- Cursor(StandardCursorType.Wait)
//else this.Cursor <- Cursor(StandardCursorType.Arrow)

let scrollBuffer (top: int) (bot: int) (left: int) (right: int) (rows: int) (cols: int) =
// !NOTE top-bot are the bounds of the SCROLL-REGION, not SRC or DST.
Expand Down Expand Up @@ -255,7 +262,9 @@ type EditorViewModel(_gridid: int, ?parent: EditorViewModel, ?_gridsize: GridSiz
for i = bot + rows - 1 downto top do
copy i (i-rows)

if top <= m_cursor_vm.row
if m_cursor_vm.enabled
&& m_cursor_vm.focused
&& top <= m_cursor_vm.row
&& m_cursor_vm.row <= bot
&& left <= m_cursor_vm.col
&& m_cursor_vm.col <= right
Expand Down Expand Up @@ -359,7 +368,7 @@ type EditorViewModel(_gridid: int, ?parent: EditorViewModel, ?_gridsize: GridSiz
let s, w, h = MeasureText(Rune.empty, theme.guifont, theme.guifontwide, theme.fontsize, m_gridscale)
m_glyphsize <- Size(w, h)
m_fontsize <- s
trace _gridid "fontConfig: glyphsize=%A, measured font size=%A" m_glyphsize m_fontsize
//trace _gridid "fontConfig: glyphsize=%A, measured font size=%A" m_glyphsize m_fontsize

// sync font to cursor vm
cursorConfig()
Expand Down Expand Up @@ -419,15 +428,15 @@ type EditorViewModel(_gridid: int, ?parent: EditorViewModel, ?_gridsize: GridSiz
|> Observable.subscribe fontConfig

theme.cursoren_ev.Publish
|> Observable.subscribe (fun en ->
if m_cursor_vm.ingrid then
setCursorEnabled en)
|> Observable.subscribe setCursorEnabled

states.register.watch "font" fontConfig
rpc.register.watch "font" fontConfig

this.ObservableForProperty(fun x -> x.IsFocused)
|> Observable.subscribe (fun x ->
trace _gridid "focus state changed: %A" x.Value)
trace _gridid "focus state changed: %A" x.Value
if x.Value then cursorConfig()
)
]

interface IGridUI with
Expand All @@ -436,12 +445,13 @@ type EditorViewModel(_gridid: int, ?parent: EditorViewModel, ?_gridsize: GridSiz
member __.GridWidth = int( this.Width / m_glyphsize.Width )
member __.Resized = m_resize_ev.Publish
member __.Input = m_input_ev.Publish
member __.BackgroundColor with get(): Color = theme.default_bg
member __.HasChildren = m_child_grids.Count <> 0
member __.Redraw cmd = redraw cmd
member __.CreateChild id r c =
trace _gridid "CreateChild: #%d" id
let child_size = this.GetPoint r c
let child = EditorViewModel(id, this, {rows=r; cols=c}, Size(child_size.X, child_size.Y), m_gridscale, m_cursor_vm.modeidx)
let child = GridViewModel(id, this, {rows=r; cols=c}, Size(child_size.X, child_size.Y), m_gridscale, m_cursor_vm.modeidx)
m_child_grids.Add child
child :> IGridUI
member __.RemoveChild c =
Expand All @@ -461,7 +471,7 @@ type EditorViewModel(_gridid: int, ?parent: EditorViewModel, ?_gridsize: GridSiz
member __.GetPoint row col =
Point(double(col) * m_glyphsize.Width, double(row) * m_glyphsize.Height)

member this.SetMeasuredSize (v: Size) =
member __.SetMeasuredSize (v: Size) =
trace _gridid "set measured size: %A" v
let gridui = this :> IGridUI
let gw, gh = gridui.GridWidth, gridui.GridHeight
Expand All @@ -485,7 +495,6 @@ type EditorViewModel(_gridid: int, ?parent: EditorViewModel, ?_gridsize: GridSiz
with get() : float = m_gridscale
and set(v) = m_gridscale <- v
member __.FontAttrs with get() = theme.guifont, theme.guifontwide, m_fontsize
member __.BackgroundColor with get(): Color = theme.default_bg
member __.BufferHeight with get(): float = m_fb_h
member __.BufferWidth with get(): float = m_fb_w
member __.GlyphHeight with get(): float = m_glyphsize.Height
Expand Down
Loading

0 comments on commit c599ecf

Please sign in to comment.