1
0

layout.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. package layout
  2. type LayoutManager struct {
  3. Workspaces map[int]Workspace
  4. ActiveIdx int
  5. CurrentSplit SplitType
  6. }
  7. type Workspace struct {
  8. RootContainer Container
  9. }
  10. type SplitType int
  11. const (
  12. SplitHorizontal SplitType = iota
  13. SplitVertical
  14. )
  15. func (s *SplitType) SetOpposite() SplitType{
  16. if *s == SplitHorizontal {
  17. *s = SplitVertical
  18. } else {
  19. *s = SplitHorizontal
  20. }
  21. return *s
  22. }
  23. type ContainerNode interface {
  24. isContainerNode()
  25. }
  26. type ContainerBuffers struct {
  27. Buffers []int
  28. ActiveIdx int
  29. }
  30. func (ContainerBuffers) isContainerNode() {}
  31. type Container struct {
  32. Children [2]ContainerNode
  33. Split SplitType
  34. ActiveChildIdx int
  35. }
  36. func (Container) isContainerNode() {}
  37. func NewLayoutManager() LayoutManager {
  38. return LayoutManager{
  39. Workspaces: map[int]Workspace{0: NewWorkspace()},
  40. CurrentSplit: SplitVertical,
  41. }
  42. }
  43. func NewWorkspace() Workspace {
  44. return Workspace{
  45. RootContainer: NewContainerEmpty(),
  46. }
  47. }
  48. func NewContainerEmpty() Container {
  49. return Container{
  50. Children: [2]ContainerNode{
  51. ContainerBuffers{
  52. Buffers: []int{0},
  53. ActiveIdx: 0,
  54. },
  55. },
  56. Split: SplitHorizontal,
  57. ActiveChildIdx: 0,
  58. }
  59. }
  60. func (c *Container) WalkAndMutateActive(fn func(cb *ContainerBuffers) ContainerNode) {
  61. switch child := c.Children[c.ActiveChildIdx].(type) {
  62. case ContainerBuffers:
  63. c.Children[c.ActiveChildIdx] = fn(&child)
  64. case Container:
  65. child.WalkAndMutateActive(fn)
  66. c.Children[c.ActiveChildIdx] = child
  67. default:
  68. cb := ContainerBuffers{Buffers: []int{}, ActiveIdx: 0}
  69. c.Children[c.ActiveChildIdx] = fn(&cb)
  70. }
  71. }
  72. func (lm *LayoutManager) InsertBuffer(bufferIdx int, newNode bool) {
  73. workspace := lm.Workspaces[lm.ActiveIdx]
  74. workspace.RootContainer.WalkAndMutateActive(func(cb *ContainerBuffers) ContainerNode {
  75. if !newNode || len(cb.Buffers) == 0 {
  76. cb.Buffers = append(cb.Buffers, bufferIdx)
  77. cb.ActiveIdx = len(cb.Buffers) - 1
  78. return *cb
  79. }
  80. cbNew := ContainerBuffers{
  81. Buffers: []int{bufferIdx},
  82. ActiveIdx: 0,
  83. }
  84. return Container{
  85. Children: [2]ContainerNode{*cb, cbNew},
  86. Split: lm.CurrentSplit.SetOpposite(),
  87. ActiveChildIdx: 1,
  88. }
  89. })
  90. lm.Workspaces[lm.ActiveIdx] = workspace
  91. }