223 lines
5.3 KiB
Go
223 lines
5.3 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
|
|
"github.com/gotk3/gotk3/glib"
|
|
"github.com/gotk3/gotk3/gtk"
|
|
)
|
|
|
|
const appId = "com.github.gotk3.gotk3-examples.glade"
|
|
|
|
type App struct {
|
|
app *gtk.Application
|
|
|
|
mw *gtk.ApplicationWindow
|
|
|
|
// The stack holds the views of the main window
|
|
stack *gtk.Stack
|
|
stackMain *gtk.Box
|
|
stackAbout *gtk.Grid
|
|
|
|
// Detail stack variables
|
|
stackDetail *gtk.Box
|
|
detail struct {
|
|
header *gtk.Label
|
|
}
|
|
|
|
dynBtnBox *gtk.Box
|
|
|
|
dlgNew *gtk.FileChooserDialog
|
|
listbox *gtk.ListBox
|
|
}
|
|
|
|
func New() *App {
|
|
return &App{}
|
|
}
|
|
|
|
func main() {
|
|
app := New()
|
|
|
|
// Create a new application.
|
|
application, err := gtk.ApplicationNew(appId, glib.APPLICATION_FLAGS_NONE)
|
|
errorCheck(err)
|
|
app.app = application
|
|
|
|
// Connect function to application startup event, this is not required.
|
|
application.Connect("startup", func() {
|
|
log.Println("application startup")
|
|
})
|
|
|
|
// Connect function to application activate event
|
|
application.Connect("activate", func() {
|
|
log.Println("application activate")
|
|
|
|
// Get the GtkBuilder UI definition in the glade file.
|
|
builder, err := gtk.BuilderNewFromFile("ui/app.glade")
|
|
errorCheck(err)
|
|
|
|
// Map the handlers to callback functions, and connect the signals
|
|
// to the Builder.
|
|
signals := map[string]interface{}{
|
|
"on_main_window_destroy": app.onMainWindowDestroy,
|
|
"on_menu_home_activate": app.onBtnAboutBackClicked,
|
|
"on_menu_new_activate": app.onMenuNewActivate,
|
|
"on_menu_open_activate": app.onMenuOpenActivate,
|
|
"on_menu_quit_activate": app.onMenuQuitActivate,
|
|
"on_btn_about_clicked": app.onBtnAboutClicked,
|
|
"on_btn_about_back_clicked": app.onBtnAboutBackClicked,
|
|
"on_btn_detail_back_clicked": app.onBtnAboutBackClicked,
|
|
}
|
|
builder.ConnectSignals(signals)
|
|
|
|
// Get the object with the id of "main_window".
|
|
obj, err := builder.GetObject("main_window")
|
|
errorCheck(err)
|
|
|
|
// Verify that the object is a pointer to a gtk.ApplicationWindow.
|
|
win, err := isWindow(obj)
|
|
errorCheck(err)
|
|
app.mw = win
|
|
|
|
stack, _ := builder.GetObject("mw_stack")
|
|
app.stack = stack.(*gtk.Stack)
|
|
|
|
app.stackMain, _ = get(builder, "box_main").(*gtk.Box)
|
|
app.stackAbout, _ = get(builder, "box_about").(*gtk.Grid)
|
|
|
|
app.stackDetail, _ = get(builder, "box_detail").(*gtk.Box)
|
|
app.detail.header, _ = get(builder, "box_detail_header").(*gtk.Label)
|
|
|
|
app.dlgNew, _ = get(builder, "dlg_new_file").(*gtk.FileChooserDialog)
|
|
app.listbox, _ = get(builder, "mw_list").(*gtk.ListBox)
|
|
|
|
app.dynBtnBox, _ = get(builder, "dyn_btn_box").(*gtk.Box)
|
|
|
|
for _, row := range []string{"First Button", "Second", "Third"} {
|
|
app.AddButton(row)
|
|
}
|
|
|
|
// for _, row := range []string{"First", "Second", "Third"} {
|
|
// lbRow, err := gtk.ListBoxRowNew()
|
|
// errorCheck(err)
|
|
//
|
|
// }
|
|
|
|
// Show the Window and all of its components.
|
|
win.Show()
|
|
application.AddWindow(win)
|
|
})
|
|
|
|
// Connect function to application shutdown event, this is not required.
|
|
application.Connect("shutdown", func() {
|
|
log.Println("application shutdown")
|
|
})
|
|
|
|
// Launch the application
|
|
os.Exit(application.Run(os.Args))
|
|
}
|
|
|
|
func isWindow(obj glib.IObject) (*gtk.ApplicationWindow, error) {
|
|
// Make type assertion (as per gtk.go).
|
|
if win, ok := obj.(*gtk.ApplicationWindow); ok {
|
|
return win, nil
|
|
}
|
|
return nil, errors.New("not a *gtk.Window")
|
|
}
|
|
|
|
func get(builder *gtk.Builder, name string) glib.IObject {
|
|
v, err := builder.GetObject(name)
|
|
errorCheck(err)
|
|
return v
|
|
}
|
|
|
|
func errorCheck(e error) {
|
|
if e != nil {
|
|
// panic for any errors.
|
|
log.Panic(e)
|
|
}
|
|
}
|
|
|
|
// adds a button to the dynBtnBox
|
|
func (a *App) AddButton(label string) {
|
|
btn, err := gtk.ButtonNewWithLabel(label)
|
|
errorCheck(err)
|
|
|
|
btn.Connect("clicked", func() {
|
|
a.gotoDetailScreen(label)
|
|
})
|
|
|
|
// PackEnd(widget, expand, fill, padding)
|
|
a.dynBtnBox.PackStart(btn, false, true, 0)
|
|
btn.Show()
|
|
}
|
|
|
|
// onMainWindowDestory is the callback that is linked to the
|
|
// on_main_window_destroy handler. It is not required to map this,
|
|
// and is here to simply demo how to hook-up custom callbacks.
|
|
func (a *App) onMainWindowDestroy() {
|
|
log.Println("onMainWindowDestroy")
|
|
}
|
|
|
|
func (a *App) onMenuNewActivate() {
|
|
log.Println("new clicked")
|
|
a.dlgNew.Show()
|
|
}
|
|
|
|
func (a *App) onMenuOpenActivate() {
|
|
log.Println("open clicked")
|
|
|
|
dialog, err := gtk.FileChooserDialogNewWith2Buttons(
|
|
"Open File...",
|
|
a.mw,
|
|
gtk.FILE_CHOOSER_ACTION_OPEN,
|
|
"Cancel",
|
|
gtk.RESPONSE_DELETE_EVENT,
|
|
"Open",
|
|
gtk.RESPONSE_ACCEPT)
|
|
errorCheck(err)
|
|
|
|
filter, _ := gtk.FileFilterNew()
|
|
filter.AddPattern("*.jpg")
|
|
filter.SetName("JPEG images")
|
|
dialog.AddFilter(filter)
|
|
|
|
switcher := dialog.Run()
|
|
log.Printf("switcher: %d\n", switcher)
|
|
filename := dialog.GetFilename()
|
|
dialog.Destroy()
|
|
|
|
if switcher != -3 {
|
|
fmt.Printf("user canceled\n")
|
|
return
|
|
}
|
|
|
|
fmt.Printf("chosen: %s\n", filename)
|
|
|
|
}
|
|
|
|
func (a *App) onMenuQuitActivate() {
|
|
a.mw.Destroy()
|
|
// os.Exit(0) // TODO: more graceful
|
|
}
|
|
|
|
func (a *App) onBtnAboutClicked() {
|
|
fmt.Println("about clicked")
|
|
a.stack.SetTransitionType(gtk.STACK_TRANSITION_TYPE_SLIDE_LEFT)
|
|
a.stack.SetVisibleChild(a.stackAbout)
|
|
}
|
|
|
|
func (a *App) onBtnAboutBackClicked() {
|
|
a.stack.SetTransitionType(gtk.STACK_TRANSITION_TYPE_SLIDE_RIGHT)
|
|
a.stack.SetVisibleChild(a.stackMain)
|
|
}
|
|
|
|
func (a *App) gotoDetailScreen(label string) {
|
|
a.detail.header.SetText("Detail: " + label)
|
|
a.stack.SetTransitionType(gtk.STACK_TRANSITION_TYPE_SLIDE_LEFT)
|
|
a.stack.SetVisibleChild(a.stackDetail)
|
|
}
|