1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
|
/*
* Copyright 2020 Dmitry Kann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package player
import (
"fmt"
"github.com/gotk3/gotk3/gtk"
"reflect"
)
// Builder instance capable of finding specific types of widgets
type Builder struct {
*gtk.Builder
}
// NewBuilder creates and returns a new Builder instance
func NewBuilder(content string) (*Builder, error) {
builder, err := gtk.BuilderNew()
if err != nil {
return nil, err
}
if err := builder.AddFromString(content); err != nil {
return nil, fmt.Errorf("builder.AddFromString() failed: %v", err)
}
return &Builder{Builder: builder}, nil
}
// BindWidgets binds the builder's widgets to same-named fields in the provided struct. Only exported fields are taken
// into account
func (b *Builder) BindWidgets(obj interface{}) error {
// We're only dealing with structs
vPtr := reflect.ValueOf(obj)
if vPtr.Kind() != reflect.Ptr || vPtr.IsNil() || vPtr.Elem().Kind() != reflect.Struct {
return fmt.Errorf("*struct expected, %T was given", obj)
}
// Fetch a value for the struct vPtr points to
v := vPtr.Elem()
// Iterate over struct's fields
t := v.Type()
for i := 0; i < t.NumField(); i++ {
valField := v.Field(i)
if valField.CanSet() {
// Verify it's a pointer
typeField := t.Field(i)
if valField.Kind() != reflect.Ptr {
return fmt.Errorf("struct's field %s is %v, but only pointers are supported", typeField.Name, valField.Kind())
}
// Try to find a widget with the field's name
widget, err := b.GetObject(typeField.Name)
if err != nil {
return err
}
// Try to cast the value to the target type
var targetVal reflect.Value
func() {
err = nil
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("failed to cast IObject (ID=%s) to %s: %v", typeField.Name, typeField.Type, r)
}
}()
targetVal = reflect.ValueOf(widget).Convert(typeField.Type)
}()
if err != nil {
return err
}
// Set the value. Any possible panic won't be recovered
valField.Set(targetVal)
}
}
return nil
}
|