layout.go 1.9 KB

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