277 lines
8.7 KiB
Go
277 lines
8.7 KiB
Go
package main
|
||
|
||
import (
|
||
"fmt"
|
||
"os"
|
||
"strconv"
|
||
"strings"
|
||
g "github.com/AllenDang/giu"
|
||
)
|
||
|
||
const (
|
||
MasterWidth int = 376
|
||
Version string = "0.0.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)
|
||
}
|