summaryrefslogtreecommitdiff
path: root/gui/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'gui/cmd')
-rw-r--r--gui/cmd/hello/main.go5
-rw-r--r--gui/cmd/spike/main.go106
-rw-r--r--gui/cmd/text/main.go66
3 files changed, 177 insertions, 0 deletions
diff --git a/gui/cmd/hello/main.go b/gui/cmd/hello/main.go
new file mode 100644
index 0000000..26b925b
--- /dev/null
+++ b/gui/cmd/hello/main.go
@@ -0,0 +1,5 @@
+package main
+
+import "fmt"
+
+func main() { fmt.Println("hello from go on plan9") }
diff --git a/gui/cmd/spike/main.go b/gui/cmd/spike/main.go
new file mode 100644
index 0000000..442df52
--- /dev/null
+++ b/gui/cmd/spike/main.go
@@ -0,0 +1,106 @@
+// Spike: prove that a Plan 9 GUI can be written in Go with nothing but the
+// standard library -- no C, no cgo, no libdraw, no window system.
+//
+// Draws a panel layout and a cursor block that tracks the mouse.
+// Button 3 quits; so does the deadline, so a forgotten instance on a VM
+// does not sit on /dev/draw forever.
+package main
+
+import (
+ "fmt"
+ "os"
+ "time"
+
+ "9front/gui/draw"
+)
+
+func main() {
+ if err := run(); err != nil {
+ fmt.Fprintf(os.Stderr, "spike: %v\n", err)
+ os.Exit(1)
+ }
+}
+
+func run() error {
+ d, err := draw.Init("/dev")
+ if err != nil {
+ return err
+ }
+ defer d.Close()
+ if d.Screen == nil {
+ return fmt.Errorf("draw device gave no screen image")
+ }
+ scr := d.Screen
+ r := scr.Rect()
+ fmt.Fprintf(os.Stderr, "spike: screen %dx%d\n", r.Dx(), r.Dy())
+
+ col := map[string]uint32{}
+ img := map[string]*draw.Image{}
+ for name, v := range map[string]uint32{
+ "bg": 0x2B3A42FF,
+ "panel": 0x3F5765FF,
+ "accent": 0xBDD4DEFF,
+ "hot": 0xEFA00BFF,
+ } {
+ col[name] = v
+ if img[name], err = d.Color(v); err != nil {
+ return err
+ }
+ }
+
+ // Static layout: a header bar and three panels, laid out by arithmetic
+ // rather than by hand-placed constants. This is the seam where a real
+ // layout pass would go.
+ repaint := func() {
+ draw.Draw(scr, r, img["bg"], nil, draw.ZP)
+ hdr := draw.Rect(r.Min.X, r.Min.Y, r.Max.X, r.Min.Y+40)
+ draw.Draw(scr, hdr, img["accent"], nil, draw.ZP)
+
+ const gap = 12
+ top := r.Min.Y + 40 + gap
+ w := (r.Dx() - 4*gap) / 3
+ for i := int32(0); i < 3; i++ {
+ x := r.Min.X + gap + i*(w+gap)
+ p := draw.Rect(x, top, x+w, r.Max.Y-gap)
+ draw.Draw(scr, p, img["panel"], nil, draw.ZP)
+ }
+ }
+ repaint()
+ d.Flush()
+
+ mc, err := draw.OpenMouse("/dev")
+ if err != nil {
+ return err
+ }
+ defer mc.Close()
+
+ deadline := time.After(10 * time.Minute)
+ cursor := draw.Rect(0, 0, 28, 28)
+ var last draw.Rectangle
+ for {
+ select {
+ case m, ok := <-mc.C:
+ if !ok {
+ return nil
+ }
+ if m.Buttons&4 != 0 {
+ return nil
+ }
+ // Damage repair without a full repaint: erase where the
+ // block was, then draw it where the mouse is now.
+ if last != (draw.Rectangle{}) {
+ repaint()
+ }
+ now := cursor.Add(draw.Point{X: m.X - 14, Y: m.Y - 14})
+ draw.Draw(scr, now, img["hot"], nil, draw.ZP)
+ d.Flush()
+ last = now
+ case <-mc.Resize:
+ r = scr.Rect()
+ repaint()
+ d.Flush()
+ case <-deadline:
+ return nil
+ }
+ }
+}
diff --git a/gui/cmd/text/main.go b/gui/cmd/text/main.go
new file mode 100644
index 0000000..f1e2a9f
--- /dev/null
+++ b/gui/cmd/text/main.go
@@ -0,0 +1,66 @@
+// text: prove the font layer draws glyphs on the raw screen.
+package main
+
+import (
+ "fmt"
+ "os"
+ "time"
+
+ "9front/gui/draw"
+)
+
+const fontpath = "/lib/font/bit/lucidasans/unicode.8.font"
+
+func main() {
+ if err := run(); err != nil {
+ fmt.Fprintf(os.Stderr, "text: %v\n", err)
+ os.Exit(1)
+ }
+}
+
+func run() error {
+ d, err := draw.Init("/dev")
+ if err != nil {
+ return err
+ }
+ defer d.Close()
+ scr := d.Screen
+ r := scr.Rect()
+
+ f, err := d.OpenFont(fontpath)
+ if err != nil {
+ return err
+ }
+ fmt.Fprintf(os.Stderr, "text: font h=%d ascent=%d\n", f.Height, f.Ascent)
+
+ // acme's palette: a 25% mix over white, per allocimagemix.
+ bg, err := d.Color(0xFFFFEAFF)
+ if err != nil {
+ return err
+ }
+ ink, err := d.Color(0x000000FF)
+ if err != nil {
+ return err
+ }
+ rule, err := d.Color(0x99994CFF)
+ if err != nil {
+ return err
+ }
+
+ draw.Draw(scr, r, bg, nil, draw.ZP)
+ y := r.Min.Y + 20
+ for _, s := range []string{
+ "Go on Plan 9: glyphs from /lib/font/bit, no libdraw.",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz",
+ "0123456789 !@#$%^&*()-=[]{};'\\:\"|,./<>?",
+ "width(\"hello\") = " + fmt.Sprint(f.Width("hello")) + " px",
+ time.Now().Format("Mon 2 Jan 2006 15:04:05"),
+ } {
+ f.String(scr, draw.Point{X: r.Min.X + 20, Y: y}, ink, s)
+ y += int32(f.Height) + 6
+ }
+ draw.Draw(scr, draw.Rect(r.Min.X+20, y+8, r.Min.X+520, y+9), rule, nil, draw.ZP)
+ d.Flush()
+ time.Sleep(90 * time.Second)
+ return nil
+}