1
0
Fork 0
gnums/main.go

277 lines
8.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"fmt"
"os"
"strconv"
"strings"
g "github.com/AllenDang/giu"
)
const (
MasterWidth int = 376
Version string = "0.1.1"
FullStack int = iota
TopThree
TopOfStack
Dsc
Asc
)
type Input struct {
buf strings.Builder
decimal bool
negative bool
}
func (i *Input) String() string {
return i.buf.String()
}
func (i *Input) Append(value rune) {
switch value {
case '.':
if i.decimal {
return
}
if i.buf.Len() == 0 {
i.buf.WriteRune('0')
}
i.decimal = true
i.buf.WriteRune(value)
case '-':
if i.buf.Len() > 0 {
return
}
i.negative = true
i.buf.WriteRune(value)
default:
i.buf.WriteRune(value)
}
inputDisplay = i.String()
SetComboOut()
}
func (i *Input) Store() {
if i.buf.Len() == 0 {
return
}
if i.buf.Len() == 1 && (i.negative || i.decimal) {
i.Reset()
return
}
num, err := strconv.ParseFloat(i.buf.String(), 64)
if err != nil {
panic("Bad input")
}
s.Push(num)
i.Reset()
inputDisplay = ""
}
func (i *Input) Reset() {
i.buf.Reset()
i.decimal = false
i.negative = false
}
func (i *Input) Delete() {
if i.buf.Len() == 0 {
return
}
val := i.buf.String()
popped := val[len(val)-1]
i.buf.Reset()
i.buf.WriteString(val[:len(val)-1])
if popped == '.' {
i.decimal = false
} else if popped == '-' {
i.negative = false
}
inputDisplay = i.String()
SetComboOut()
}
var (
wnd *g.MasterWindow
inputBuffer *Input = &Input{}
s *stack = &stack{-1, [100]float64{}}
stackStyle int = FullStack
inputDisplay string = inputBuffer.String()
outputDisplay string = s.String()
comboDisplay string = inputBuffer.String()
Display *g.InputTextWidget = g.InputText("", &inputDisplay)
Output *g.InputTextMultilineWidget = g.InputTextMultiline("", &outputDisplay)
ComboView *g.InputTextWidget = g.InputText("", &comboDisplay)
ShowStack bool = true
stackSort int = Dsc
stackLabel *g.LabelWidget = g.Label("Stack Output\n[d]{TOS ...}")
)
func callStackWord(f func()) {
inputBuffer.Store()
f()
outputDisplay = s.String()
SetComboOut()
}
func SetComboOut() {
if inputBuffer.buf.Len() > 0 {
comboDisplay = inputBuffer.String()
} else {
comboDisplay = strconv.FormatFloat(s.Peek(), 'f', -1, 64)
}
}
func SetStackLabelWithSort() {
sort := "TOS ..."
if stackSort == Asc {
sort = "... TOS"
}
stackLabel = g.Label(fmt.Sprintf("Stack Output\n[d]{%s}", sort))
}
func loop() {
g.SingleWindowWithMenuBar("gnums - " + Version).Layout(
g.MenuBar().Layout(
g.Menu("File").Layout(
g.MenuItem("Exit").OnClick(Exit),
),
g.Menu("Edit").Layout(
g.MenuItem("Copy TOS"),
g.MenuItem("Copy Stack"),
g.MenuItem("Clear Stack"),
),
g.Menu("Settings").Layout(
g.Checkbox("Show Stack Window", &ShowStack).OnChange(func(){
width := MasterWidth
if ShowStack {
width = MasterWidth + MasterWidth / 2
}
wnd.SetSize(width,400)}),
g.Menu("Output Style").Layout(
g.RadioButton("Full Stack", stackStyle == FullStack).OnChange(func(){stackStyle = FullStack; outputDisplay = s.String()}),
g.RadioButton("Top Three", stackStyle == TopThree).OnChange(func(){stackStyle = TopThree; outputDisplay = s.String()}),
g.RadioButton("Top Of Stack", stackStyle == TopOfStack).OnChange(func(){stackStyle = TopOfStack; outputDisplay = s.String()}),
),
g.Menu("Stack Sort").Layout(
g.RadioButton("TOS ...", stackSort == Dsc).OnChange(func(){stackSort = Dsc; SetStackLabelWithSort()}),
g.RadioButton("... TOS", stackSort == Asc).OnChange(func(){stackSort = Asc; SetStackLabelWithSort()}),
),
),
),
g.Row(
g.Label("gnums v" + Version),
),
g.Dummy(0, 5),
ComboView.Size(-1).Flags(1 << 14),
g.Row(
g.Condition(ShowStack, g.Layout{
g.Row(
g.Child("Left").Layout(
stackLabel,
g.Tooltip("Stack display is\nnewest on top"),
Output.Size(-1, -1).Flags(1 << 14),
).Size(
float32(MasterWidth/2), -1,
),
g.Child("Section").Layout(
g.Row(
g.Button("Clear").Size(50,50).OnClick(func(){callStackWord(s.Clear)}),
g.Button("Delete").Size(50,50).OnClick(func(){inputBuffer.Delete()}),
g.Button("Round").Size(50,50).OnClick(func(){callStackWord(s.Round)}),
g.Button("^").Size(50,50).OnClick(func(){callStackWord(s.Pow)}),
g.Button("÷").Size(50,50).OnClick(func(){callStackWord(s.Div)}),
g.Button("Sqrt").Size(50,50).OnClick(func(){callStackWord(s.Sqt)}),
),
g.Row(
g.Button("Over").Size(50,50).OnClick(func(){callStackWord(s.Ovr)}),
g.Button("7").Size(50,50).OnClick(func(){inputBuffer.Append('7')}),
g.Button("8").Size(50,50).OnClick(func(){inputBuffer.Append('8')}),
g.Button("9").Size(50,50).OnClick(func(){inputBuffer.Append('9')}),
g.Button("×").Size(50,50).OnClick(func(){callStackWord(s.Mul)}),
g.Button("Floor").Size(50,50).OnClick(func(){callStackWord(s.Floor)}),
),
g.Row(
g.Button("Swap").Size(50,50).OnClick(func(){callStackWord(s.Swp)}),
g.Button("4").Size(50,50).OnClick(func(){inputBuffer.Append('4')}),
g.Button("5").Size(50,50).OnClick(func(){inputBuffer.Append('5')}),
g.Button("6").Size(50,50).OnClick(func(){inputBuffer.Append('6')}),
g.Button("-").Size(50,50).OnClick(func(){callStackWord(s.Sub)}),
g.Button("Ceil").Size(50,50).OnClick(func(){callStackWord(s.Ceil)}),
),
g.Row(
g.Button("Dup").Size(50,50).OnClick(func(){callStackWord(s.Dup)}),
g.Button("1").Size(50,50).OnClick(func(){inputBuffer.Append('1')}),
g.Button("2").Size(50,50).OnClick(func(){inputBuffer.Append('2')}),
g.Button("3").Size(50,50).OnClick(func(){inputBuffer.Append('3')}),
g.Button("+").Size(50,50).OnClick(func(){callStackWord(s.Add)}),
g.Button("+/-").Size(50,50).OnClick(func(){callStackWord(s.Inv)}),
),
g.Row(
g.Button("Drop").Size(50,50).OnClick(func(){callStackWord(s.Drp)}),
g.Button(".").Size(50,50).OnClick(func(){inputBuffer.Append('.')}),
g.Button("0").Size(50,50).OnClick(func(){inputBuffer.Append('0')}),
g.Button("Enter").Size(165,50).OnClick(func(){inputBuffer.Store(); outputDisplay = s.String()}),
),
),
),
}, g.Layout{
g.Child("Button Section").Layout(
g.Row(
g.Button("Clear").Size(50,50).OnClick(func(){callStackWord(s.Clear)}),
g.Button("Delete").Size(50,50).OnClick(func(){inputBuffer.Delete()}),
g.Button("Round").Size(50,50).OnClick(func(){callStackWord(s.Round)}),
g.Button("^").Size(50,50).OnClick(func(){callStackWord(s.Pow)}),
g.Button("÷").Size(50,50).OnClick(func(){callStackWord(s.Div)}),
g.Button("Sqrt").Size(50,50).OnClick(func(){callStackWord(s.Sqt)}),
),
g.Row(
g.Button("Over").Size(50,50).OnClick(func(){callStackWord(s.Ovr)}),
g.Button("7").Size(50,50).OnClick(func(){inputBuffer.Append('7')}),
g.Button("8").Size(50,50).OnClick(func(){inputBuffer.Append('8')}),
g.Button("9").Size(50,50).OnClick(func(){inputBuffer.Append('9')}),
g.Button("×").Size(50,50).OnClick(func(){callStackWord(s.Mul)}),
g.Button("Floor").Size(50,50).OnClick(func(){callStackWord(s.Floor)}),
),
g.Row(
g.Button("Swap").Size(50,50).OnClick(func(){callStackWord(s.Swp)}),
g.Button("4").Size(50,50).OnClick(func(){inputBuffer.Append('4')}),
g.Button("5").Size(50,50).OnClick(func(){inputBuffer.Append('5')}),
g.Button("6").Size(50,50).OnClick(func(){inputBuffer.Append('6')}),
g.Button("-").Size(50,50).OnClick(func(){callStackWord(s.Sub)}),
g.Button("Ceil").Size(50,50).OnClick(func(){callStackWord(s.Ceil)}),
),
g.Row(
g.Button("Dup").Size(50,50).OnClick(func(){callStackWord(s.Dup)}),
g.Button("1").Size(50,50).OnClick(func(){inputBuffer.Append('1')}),
g.Button("2").Size(50,50).OnClick(func(){inputBuffer.Append('2')}),
g.Button("3").Size(50,50).OnClick(func(){inputBuffer.Append('3')}),
g.Button("+").Size(50,50).OnClick(func(){callStackWord(s.Add)}),
g.Button("+/-").Size(50,50).OnClick(func(){callStackWord(s.Inv)}),
),
g.Row(
g.Button("Drop").Size(50,50).OnClick(func(){callStackWord(s.Drp)}),
g.Button(".").Size(50,50).OnClick(func(){inputBuffer.Append('.')}),
g.Button("0").Size(50,50).OnClick(func(){inputBuffer.Append('0')}),
g.Button("Enter").Size(165,50).OnClick(func(){inputBuffer.Store(); outputDisplay = s.String()}),
),
),
}),
),
)
}
func Exit() {
os.Exit(0)
}
func main() {
wnd = g.NewMasterWindow("gnums", MasterWidth+MasterWidth/2, 390, g.MasterWindowFlagsNotResizable, nil)
wnd.Run(loop)
}