ref: 7084ab4489ce1ddb6595a8f2624e8fdf23a73d8f
dir: /main.go/
package main import ( "9fans.net/go/draw" "bytes" "fmt" "image" imagedraw "image/draw" "flag" "github.com/mjl-/duit" "github.com/psilva261/szdd" xdraw "golang.org/x/image/draw" "log" "math" "os" _ "golang.org/x/image/bmp" _ "image/gif" _ "image/jpeg" _ "image/png" ) var ( dui *duit.DUI scale int ) type Folder struct { *duit.Image Pre string Suf string Name string Items map[string]string Targets []Target } func getFolder(root, pre string) (ff *Folder) { //log.Printf("getFolder(%v, %v)", root, pre) var rf *Folder if root != "" { for _, f := range folders { if f.Pre == root { rf = f } } } for _, f := range folders { if f.Pre == pre { ff = f } } var fn string if ff != nil { fn = ff.Main() } else { ff = rf fn = ff.getItem(pre) } ff.Image = &duit.Image{ Image: readImagePath(fn), } return } func (f Folder) Main() string { fnSuf := f.Suf if _, ok := f.Items[f.Suf]; !ok { fnSuf = "0001" } return fmt.Sprintf("./data/about/%v%v/%v%v.dib", f.Pre, f.Suf, f.Pre, fnSuf) } func (f Folder) getItem(k string) string { fnSuf := k return fmt.Sprintf("./data/about/%v%v/%v%v.dib", f.Pre, f.Suf, f.Pre, fnSuf) } func (f *Folder) Mouse(dui *duit.DUI, self *duit.Kid, m draw.Mouse, origM draw.Mouse, orig image.Point) (r duit.Result) { if m.Buttons&1 == 1 { //log.Printf("m=%+v, origM=%+v", m, origM) for _, t := range f.Targets { if t.has(m.Point) { tf := getFolder(f.Pre, t.key) dui.Top.UI = tf dui.MarkLayout(dui.Top.UI) dui.MarkDraw(dui.Top.UI) dui.Render() } } return duit.Result{ Consumed: true, } } else if m.Buttons&4 == 4 { tf := getFolder("", "cont") dui.Top.UI = tf dui.MarkLayout(dui.Top.UI) dui.MarkDraw(dui.Top.UI) dui.Render() } return f.Image.Mouse(dui, self, m, origM, orig) } type Target struct { key string xy draw.Point r int } func (t Target) has(p draw.Point) bool { x := p.X * 2 / scale y := p.Y * 2 / scale return math.Abs(float64(x)-float64(t.xy.X)) < float64(t.r) && math.Abs(float64(y)-float64(t.xy.Y)) < float64(t.r) } var folders = []*Folder{ &Folder{ Pre: "afri", Suf: "00aa", Name: "Africa", Items: map[string]string{ "00aa": "Waterhole", "00fb": "Art", }, }, &Folder{ Pre: "atls", Suf: "00nv", Name: "Atlas", Items: map[string]string{ "00nv": "Continents", "01p1": "African reptiles", "01p2": "African herbivores", "01pu": "Africa", "02pu": "Asia", "03pu": "Australia", "04pu": "Europe", "05pu": "North America", "06pu": "South America", }, Targets: []Target{ Target{ key: "01pu", xy: draw.Point{ X: 659, Y: 461, }, r: 100, }, Target{ key: "02pu", xy: draw.Point{ X: 931, Y: 275, }, r: 200, }, Target{ key: "03pu", xy: draw.Point{ X: 1117, Y: 603, }, r: 50, }, Target{ key: "04pu", xy: draw.Point{ X: 600, Y: 262, }, r: 50, }, Target{ key: "05pu", xy: draw.Point{ X: 222, Y: 270, }, r: 140, }, Target{ key: "06pu", xy: draw.Point{ X: 350, Y: 552, }, r: 120, }, }, }, &Folder{ Pre: "aust", Suf: "00aa", Name: "Australia", Items: map[string]string{ "00aa": "Oddities", }, }, &Folder{ Pre: "beet", Suf: "00aa", Name: "Beetles", Items: map[string]string{ "00aa": "Beetles", }, }, &Folder{ Pre: "frst", Suf: "00aa", Name: "Forest", Items: map[string]string{ "00aa": "Forest Environments", }, }, &Folder{ Pre: "cont", Suf: "00nv", Name: "Contents", Items: map[string]string{ "00nv": "Contents", }, Targets: []Target{ Target{ key: "atls", xy: draw.Point{ X: 242, Y: 190, }, r: 150, }, Target{ key: "habt", xy: draw.Point{ X: 256, Y: 588, }, r: 200, }, Target{ key: "indx", xy: draw.Point{ X: 920, Y: 614, }, r: 200, }, Target{ key: "weap", xy: draw.Point{ X: 997, Y: 200, }, r: 200, }, }, }, &Folder{ Pre: "guid", Suf: "00nv", Name: "Guides", Items: map[string]string{ "00nv": "Guides", }, }, &Folder{ Pre: "habt", Suf: "00nv", Name: "Habitats", Items: map[string]string{ "00nv": "Habitats", }, }, &Folder{ Pre: "help", Suf: "00nv", Name: "Help", Items: map[string]string{ "00nv": "Help", }, }, &Folder{ Pre: "indx", Suf: "00nv", Name: "Index", Items: map[string]string{ "0001": "Index", }, Targets: []Target{ Target{ key: "0001", xy: draw.Point{ X: 48, Y: 90, }, r: 25, }, Target{ key: "0002", xy: draw.Point{ X: 97, Y: 90, }, r: 25, }, Target{ key: "0003", xy: draw.Point{ X: 144, Y: 90, }, r: 25, }, Target{ key: "0003", xy: draw.Point{ X: 186, Y: 90, }, r: 25, }, Target{ key: "0004", xy: draw.Point{ X: 236, Y: 90, }, r: 25, }, Target{ key: "0005", xy: draw.Point{ X: 340, Y: 90, }, r: 40, }, Target{ key: "0006", xy: draw.Point{ X: 440, Y: 90, }, r: 40, }, Target{ key: "0007", xy: draw.Point{ X: 600, Y: 90, }, r: 90, }, Target{ key: "0008", xy: draw.Point{ X: 748, Y: 90, }, r: 40, }, Target{ key: "0009", xy: draw.Point{ X: 843, Y: 90, }, r: 38, }, Target{ key: "0010", xy: draw.Point{ X: 947, Y: 90, }, r: 60, }, Target{ key: "0011", xy: draw.Point{ X: 1112, Y: 90, }, r: 85, }, }, }, /*Folder{ Pre: "titl", Suf: "00nv", Name: "Title", Items: map[string]string{ "00nv": "Title", }, },*/ &Folder{ Pre: "weap", Suf: "00nv", Name: "Index", Items: map[string]string{ "00nv": "Index", }, Targets: []Target{ Target{ key: "01pu", xy: draw.Point{ X: 250, Y: 400, }, r: 150, }, Target{ key: "03pu", xy: draw.Point{ X: 654, Y: 375, }, r: 150, }, Target{ key: "02pu", xy: draw.Point{ X: 1047, Y: 400, }, r: 150, }, }, }, } func check(err error, msg string) { if err != nil { log.Fatalf("%s: %s\n", msg, err) } } func resize(img image.Image, scale int) image.Image { bounds := img.Bounds() newX := bounds.Dx() * 2 newY:= bounds.Dy() * 2 dst := image.NewRGBA(image.Rect(0, 0, newX, newY)) xdraw.NearestNeighbor.Scale(dst, dst.Rect, img, img.Bounds(), xdraw.Over, nil) return dst } func readImagePath(path string) *draw.Image { bs, err := os.ReadFile(path) check(err, "read file") data, err := szdd.Expand(bs) check(err, "expand") img, _, err := image.Decode(bytes.NewReader(data)) check(err, "decode") if scale > 1 { img = resize(img, scale) } bounds := img.Bounds() ni, err := dui.Display.AllocImage(bounds, draw.ABGR32, false, draw.White) check(err, "allocimage") var rgba *image.RGBA switch i := img.(type) { case *image.RGBA: rgba = i default: b := img.Bounds() rgba = image.NewRGBA(image.Rectangle{image.ZP, b.Size()}) imagedraw.Draw(rgba, rgba.Bounds(), img, b.Min, imagedraw.Src) } _, err = ni.Load(rgba.Bounds(), rgba.Pix) check(err, "load image") return ni } func main() { sc := flag.Int("x", 0, "scale") flag.Parse() scale = *sc var err error dui, err = duit.NewDUI("wildlife", nil) check(err, "new dui") if scale == 0 { if dui.Display.DPI > 100 { scale = 2 } else { scale = 1 } } _=readImagePath f := getFolder("", "cont") dui.Top.UI = f dui.Render() for { select { case e := <-dui.Inputs: dui.Input(e) case err, ok := <-dui.Error: if !ok { return } log.Printf("duit: %s\n", err) } } }