├── README ├── calculator.go └── gui.go /README: -------------------------------------------------------------------------------- 1 | Simple Go Gtk Calculator using go-gtk (github.com/mattn/go-gtk) 2 | 3 | go get github.com/abiosoft/gocalc 4 | 5 | Depends on go-gtk 6 | 7 | go get github.com/mattn/go-gtk/gtk -------------------------------------------------------------------------------- /calculator.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // Stores the result of calculations 8 | var result struct { 9 | last float32 // stores last result 10 | operator string // the next operator to use 11 | active bool // whether calculation has started 12 | } 13 | 14 | // Perform calculation 15 | func Calculation(val float32, operator string) { 16 | if !result.active { 17 | result.last = val 18 | result.operator = operator 19 | result.active = true 20 | return 21 | } 22 | switch result.operator { 23 | case "+": 24 | result.last += val 25 | case "-": 26 | result.last -= val 27 | case "/": 28 | result.last /= val 29 | case "x": 30 | result.last *= val 31 | } 32 | result.operator = operator 33 | } 34 | 35 | // Resets the calculator 36 | func Reset() { 37 | result.last = 0 38 | result.operator = "" 39 | result.active = false 40 | } 41 | 42 | // Generate formatted output, returns a function 43 | func GetResult() string { 44 | val := fmt.Sprintf("%f", result.last) 45 | exp := fmt.Sprintf("%E", result.last) 46 | trim := val[0 : len(val)-7] 47 | if len(trim) <= 10 { 48 | if val[len(val)-7:] == ".000000" { 49 | return trim 50 | } 51 | if len(val) <= 10 { 52 | return func() string { 53 | for i := len(val) - 1; i >= len(val)-7; i-- { 54 | if val[i] != '0' { 55 | return val[0 : i+1] 56 | } 57 | } 58 | return val 59 | }() 60 | } 61 | } 62 | return exp 63 | } 64 | -------------------------------------------------------------------------------- /gui.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | gtk "github.com/mattn/go-gtk/gtk" 5 | "os" 6 | "strconv" 7 | "strings" 8 | ) 9 | 10 | var ( 11 | display *gtk.Entry // where values are displayed 12 | inputMode = false 13 | nums = "789/456x123-0.=+" 14 | operators = "/x-+=" 15 | ) 16 | 17 | // End the program 18 | func Quit() { 19 | gtk.MainQuit() 20 | } 21 | 22 | // Action to be performed by each button, returns a handler function 23 | func Input(b *gtk.Button) func() { 24 | return func() { 25 | if strings.Index(operators, b.GetLabel()) != -1 { 26 | val, _ := strconv.ParseFloat(display.GetText(), 32) 27 | Calculation(float32(val), b.GetLabel()) 28 | display.SetText(GetResult()) 29 | inputMode = false 30 | } else { 31 | if inputMode { 32 | display.SetText(display.GetText() + b.GetLabel()) 33 | } else { 34 | display.SetText(b.GetLabel()) 35 | inputMode = true 36 | if result.operator == "=" { 37 | Reset() 38 | } 39 | } 40 | } 41 | } 42 | } 43 | 44 | func main() { 45 | gtk.Init(&os.Args) 46 | display = gtk.NewEntry() 47 | window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL) 48 | window.SetTitle("Simple Go Calculator") 49 | window.Connect("destroy", Quit, nil) 50 | 51 | // Vertical box containing all components 52 | vbox := gtk.NewVBox(false, 1) 53 | 54 | // Menu bar 55 | menubar := gtk.NewMenuBar() 56 | vbox.PackStart(menubar, false, false, 0) 57 | 58 | // Add calculator display to vertical box 59 | display.SetCanFocus(false) // disable focus on calcuator display 60 | display.SetText("0") 61 | display.SetAlignment(1.0) //align text to right 62 | vbox.Add(display) 63 | 64 | // Menu items 65 | filemenu := gtk.NewMenuItemWithMnemonic("_File") 66 | menubar.Append(filemenu) 67 | filesubmenu := gtk.NewMenu() 68 | filemenu.SetSubmenu(filesubmenu) 69 | 70 | aboutmenuitem := gtk.NewMenuItemWithMnemonic("_About") 71 | aboutmenuitem.Connect("activate", func() { 72 | messagedialog := gtk.NewMessageDialog( 73 | window.GetTopLevelAsWindow(), 74 | gtk.DIALOG_MODAL, 75 | gtk.MESSAGE_INFO, 76 | gtk.BUTTONS_OK, 77 | "Simple Go Calculator") 78 | messagedialog.Response(func() {}, nil) 79 | messagedialog.Run() 80 | messagedialog.Destroy() 81 | }, 82 | nil) 83 | filesubmenu.Append(aboutmenuitem) 84 | 85 | resetmenuitem := gtk.NewMenuItemWithMnemonic("_Reset") 86 | resetmenuitem.Connect("activate", func() { Reset(); display.SetText("0") }, nil) 87 | filesubmenu.Append(resetmenuitem) 88 | 89 | exitmenuitem := gtk.NewMenuItemWithMnemonic("E_xit") 90 | exitmenuitem.Connect("activate", Quit, nil) 91 | filesubmenu.Append(exitmenuitem) 92 | 93 | // Vertical box containing all buttons 94 | buttons := gtk.NewVBox(false, 5) 95 | 96 | for i := 0; i < 4; i++ { 97 | hbox := gtk.NewHBox(false, 5) // a horizontal box for each 4 buttons 98 | for j := 0; j < 4; j++ { 99 | b := gtk.NewButtonWithLabel(string(nums[i*4+j])) 100 | b.Clicked(Input(b), nil) //add click event 101 | hbox.Add(b) 102 | } 103 | buttons.Add(hbox) // add horizonatal box to vertical buttons' box 104 | } 105 | 106 | vbox.Add(buttons) 107 | 108 | window.Add(vbox) 109 | window.SetSizeRequest(250, 250) 110 | window.ShowAll() 111 | gtk.Main() 112 | } 113 | --------------------------------------------------------------------------------