From 3321e80a569ff8f707dfcee95b145bbbd5ff5998 Mon Sep 17 00:00:00 2001 From: sqshq Date: Mon, 29 Apr 2019 23:29:31 -0400 Subject: [PATCH] added arrangement into empty space, if available --- component/textbox/textbox.go | 2 +- config/arrangement.go | 139 ++++++++++++++++++++++++++++------- config/component.go | 2 +- 3 files changed, 116 insertions(+), 27 deletions(-) diff --git a/component/textbox/textbox.go b/component/textbox/textbox.go index 4e9221e..306490e 100644 --- a/component/textbox/textbox.go +++ b/component/textbox/textbox.go @@ -48,7 +48,7 @@ func (t *TextBox) Draw(buffer *ui.Buffer) { rows := ui.SplitCells(cells, '\n') for y, row := range rows { - if y+t.Inner.Min.Y >= t.Inner.Max.Y { + if y+t.Inner.Min.Y >= t.Inner.Max.Y-1 { break } row = ui.TrimCells(row, t.Inner.Dx()-2) diff --git a/config/arrangement.go b/config/arrangement.go index d52d2a2..bf6b7da 100644 --- a/config/arrangement.go +++ b/config/arrangement.go @@ -1,7 +1,9 @@ package config import ( + ui "github.com/gizak/termui/v3" "github.com/sqshq/sampler/console" + "image" ) func (c *Config) setDefaultArrangement() { @@ -13,38 +15,53 @@ func (c *Config) setDefaultArrangement() { } for _, component := range components { - if component.Position == nil { + if component.Position == nil || len(component.Position) == 0 { lc := getLargestComponent(components) - lr := lc.GetRectangle() + le := getLargestEmptySpaceRectangle(components) - var w, h, ws, hs int - - if lr.Dx()/2 > lr.Dy() { - w = lr.Dx() / 2 - h = lr.Dy() - ws = w - hs = 0 + if getSquare(lc) > le.Dx()*le.Dy()*2 { + arrangeIntoLargestComponent(component, lc) } else { - w = lr.Dx() - h = lr.Dy() / 2 - ws = 0 - hs = h - } - - component.Position = [][]int{ - {lr.Min.X + ws, lr.Min.Y + hs}, - {w, h}, - } - - lc.Position = [][]int{ - {lr.Min.X, lr.Min.Y}, - {w, h}, + arrangeIntoLargestEmptySpace(component, le) } } } } +func arrangeIntoLargestComponent(component *ComponentConfig, lc *ComponentConfig) { + + lr := lc.GetRectangle() + var w, h, ws, hs int + + if lr.Dx()/2 > lr.Dy() { + w = lr.Dx() / 2 + h = lr.Dy() + ws = w + hs = 0 + } else { + w = lr.Dx() + h = lr.Dy() / 2 + ws = 0 + hs = h + } + component.Position = [][]int{ + {lr.Min.X + ws, lr.Min.Y + hs}, + {w, h}, + } + lc.Position = [][]int{ + {lr.Min.X, lr.Min.Y}, + {w, h}, + } +} + +func arrangeIntoLargestEmptySpace(component *ComponentConfig, le image.Rectangle) { + component.Position = [][]int{ + {le.Min.X, le.Min.Y}, + {le.Dx(), le.Dy()}, + } +} + func allHaveNoPosition(components []*ComponentConfig) bool { for _, component := range components { if component.Position != nil { @@ -99,10 +116,82 @@ func getComponents(c *Config) []*ComponentConfig { } func setSingleComponentPosition(c *ComponentConfig) { - w := int(console.ColumnsCount * 0.8) - h := int(console.RowsCount * 0.7) + w := int(console.ColumnsCount) + h := int(console.RowsCount * 0.6) c.Position = [][]int{ {(console.ColumnsCount - w) / 2, (console.RowsCount - h) / 2}, {w, h}, } } + +func getLargestEmptySpaceRectangle(components []*ComponentConfig) image.Rectangle { + + grid := [console.RowsCount][console.ColumnsCount]int{} + + for _, component := range components { + rect := component.GetRectangle() + for r := ui.MinInt(console.RowsCount, rect.Min.Y); r < ui.MinInt(console.RowsCount, rect.Max.Y); r++ { + for c := ui.MinInt(console.ColumnsCount, rect.Min.X); c < ui.MinInt(console.ColumnsCount, rect.Max.X); c++ { + grid[r][c] = 1 + } + } + } + + mr := image.ZR + + for row := 0; row < console.RowsCount; row++ { + histogram := createHistogram(grid, row) + r := calcMaxRectangle(histogram, row) + if r.Dx()*r.Dy() > mr.Dx()*mr.Dy() { + mr = r + } + } + + return mr +} + +func calcMaxRectangle(histogram [console.ColumnsCount]int, row int) image.Rectangle { + + maxRectangle := image.ZR + maxArea := 0 + + for i := 0; i < len(histogram); i++ { + + height := histogram[i] + if height > maxArea { + maxArea = height + maxRectangle = image.Rect(i, row, i, row+height) + } + + for j := i - 1; j >= 0; j-- { + width := i - j + 1 + height = ui.MinInt(height, histogram[j]) + if width*height > maxArea { + maxArea = width * height + maxRectangle = image.Rect(j, row, j+width, row+height) + } + } + } + + return maxRectangle +} + +func createHistogram(grid [console.RowsCount][console.ColumnsCount]int, row int) [console.ColumnsCount]int { + histogram := [console.ColumnsCount]int{} + for column := 0; column < console.ColumnsCount; column++ { + histogram[column] = countEmptyCellsBelow(grid, row, column) + } + return histogram +} + +func countEmptyCellsBelow(grid [console.RowsCount][console.ColumnsCount]int, row int, column int) int { + count := 0 + for r := row; r < console.RowsCount; r++ { + if grid[r][column] == 1 { + return count + } else { + count++ + } + } + return count +} diff --git a/config/component.go b/config/component.go index 6fbd171..244263a 100644 --- a/config/component.go +++ b/config/component.go @@ -34,7 +34,7 @@ func (c *ComponentConfig) GetSize() Size { } func (c *ComponentConfig) GetRectangle() image.Rectangle { - if c.Position == nil { + if c.Position == nil || len(c.Position) == 0 { return image.ZR } else { return image.Rect(c.Position[0][0], c.Position[0][1], c.Position[0][0]+c.Position[1][0], c.Position[0][1]+c.Position[1][1])