diff --git a/internal/gutil/cast_test.go b/internal/gutil/cast_test.go
index a27e9603..4f527120 100644
--- a/internal/gutil/cast_test.go
+++ b/internal/gutil/cast_test.go
@@ -50,41 +50,3 @@ func TestMustCastPanics(t *testing.T) {
}()
gutil.MustCast[gio.SimpleAction](str, gio.SimpleActionGLibType())
}
-
-func TestFillFromUI(t *testing.T) {
- const ui = `
-
-
-`
- var dst struct {
- Adj *gtk.Adjustment
- Renamed *gtk.Adjustment `gtk:"Other"`
- Missing *gtk.Adjustment
- Skipped *gtk.Adjustment `gtk:"-"`
- }
- gutil.FillFromUI(&dst, ui)
- if dst.Adj == nil || dst.Adj.GetUpper() != 10 || dst.Renamed == nil {
- t.Fatalf("FillFromUI did not fill fields: %+v", dst)
- }
- if dst.Missing != nil || dst.Skipped != nil {
- t.Errorf("FillFromUI filled missing/skipped fields: %+v", dst)
- }
- // The builder is gone; our references must keep the objects alive.
- if dst.Adj.GetUpper() != 10 {
- t.Error("object did not survive the builder")
- }
- gutil.UnrefFields(&dst)
- if dst.Adj != nil || dst.Renamed != nil {
- t.Error("UnrefFields did not clear fields")
- }
-}
-
-func TestFillFromUIWrongType(t *testing.T) {
- defer func() {
- if recover() == nil {
- t.Error("FillFromUI with a wrong field type did not panic")
- }
- }()
- var dst struct{ Adj *gtk.Label }
- gutil.FillFromUI(&dst, ``)
-}
diff --git a/internal/gutil/gutil.go b/internal/gutil/gutil.go
index 5e187370..41f4a38a 100644
--- a/internal/gutil/gutil.go
+++ b/internal/gutil/gutil.go
@@ -12,164 +12,8 @@ import (
"codeberg.org/puregotk/puregotk/v4/gobject"
"codeberg.org/puregotk/puregotk/v4/gobject/types"
"codeberg.org/puregotk/puregotk/v4/gtk"
- "deedles.dev/trayscale/internal/locale"
)
-// FillFromBuilder sets fields in the struct dst using objects looked
-// up in builder. If the field has a `gtk` tag, the value of it is
-// used as the name to look up in builder, unless the tag is exactly
-// `"-"` in which case the field is skipped. If it does not have a
-// tag, the field name is used instead. If an object by that name does
-// not exist in the builder, it is quietly skipped. If it does exist
-// but is the wrong type, this function will panic.
-//
-// Only exported pointer fields to puregotk wrappers are considered.
-// puregotk's casts are unchecked, so a field's type must be registered
-// with [RegisterType] for its GType to be checked; filling an
-// unregistered type panics.
-//
-// Each stored object gets its own reference, so dst stays valid after
-// builder is released. Release them with [UnrefFields].
-//
-// For example,
-//
-// var example struct {
-// Label *gtk.Label
-// Button *gtk.Button `gtk:"DoneButton"`
-// }
-// FillFromBuilder(&example, builder)
-//
-// will cause the Label field to get filled with the object named
-// "Label" and the Button field to get filled with the object named
-// "DoneButton".
-func FillFromBuilder[T any](dst *T, builder *gtk.Builder) {
- for fv, name := range builderFields(dst) {
- // puregotk's GetObject returns a new reference, which the field
- // keeps.
- obj := builder.GetObject(name)
- if obj == nil {
- continue
- }
-
- et := fv.Type().Elem()
- gtype, ok := typeRegistry[et]
- if !ok {
- obj.Unref()
- panic(fmt.Sprintf("gutil.FillFromBuilder: no GType registered for %v (field for %q)", et, name))
- }
- if !IsA(obj, gtype()) {
- obj.Unref()
- panic(fmt.Sprintf("gutil.FillFromBuilder: %q is a %v, want %v", name, TypeName(obj), et))
- }
-
- nv := reflect.New(et)
- nv.Interface().(gobject.Ptr).SetGoPointer(obj.GoPointer())
- fv.Set(nv)
- }
-}
-
-// UnrefFields drops the references [FillFromBuilder] took for dst's
-// fields and clears them.
-func UnrefFields[T any](dst *T) {
- for fv := range builderFields(dst) {
- if fv.IsNil() {
- continue
- }
- p := fv.Interface().(gobject.Ptr).GoPointer()
- if p != 0 {
- gobject.ObjectNewFromInternalPtr(p).Unref()
- }
- fv.SetZero()
- }
-}
-
-func builderFields[T any](dst *T) iter.Seq2[reflect.Value, string] {
- return func(yield func(reflect.Value, string) bool) {
- v := reflect.ValueOf(dst).Elem()
- t := v.Type()
- for i := range t.NumField() {
- ft := t.Field(i)
- if !ft.IsExported() || ft.Type.Kind() != reflect.Pointer || !ft.Type.Implements(ptrType) {
- continue
- }
- name := ft.Name
- if tag, ok := ft.Tag.Lookup("gtk"); ok {
- if tag == "-" {
- continue
- }
- name = tag
- }
- if !yield(v.Field(i), name) {
- return
- }
- }
- }
-}
-
-var ptrType = reflect.TypeFor[gobject.Ptr]()
-
-var typeRegistry = map[reflect.Type]func() types.GType{}
-
-// RegisterType records the GType of the puregotk wrapper T so that
-// [FillFromBuilder] can check and fill fields of type *T.
-func RegisterType[T any](gtype func() types.GType) {
- typeRegistry[reflect.TypeFor[T]()] = gtype
-}
-
-func init() {
- RegisterType[gtk.Box](gtk.BoxGLibType)
- RegisterType[gtk.Button](gtk.ButtonGLibType)
- RegisterType[gtk.DropDown](gtk.DropDownGLibType)
- RegisterType[gtk.DropTarget](gtk.DropTargetGLibType)
- RegisterType[gtk.Image](gtk.ImageGLibType)
- RegisterType[gtk.Label](gtk.LabelGLibType)
- RegisterType[gtk.ListBox](gtk.ListBoxGLibType)
- RegisterType[gtk.MenuButton](gtk.MenuButtonGLibType)
- RegisterType[gtk.ScrolledWindow](gtk.ScrolledWindowGLibType)
- RegisterType[gtk.SearchBar](gtk.SearchBarGLibType)
- RegisterType[gtk.SearchEntry](gtk.SearchEntryGLibType)
- RegisterType[gtk.Adjustment](gtk.AdjustmentGLibType)
- RegisterType[gtk.Window](gtk.WindowGLibType)
- RegisterType[adw.Spinner](adw.SpinnerGLibType)
- RegisterType[adw.ViewSwitcherSidebar](adw.ViewSwitcherSidebarGLibType)
- RegisterType[gtk.Switch](gtk.SwitchGLibType)
- RegisterType[gtk.ToggleButton](gtk.ToggleButtonGLibType)
- RegisterType[adw.ActionRow](adw.ActionRowGLibType)
- RegisterType[adw.ApplicationWindow](adw.ApplicationWindowGLibType)
- RegisterType[adw.ButtonRow](adw.ButtonRowGLibType)
- RegisterType[adw.ComboRow](adw.ComboRowGLibType)
- RegisterType[adw.EntryRow](adw.EntryRowGLibType)
- RegisterType[adw.ExpanderRow](adw.ExpanderRowGLibType)
- RegisterType[adw.NavigationSplitView](adw.NavigationSplitViewGLibType)
- RegisterType[adw.PreferencesDialog](adw.PreferencesDialogGLibType)
- RegisterType[adw.PreferencesGroup](adw.PreferencesGroupGLibType)
- RegisterType[adw.PreferencesPage](adw.PreferencesPageGLibType)
- RegisterType[adw.SpinRow](adw.SpinRowGLibType)
- RegisterType[adw.StatusPage](adw.StatusPageGLibType)
- RegisterType[adw.SwitchRow](adw.SwitchRowGLibType)
- RegisterType[adw.ToastOverlay](adw.ToastOverlayGLibType)
- RegisterType[adw.ViewStack](adw.ViewStackGLibType)
-}
-
-// FillFromUI loads the given xml data in the order that it is passed
-// and fills into with it in the same way that [FillFromBuilder] does.
-// Each xml value should be an entire XML UI definition file. Invalid
-// XML is a programming error and panics. The builder is released
-// before returning.
-func FillFromUI[T any](into *T, xml ...string) {
- builder := gtk.NewBuilder()
- defer builder.Unref()
-
- builder.SetTranslationDomain(locale.TranslationDomain)
- for _, v := range xml {
- if _, err := builder.AddFromString(v, -1); err != nil {
- panic(err)
- }
- }
-
- FillFromBuilder(into, builder)
-}
-
// ErrHasCode returns true if and only if err is a [glib.Error] and
// its error code is code.
func ErrHasCode(err error, code int) bool {