shithub: wildlife

ref: 7084ab4489ce1ddb6595a8f2624e8fdf23a73d8f
dir: /main.go/

View raw version
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)
		}
	}
}