From d6ae3afeb4b5e9550f6c6b088ba30265d2a9c1a9 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Thu, 16 Oct 2014 19:35:50 -0400 Subject: [PATCH] Added margined to Group and reworked the test. Now for spacing. --- newctrl/basicctrls.go | 5 + newctrl/container.go | 3 - newctrl/group_windows.go | 12 +- newctrl/zz_test.go | 284 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 299 insertions(+), 5 deletions(-) create mode 100644 newctrl/zz_test.go diff --git a/newctrl/basicctrls.go b/newctrl/basicctrls.go index 5b28975..1ef720b 100644 --- a/newctrl/basicctrls.go +++ b/newctrl/basicctrls.go @@ -110,6 +110,11 @@ type Group interface { // Text and SetText get and set the Group's label text. Text() string SetText(text string) + + // Margined and SetMargined get and set whether the contents of the Group have a margin around them. + // The size of the margin is platform-dependent. + Margined() bool + SetMargined(margined bool) } // NewGroup creates a new Group with the given text label and child Control. diff --git a/newctrl/container.go b/newctrl/container.go index ea7449f..27674d0 100644 --- a/newctrl/container.go +++ b/newctrl/container.go @@ -9,9 +9,6 @@ type sizingbase struct { // The container type, which is defined per-platform, is an internal Control that is only used to house other Controls from the underlying UI toolkit's point of view -// set to true to apply spacing to all windows -var spaced bool = false - /* TODO func (c *container) resize(x, y, width, height int) { if c.child == nil { // no children; nothing to do diff --git a/newctrl/group_windows.go b/newctrl/group_windows.go index 2ce434c..ee406d8 100644 --- a/newctrl/group_windows.go +++ b/newctrl/group_windows.go @@ -36,6 +36,14 @@ func (g *group) SetText(text string) { g.setText(text) } +func (g *group) Margined() bool { + return g.margined +} + +func (g *group) SetMargined(margined bool) { + g.margined = margined +} + const ( groupXMargin = 6 groupYMarginTop = 11 // note this value /includes the groupbox label/ @@ -55,10 +63,10 @@ func (g *group) preferredSize(d *sizing) (width, height int) { r.bottom = C.LONG(height) // use negative numbers to increase the size of the rectangle if g.margined { - // unforutnately, as mentioned above, the size of a groupbox includes the label and border - // 1DLU on each side should be enough to make up for that; if not, we can change it marginRectDLU(&r, -groupYMarginTop, -groupYMarginBottom, -groupXMargin, -groupXMargin, d) } else { + // unforutnately, as mentioned above, the size of a groupbox includes the label and border + // 1DLU on each side should be enough to make up for that; TODO is not, we can change it // TODO make these named constants marginRectDLU(&r, -1, -1, -1, -1, d) } diff --git a/newctrl/zz_test.go b/newctrl/zz_test.go new file mode 100644 index 0000000..cb8bf60 --- /dev/null +++ b/newctrl/zz_test.go @@ -0,0 +1,284 @@ +// 8 july 2014 + +package ui + +// This file is called zz_test.go to keep it separate from the other files in this package (and because go test won't accept just test.go) + +import ( + "flag" + "fmt" + "image" + "image/color" + "image/draw" + "reflect" + "strings" + "testing" + "time" +) + +var closeOnClick = flag.Bool("close", false, "close on click") +var smallWindow = flag.Bool("small", false, "open a small window (test Mac OS X initial control sizing)") +var spaced = flag.Bool("spaced", false, "enable spacing") + +type dtype struct { + Name string + Address string +} + +var ddata = []dtype{ + {"alpha", "beta"}, + {"gamma", "delta"}, + {"epsilon", "zeta"}, + {"eta", "theta"}, + {"iota", "kappa"}, +} + +type testwin struct { + t Tab + w Window + repainter *repainter + fe *ForeignEvent + festack Stack + festart Button + felabel Label + festop Button + vedit TextField + openbtn Button + fnlabel Label + icons []icon + il ImageList + icontbl Table + group2 Group + group Group + simpleGrid SimpleGrid + nt Tab + a Area + spw Stack + sph Stack + s Stack + l Label + table Table + b Button + c Checkbox + e TextField + e2 TextField + + wsmall Window +} + +type areaHandler struct { + handled bool +} + +func (a *areaHandler) Paint(r image.Rectangle) *image.RGBA { + i := image.NewRGBA(r) + draw.Draw(i, r, &image.Uniform{color.RGBA{128, 0, 128, 255}}, image.ZP, draw.Src) + return i +} +func (a *areaHandler) Mouse(me MouseEvent) { fmt.Printf("%#v\n", me) } +func (a *areaHandler) Key(ke KeyEvent) bool { fmt.Printf("%#v %q\n", ke, ke.Key); return a.handled } + +func (tw *testwin) openFile(fn string) { + if fn == "" { + fn = "" + } + tw.fnlabel.SetText(fn) +} + +func (tw *testwin) addfe() { + tw.festart = NewButton("Start") + tw.festart.OnClicked(func() { + if tw.fe != nil { + tw.fe.Stop() + } + ticker := time.NewTicker(1 * time.Second) + tw.fe = NewForeignEvent(ticker.C, func(d interface{}) { + t := d.(time.Time) + tw.felabel.SetText(t.String()) + }) + }) + tw.felabel = NewLabel("") + tw.festop = NewButton("Stop") + tw.festop.OnClicked(func() { + if tw.fe != nil { + tw.fe.Stop() + tw.felabel.SetText("") + tw.fe = nil + } + }) + tw.vedit = NewTextField() + tw.vedit.OnChanged(func() { + if strings.Contains(tw.vedit.Text(), "bad") { + tw.vedit.Invalid("bad entered") + } else { + tw.vedit.Invalid("") + } + }) + tw.openbtn = NewButton("Open") + tw.openbtn.OnClicked(func() { + OpenFile(tw.w, tw.openFile) + }) + tw.fnlabel = NewLabel("") + tw.festack = NewVerticalStack(tw.festart, + tw.felabel, + tw.festop, + NewCheckbox("This is a checkbox test"), + Space(), + tw.vedit, + Space(), + NewCheckbox("This is a checkbox test"), + tw.openbtn, tw.fnlabel) + tw.festack.SetStretchy(4) + tw.festack.SetStretchy(6) + tw.festack = NewHorizontalStack(tw.festack, Space()) + tw.festack.SetStretchy(0) + tw.festack.SetStretchy(1) + tw.t.Append("Foreign Events", tw.festack) +} + +func (tw *testwin) make(done chan struct{}) { + tw.t = NewTab() + tw.w = NewWindow("Hello", 320, 240, tw.t) + tw.w.SetMargined(*spaced) + tw.w.OnClosing(func() bool { + if *closeOnClick { + panic("window closed normally in close on click mode (should not happen)") + } + println("window close event received") + Stop() + done <- struct{}{} + return true + }) + tw.icons, tw.il = readIcons() // repainter uses these + tw.repainter = newRepainter(15) + tw.t.Append("Repaint", tw.repainter.grid) + tw.addfe() + tw.icontbl = NewTable(reflect.TypeOf(icon{})) + tw.icontbl.Lock() + idq := tw.icontbl.Data().(*[]icon) + *idq = tw.icons + tw.icontbl.Unlock() + tw.icontbl.LoadImageList(tw.il) + tw.icontbl.OnSelected(func() { + s := fmt.Sprintf("%d ", tw.icontbl.Selected()) + tw.icontbl.RLock() + defer tw.icontbl.RUnlock() + idq := tw.icontbl.Data().(*[]icon) + for _, v := range *idq { + s += strings.ToUpper(fmt.Sprintf("%v", v.Bool)[0:1]) + " " + } + tw.w.SetTitle(s) + }) + tw.t.Append("Image List Table", tw.icontbl) + tw.group2 = NewGroup("Group", NewButton("Button in Group")) + tw.t.Append("Empty Group", NewGroup("Group", Space())) + tw.t.Append("Filled Group", tw.group2) + tw.group2.SetMargined(*spaced) + tw.group = NewGroup("Group", NewVerticalStack(NewCheckbox("Checkbox in Group"))) + tw.group.SetMargined(*spaced) + tw.t.Append("Group", tw.group) + tw.simpleGrid = NewSimpleGrid(3, + NewLabel("0,0"), NewTextField(), NewLabel("0,2"), + NewButton("1,0"), NewButton("1,1"), NewButton("1,2"), + NewLabel("2,0"), NewTextField(), NewLabel("2,2")) + tw.simpleGrid.SetFilling(2, 1) + tw.simpleGrid.SetFilling(1, 2) + tw.simpleGrid.SetStretchy(1, 1) + tw.t.Append("Simple Grid", tw.simpleGrid) + tw.t.Append("Blank Tab", NewTab()) + tw.nt = NewTab() + tw.nt.Append("Tab 1", Space()) + tw.nt.Append("Tab 2", Space()) + tw.t.Append("Tab", tw.nt) + tw.t.Append("Space", Space()) + tw.a = NewArea(200, 200, &areaHandler{false}) + tw.t.Append("Area", tw.a) + tw.spw = NewHorizontalStack( + NewButton("hello"), + NewCheckbox("hello"), + NewTextField(), + NewPasswordField(), + NewTable(reflect.TypeOf(struct{ A, B, C int }{})), + NewLabel("hello")) + tw.t.Append("Pref Width", tw.spw) + tw.sph = NewVerticalStack( + NewButton("hello"), + NewCheckbox("hello"), + NewTextField(), + NewPasswordField(), + NewTable(reflect.TypeOf(struct{ A, B, C int }{})), + NewLabel("hello ÉÀÔ")) + tw.t.Append("Pref Height", tw.sph) + stack1 := NewHorizontalStack(NewLabel("Test"), NewTextField()) + stack1.SetStretchy(1) + stack2 := NewHorizontalStack(NewLabel("ÉÀÔ"), NewTextField()) + stack2.SetStretchy(1) + stack3 := NewHorizontalStack(NewLabel("Test 2"), + NewTable(reflect.TypeOf(struct{ A, B, C int }{}))) + stack3.SetStretchy(1) + tw.s = NewVerticalStack(stack1, stack2, stack3) + tw.s.SetStretchy(2) + tw.t.Append("Stack", tw.s) + tw.l = NewLabel("hello") + tw.t.Append("Label", tw.l) + tw.table = NewTable(reflect.TypeOf(ddata[0])) + tw.table.Lock() + dq := tw.table.Data().(*[]dtype) + *dq = ddata + tw.table.Unlock() + tw.t.Append("Table", tw.table) + tw.b = NewButton("There") + if *closeOnClick { + tw.b.SetText("Click to Close") + } + tw.b.OnClicked(func() { + println("in OnClicked()") + if *closeOnClick { + tw.w.Close() + Stop() + done <- struct{}{} + } + }) + tw.t.Append("Button", tw.b) + tw.c = NewCheckbox("You Should Now See Me Instead") + tw.c.OnToggled(func() { + tw.w.SetTitle(fmt.Sprint(tw.c.Checked())) + }) + tw.t.Append("Checkbox", tw.c) + tw.e = NewTextField() + tw.t.Append("Text Field", tw.e) + tw.e2 = NewPasswordField() + tw.t.Append("Password Field", tw.e2) + tw.w.Show() + if *smallWindow { + tw.wsmall = NewWindow("Small", 80, 80, + NewVerticalStack( + NewButton("Small"), + NewButton("Small 2"), + NewArea(200, 200, &areaHandler{true}))) + tw.wsmall.Show() + } +} + +// this must be on the heap thanks to moving stacks +// soon even this won't be enough... +var tw *testwin + +// because Cocoa hates being run off the main thread, even if it's run exclusively off the main thread +func init() { + flag.Parse() + go func() { + tw = new(testwin) + done := make(chan struct{}) + Do(func() { tw.make(done) }) + <-done + }() + err := Go() + if err != nil { + panic(err) + } +} + +func TestDummy(t *testing.T) { + // do nothing +}