

Almost every application needs to communicate with the user in some way.
Therefore, a substantial part of the code deals with the interaction
of program logic with GUI components.

Typically, the following is needed:

 put values into input fields under program control
 read and check input from the user
 pop up dialogs to query the user for further information


Task

For a minimal "application", write a program that presents a form with three components to the user:

 a numeric input field ("Value") 
 a button ("increment")
 a button ("random")


The field is initialized to zero.

The user may manually enter a new value into the field,
or increment its value with the "increment" button.

Entering a non-numeric value should be either impossible,
or issue an error message.

Pressing the "random" button presents a confirmation dialog,
and resets the field's value to a random value if the answer is "Yes".

(This task may be regarded as an extension of the task Simple windowed application).



package main
 
import (
    "github.com/gotk3/gotk3/gtk"
    "log"
    "math/rand"
    "strconv"
    "time"
)
 
func validateInput(window *gtk.Window, str string) (int64, bool) {
    i, err := strconv.ParseInt(str, 10, 64)
    if err != nil {
        dialog := gtk.MessageDialogNew(
            window,
            gtk.DIALOG_MODAL,
            gtk.MESSAGE_ERROR,
            gtk.BUTTONS_OK,
            "Invalid value",
        )
        dialog.Run()
        dialog.Destroy()
        return 0, false
    }
    return i, true
}
 
func check(err error, msg string) {
    if err != nil {
        log.Fatal(msg, err)
    }
}
 
func main() {
    rand.Seed(time.Now().UnixNano())
    gtk.Init(nil)
 
    window, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
    check(err, "Unable to create window:")
    window.SetTitle("Rosetta Code")
    window.SetPosition(gtk.WIN_POS_CENTER)
    window.Connect("destroy", func() {
        gtk.MainQuit()
    })
 
    box, err := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 1)
    check(err, "Unable to create box:")
    box.SetBorderWidth(1)
 
    label, err := gtk.LabelNew("Value:")
    check(err, "Unable to create label:")
 
    entry, err := gtk.EntryNew()
    check(err, "Unable to create entry:")
    entry.SetText("0") // initialize to zero
    entry.Connect("activate", func() {
        // read and validate the entered value
        str, _ := entry.GetText()
        validateInput(window, str)
    })
 
    // button to increment
    ib, err := gtk.ButtonNewWithLabel("Increment")
    check(err, "Unable to create increment button:")
    ib.Connect("clicked", func() {
        // read and validate the entered value
        str, _ := entry.GetText()
        if i, ok := validateInput(window, str); ok {
            entry.SetText(strconv.FormatInt(i+1, 10))
        }
    })
 
    // button to put in a random value if confirmed
    rb, err := gtk.ButtonNewWithLabel("Random")
    check(err, "Unable to create random button:")
    rb.Connect("clicked", func() {
        dialog := gtk.MessageDialogNew(
            window,
            gtk.DIALOG_MODAL,
            gtk.MESSAGE_QUESTION,
            gtk.BUTTONS_YES_NO,
            "Set random value",
        )
        answer := dialog.Run()
        dialog.Destroy()
        if answer == gtk.RESPONSE_YES {
            entry.SetText(strconv.Itoa(rand.Intn(10000)))
        }
    })
 
    box.PackStart(label, false, false, 2)
    box.PackStart(entry, false, false, 2)
    box.PackStart(ib, false, false, 2)
    box.PackStart(rb, false, false, 2)
    window.Add(box)
 
    window.ShowAll()
    gtk.Main()
}