mathpan/draw.go

321 lines
7.3 KiB
Go

package main
import "fmt"
import "math"
import "git.tebibyte.media/sashakoshka/stone"
func clear (x, y, width, height int) {
for yy := 0; yy < height; yy ++ {
for xx := 0; xx < width; xx ++ {
application.SetRune(xx + x, yy + y, 0)
application.SetColor(xx + x, yy + y, stone.ColorForeground)
}}
}
func fillColor (x, y, width, height int, color stone.Color) {
for yy := 0; yy < height; yy ++ {
for xx := 0; xx < width; xx ++ {
application.SetColor(xx + x, yy + y, color)
}}
}
func redraw () {
width, _ := application.Size()
showLeftColumn = width > 44
if showLeftColumn {
drawNumberReadouts()
}
drawInput()
}
func drawInput () {
width, height := application.Size()
xOffset := 0
if showLeftColumn {
xOffset = 26
}
y := height - 1
inputWidth, _ := inputBuffer.Size()
newWidth := width - xOffset
if newWidth != inputWidth {
inputBuffer.SetSize(newWidth, 1)
}
inputBuffer.Clear()
if expressionRoot != nil {
expressionRoot.Render(&inputBuffer, 0)
}
for x := 0; x < newWidth; x ++ {
character := '_'
cell := inputBuffer.Cell(x, 0)
if cell.Rune() > 0 {
character = cell.Rune()
}
application.SetRune(x + xOffset, y, character)
if character == '_' {
application.SetColor(x + xOffset, y, stone.ColorDim)
application.SetStyle(x + xOffset, y, stone.StyleNormal)
} else {
application.SetColor(x + xOffset, y, cell.Color())
application.SetStyle(x + xOffset, y, cell.Style())
}
}
}
func drawNumberReadouts () {
_, height := application.Size()
indicatorY := height - 12
application.SetDot(0, indicatorY)
fmt.Fprint(application, "sel fin | int float")
fillColor(0, indicatorY, 19, 1, stone.ColorDim)
if showEndResult {
fillColor(4, indicatorY, 3, 1, stone.ColorBlue)
} else {
fillColor(0, indicatorY, 3, 1, stone.ColorBlue)
}
clear(0, height - 10, 25, 10)
if showFloat {
fillColor(14, indicatorY, 5, 1, stone.ColorBlue)
drawNumberReadoutsFloat()
} else {
fillColor(10, indicatorY, 3, 1, stone.ColorBlue)
drawNumberReadoutsInt()
}
}
func drawNumberReadoutsInt () {
_, height := application.Size()
var number int64
var err error
if showEndResult {
if expressionRoot != nil {
number, err = expressionRoot.Solution()
}
} else {
if selectedExpression != nil {
number, err = selectedExpression.Solution()
}
}
if err != nil {
application.SetDot((25 - len(err.Error())) / 2, height - 6)
fmt.Fprint(application, err.Error())
} else {
drawHexadecimal (0, height - 10, uint64(number))
drawDecimal (0, height - 8, uint64(number))
drawOctal (0, height - 6, uint64(number))
drawBinary (0, height - 4, uint64(number))
}
}
func drawNumberReadoutsFloat () {
_, height := application.Size()
var number float64
var err error
if showEndResult {
if expressionRoot != nil {
number, err = expressionRoot.InexactSolution()
}
} else {
if selectedExpression != nil {
number, err = selectedExpression.InexactSolution()
}
}
if err != nil {
application.SetDot((25 - len(err.Error())) / 2, height - 6)
fmt.Fprint(application, err.Error())
} else {
firstHalf := int64(math.Floor(number))
secondHalf := (number - math.Floor(number))
application.SetDot(0, height - 7)
fmt.Fprint(application, "10")
application.SetColor(0, height - 7, stone.ColorBlue)
application.SetColor(1, height - 7, stone.ColorBlue)
application.SetDot(3, height - 7)
fmt.Fprintf(application, "%+d", firstHalf)
application.SetRune(3, height - 6, '.')
for index := 4; index < 25; index ++ {
secondHalf *= 10
secondHalf = math.Mod(secondHalf, 10)
digit := rune(secondHalf) + '0'
application.SetRune(index, height - 6, digit)
}
drawBinary(0, height - 4, math.Float64bits(number))
if math.Signbit(number) {
application.SetColor(3, height - 7, stone.ColorRed)
} else {
application.SetColor(3, height - 7, stone.ColorGreen)
}
}
}
func drawBinary (xOffset, yOffset int, number uint64) {
bitOffset := 64
for y := 0; y < 4; y ++ {
application.SetDot(xOffset, y + yOffset)
fmt.Fprint(application, bitOffset)
application.SetColor(xOffset, y + yOffset, stone.ColorBlue)
application.SetColor(xOffset + 1, y + yOffset, stone.ColorBlue)
for x := 0; x < 16; x ++ {
bitOffset --
trueX := x + xOffset + x / 4 + 3
character := '0' + rune((number >> bitOffset) & 0x1)
application.SetRune(trueX, y + yOffset, character)
if character == '0' {
application.SetColor (
trueX,
y + yOffset,
stone.ColorDim)
} else {
application.SetColor (
trueX,
y + yOffset,
stone.ColorForeground)
}
}
application.SetDot(xOffset + 23, y + yOffset)
fmt.Fprint(application, bitOffset + 1)
application.SetColor(xOffset + 23, y + yOffset, stone.ColorBlue)
application.SetColor(xOffset + 24, y + yOffset, stone.ColorBlue)
}
}
func drawHexadecimal (xOffset, yOffset int, number uint64) {
bitOffset := 64
application.SetDot(xOffset, yOffset)
fmt.Fprint(application, "16")
application.SetColor(xOffset, yOffset, stone.ColorBlue)
application.SetColor(xOffset + 1, yOffset, stone.ColorBlue)
number = drawSign(xOffset, yOffset, number)
for x := 0; x < 16; x ++ {
bitOffset -= 4
trueX := x + xOffset + x / 4 + 6
character := rune((number >> bitOffset) & 0xF)
if character < 10 {
character += '0'
} else {
character += 'A' - 10
}
application.SetRune(trueX, yOffset, character)
if character == '0' {
application.SetColor (
trueX,
yOffset,
stone.ColorDim)
} else {
application.SetColor (
trueX,
yOffset,
stone.ColorForeground)
}
}
}
func drawDecimal (xOffset, yOffset int, number uint64) {
var divisor uint64 = 10000000000000000000
application.SetDot(xOffset, yOffset)
fmt.Fprint(application, "10")
application.SetColor(xOffset, yOffset, stone.ColorBlue)
application.SetColor(xOffset + 1, yOffset, stone.ColorBlue)
number = drawSign(xOffset, yOffset, number)
for x := 0; x < 20; x ++ {
trueX := x + xOffset + 5
character := rune((number / divisor) % 10) + '0'
application.SetRune(trueX, yOffset, character)
if character == '0' {
application.SetColor (
trueX,
yOffset,
stone.ColorDim)
} else {
application.SetColor (
trueX,
yOffset,
stone.ColorForeground)
}
divisor /= 10
}
}
func drawOctal (xOffset, yOffset int, number uint64) {
// fuck octal i hate it almost as much as decimal
bitOffset := 63
application.SetDot(xOffset, yOffset)
fmt.Fprint(application, "08")
application.SetColor(xOffset, yOffset, stone.ColorBlue)
application.SetColor(xOffset + 1, yOffset, stone.ColorBlue)
number = drawSign(xOffset, yOffset, number)
for x := 0; x < 21; x ++ {
bitOffset -= 3
trueX := x + xOffset + 4
character := '0' + rune((number >> bitOffset) % 8)
application.SetRune(trueX, yOffset, character)
if character == '0' {
application.SetColor (
trueX,
yOffset,
stone.ColorDim)
} else {
application.SetColor (
trueX,
yOffset,
stone.ColorForeground)
}
}
}
func drawSign (xOffset, yOffset int, number uint64) (alteredNumber uint64) {
alteredNumber = number
if showSigned {
if int64(alteredNumber) >= 0 {
application.SetRune(xOffset + 3, yOffset, '+')
application.SetColor (
xOffset + 3, yOffset, stone.ColorGreen)
} else {
application.SetRune(xOffset + 3, yOffset, '-')
application.SetColor (
xOffset + 3, yOffset, stone.ColorRed)
alteredNumber = uint64(int64(number) * -1)
}
}
return
}