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)
}
}
}