// Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build example // // This build tag means that "go install golang.org/x/exp/shiny/..." doesn't // install this example program. Use "go run main.go" to run it or "go install // -tags=example" to install it. // layout is an example of a laying out a widget node tree. Real GUI programs // won't need to do this explicitly, as the shiny/widget package will // coordinate with the shiny/screen package to call Measure, Layout and Paint // as necessary, and will re-layout widgets when windows are re-sized. This // program merely demonstrates how a widget node tree can be rendered onto a // statically sized RGBA image, for visual verification of widget code without // having to bring up and manually inspect an interactive GUI window. package main import ( "fmt" "image" "image/color" "image/draw" "image/png" "log" "os" "golang.org/x/exp/shiny/unit" "golang.org/x/exp/shiny/widget" "golang.org/x/exp/shiny/widget/node" "golang.org/x/exp/shiny/widget/theme" ) var px = unit.Pixels func colorPatch(c color.Color, w, h unit.Value) *widget.Sizer { return widget.NewSizer(w, h, widget.NewUniform(theme.StaticColor(c), nil)) } func main() { t := theme.Default // Make the widget node tree. hf := widget.NewFlow(widget.AxisHorizontal, widget.NewLabel("Cyan:"), widget.WithLayoutData( colorPatch(color.RGBA{0x00, 0x7f, 0x7f, 0xff}, px(0), px(20)), widget.FlowLayoutData{AlongWeight: 1, ExpandAlong: true}, ), widget.NewLabel("Magenta:"), widget.WithLayoutData( colorPatch(color.RGBA{0x7f, 0x00, 0x7f, 0xff}, px(0), px(30)), widget.FlowLayoutData{AlongWeight: 2, ExpandAlong: true}, ), widget.NewLabel("Yellow:"), widget.WithLayoutData( colorPatch(color.RGBA{0x7f, 0x7f, 0x00, 0xff}, px(0), px(40)), widget.FlowLayoutData{AlongWeight: 3, ExpandAlong: true}, ), ) vf := widget.NewFlow(widget.AxisVertical, colorPatch(color.RGBA{0xff, 0x00, 0x00, 0xff}, px(80), px(40)), colorPatch(color.RGBA{0x00, 0xff, 0x00, 0xff}, px(50), px(50)), colorPatch(color.RGBA{0x00, 0x00, 0xff, 0xff}, px(20), px(60)), widget.WithLayoutData( hf, widget.FlowLayoutData{ExpandAcross: true}, ), widget.NewLabel(fmt.Sprintf( "The black rectangle is 1.5 inches x 1 inch when viewed at %v DPI.", t.GetDPI())), widget.NewPadder(widget.AxisBoth, unit.Pixels(8), colorPatch(color.Black, unit.Inches(1.5), unit.Inches(1)), ), ) // Make the RGBA image. const width, height = 640, 480 rgba := image.NewRGBA(image.Rect(0, 0, width, height)) draw.Draw(rgba, rgba.Bounds(), t.GetPalette().Neutral(), image.Point{}, draw.Src) // Measure, layout and paint. vf.Measure(t, width, height) vf.Rect = rgba.Bounds() vf.Layout(t) vf.PaintBase(&node.PaintBaseContext{ Theme: t, Dst: rgba, }, image.Point{}) // Encode to PNG. out, err := os.Create("out.png") if err != nil { log.Fatalf("os.Create: %v", err) } defer out.Close() if err := png.Encode(out, rgba); err != nil { log.Fatalf("png.Encode: %v", err) } fmt.Println("Wrote out.png OK.") }