Browse Source

Initial commit

master
Noah Petherbridge 10 months ago
commit
1d2e4c0bf6
2 changed files with 553 additions and 0 deletions
  1. +222
    -0
      main.go
  2. +331
    -0
      ui/app.glade

+ 222
- 0
main.go View File

@@ -0,0 +1,222 @@
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)
}

+ 331
- 0
ui/app.glade View File

@@ -0,0 +1,331 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.36.0 -->
<interface>
<requires lib="gtk+" version="3.22"/>
<object class="GtkFileChooserDialog" id="dlg_new_file">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Choose your file</property>
<property name="type_hint">dialog</property>
<signal name="file-activated" handler="on_new_file_selected" swapped="no"/>
<child internal-child="vbox">
<object class="GtkBox">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Accept</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
<child type="titlebar">
<placeholder/>
</child>
</object>
<object class="GtkMenu" id="menu1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem" id="menu_home">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Home</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_menu_home_activate" swapped="no"/>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_new">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">New</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_menu_new_activate" swapped="no"/>
<accelerator key="n" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_open">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Open</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_menu_open_activate" swapped="no"/>
<accelerator key="o" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_save">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Save</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_menu_save_activate" swapped="no"/>
<accelerator key="s" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</object>
</child>
<child>
<object class="GtkSeparatorMenuItem">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menu_quit">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Quit</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_menu_quit_activate" swapped="no"/>
<accelerator key="F4" signal="activate" modifiers="GDK_MOD1_MASK"/>
</object>
</child>
</object>
<object class="GtkApplicationWindow" id="main_window">
<property name="width_request">360</property>
<property name="height_request">720</property>
<property name="can_focus">False</property>
<property name="show_menubar">False</property>
<signal name="destroy" handler="on_main_window_destroy" swapped="no"/>
<child>
<object class="GtkStack" id="mw_stack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="transition_type">slide-left</property>
<child>
<object class="GtkBox" id="box_main">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkListBox" id="mw_list">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="dyn_btn_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Glade button</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btn_about">
<property name="label" translatable="yes">About</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_btn_about_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="name">page0</property>
<property name="title" translatable="yes">page0</property>
</packing>
</child>
<child>
<object class="GtkGrid" id="box_about">
<property name="name">stack_about</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">The About Screen!</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btn_about_back">
<property name="label" translatable="yes">Back</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_btn_about_back_clicked" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="name">page1</property>
<property name="title" translatable="yes">page1</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkBox" id="box_detail">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel" id="box_detail_header">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
<attributes>
<attribute name="font-desc" value="Sans Bold 18"/>
<attribute name="foreground" value="#cccc00000000"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btn_detail_back">
<property name="label" translatable="yes">Back to Menu</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="clicked" handler="on_btn_detail_back_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="name">page2</property>
<property name="title" translatable="yes">page2</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
<child type="titlebar">
<object class="GtkHeaderBar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="title" translatable="yes">Hello world</property>
<property name="subtitle" translatable="yes">Test</property>
<property name="show_close_button">True</property>
<child>
<object class="GtkMenuButton" id="main_menu">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="focus_on_click">False</property>
<property name="receives_default">True</property>
<property name="popup">menu1</property>
<property name="use_popover">False</property>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>

Loading…
Cancel
Save