Example #1
0
func main() {
	gtk.Init(nil)

	win, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
	if err != nil {
		log.Fatal("Unable to create window:", err)
	}
	win.SetTitle("Grid Example")
	win.Connect("destroy", func() {
		gtk.MainQuit()
	})

	// Create a new grid widget to arrange child widgets
	grid, err := gtk.GridNew()
	if err != nil {
		log.Fatal("Unable to create grid:", err)
	}

	// gtk.Grid embeds an Orientable struct to simulate the GtkOrientable
	// GInterface.  Set the orientation from the default horizontal to
	// vertical.
	grid.SetOrientation(gtk.ORIENTATION_VERTICAL)

	// Create some widgets to put in the grid.
	lab, err := gtk.LabelNew("Just a label")
	if err != nil {
		log.Fatal("Unable to create label:", err)
	}

	btn, err := gtk.ButtonNewWithLabel("Button with label")
	if err != nil {
		log.Fatal("Unable to create button:", err)
	}

	entry, err := gtk.EntryNew()
	if err != nil {
		log.Fatal("Unable to create entry:", err)
	}

	spnBtn, err := gtk.SpinButtonNewWithRange(0.0, 1.0, 0.001)
	if err != nil {
		log.Fatal("Unable to create spin button:", err)
	}

	nb, err := gtk.NotebookNew()
	if err != nil {
		log.Fatal("Unable to create notebook:", err)
	}

	// Calling (*gtk.Container).Add() with a gtk.Grid will add widgets next
	// to each other, in the order they were added, to the right side of the
	// last added widget when the grid is in a horizontal orientation, and
	// at the bottom of the last added widget if the grid is in a vertial
	// orientation.  Using a grid in this manner works similar to a gtk.Box,
	// but unlike gtk.Box, a gtk.Grid will respect its child widget's expand
	// and margin properties.
	grid.Add(btn)
	grid.Add(lab)
	grid.Add(entry)
	grid.Add(spnBtn)

	// Widgets may also be added by calling (*gtk.Grid).Attach() to specify
	// where to place the widget in the grid, and optionally how many rows
	// and columns to span over.
	//
	// Additional rows and columns are automatically added to the grid as
	// necessary when new widgets are added with (*gtk.Container).Add(), or,
	// as shown in this case, using (*gtk.Grid).Attach().
	//
	// In this case, a notebook is added beside the widgets inserted above.
	// The notebook widget is inserted with a left position of 1, a top
	// position of 1 (starting at the same vertical position as the button),
	// a width of 1 column, and a height of 2 rows (spanning down to the
	// same vertical position as the entry).
	//
	// This example also demonstrates how not every area of the grid must
	// contain a widget.  In particular, the area to the right of the label
	// and the right of spin button have contain no widgets.
	grid.Attach(nb, 1, 1, 1, 2)
	nb.SetHExpand(true)
	nb.SetVExpand(true)

	// Add a child widget and tab label to the notebook so it renders.
	nbChild, err := gtk.LabelNew("Notebook content")
	if err != nil {
		log.Fatal("Unable to create button:", err)
	}
	nbTab, err := gtk.LabelNew("Tab label")
	if err != nil {
		log.Fatal("Unable to create label:", err)
	}
	nb.AppendPage(nbChild, nbTab)

	// Add the grid to the window, and show all widgets.
	win.Add(grid)
	win.ShowAll()

	gtk.Main()
}
Example #2
0
func windowWidget() *gtk.Widget {
	grid, err := gtk.GridNew()
	if err != nil {
		log.Fatal("Unable to create grid:", err)
	}
	grid.SetOrientation(gtk.ORIENTATION_VERTICAL)

	// Just as a demonstration, we create and destroy a Label without ever
	// adding it to a container.  In native GTK, this would result in a
	// memory leak, since gtk_widget_destroy() will not deallocate any
	// memory when passed a GtkWidget with a floating reference.
	//
	// gotk3 handles this situation by always sinking floating references
	// of any struct type embedding a glib.InitiallyUnowned, and by setting
	// a finalizer to unreference the object when Go has lost scope of the
	// variable.  Due to this design, widgets may be allocated freely
	// without worrying about handling memory incorrectly.
	//
	// The following code is not entirely useful (except to demonstrate
	// this point), but it is also not "incorrect" as the C equivalent
	// would be.
	unused, err := gtk.LabelNew("This label is never used")
	if err != nil {
		// Calling Destroy() is also unnecessary in this case.  The
		// memory will still be freed with or without calling it.
		unused.Destroy()
	}

	sw, err := gtk.ScrolledWindowNew(nil, nil)
	if err != nil {
		log.Fatal("Unable to create scrolled window:", err)
	}

	grid.Attach(sw, 0, 0, 2, 1)
	sw.SetHExpand(true)
	sw.SetVExpand(true)

	labelsGrid, err := gtk.GridNew()
	if err != nil {
		log.Fatal("Unable to create grid:", err)
	}
	labelsGrid.SetOrientation(gtk.ORIENTATION_VERTICAL)

	sw.Add(labelsGrid)
	labelsGrid.SetHExpand(true)

	insertBtn, err := gtk.ButtonNewWithLabel("Add a label")
	if err != nil {
		log.Fatal("Unable to create button:", err)
	}
	removeBtn, err := gtk.ButtonNewWithLabel("Remove a label")
	if err != nil {
		log.Fatal("Unable to create button:", err)
	}

	nLabels := 1
	insertBtn.Connect("clicked", func() {
		var s string
		if nLabels == 1 {
			s = fmt.Sprintf("Inserted %d label.", nLabels)
		} else {
			s = fmt.Sprintf("Inserted %d labels.", nLabels)
		}
		label, err := gtk.LabelNew(s)
		if err != nil {
			log.Print("Unable to create label:", err)
			return
		}

		labelList.PushBack(label)
		labelsGrid.Add(label)
		label.SetHExpand(true)
		labelsGrid.ShowAll()

		nLabels++
	})

	removeBtn.Connect("clicked", func() {
		e := labelList.Front()
		if e == nil {
			log.Print("Nothing to remove")
			return
		}
		lab, ok := labelList.Remove(e).(*gtk.Label)
		if !ok {
			log.Print("Element to remove is not a *gtk.Label")
			return
		}
		// (*Widget).Destroy() breaks this label's reference with all
		// other objects (in this case, the Grid container it was added
		// to).
		lab.Destroy()

		// At this point, only Go retains a reference to the GtkLabel.
		// When the lab variable goes out of scope when this function
		// returns, at the next garbage collector run, a finalizer will
		// be run to perform the final unreference and free the widget.
	})

	grid.Attach(insertBtn, 0, 1, 1, 1)
	grid.Attach(removeBtn, 1, 1, 1, 1)

	return &grid.Container.Widget
}