Added bounds checking to NewArea() and Area.SetSize() such that an Area must have a valid size.
This commit is contained in:
parent
1c11ef2d9c
commit
d6abf79932
13
area.go
13
area.go
|
@ -3,6 +3,7 @@
|
||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
"image"
|
"image"
|
||||||
)
|
)
|
||||||
|
@ -10,6 +11,7 @@ import (
|
||||||
// Area represents a blank canvas upon which programs may draw anything and receive arbitrary events from the user.
|
// Area represents a blank canvas upon which programs may draw anything and receive arbitrary events from the user.
|
||||||
// An Area has an explicit size, represented in pixels, that may be different from the size shown in its Window; Areas have horizontal and vertical scrollbars that are hidden when not needed.
|
// An Area has an explicit size, represented in pixels, that may be different from the size shown in its Window; Areas have horizontal and vertical scrollbars that are hidden when not needed.
|
||||||
// The coordinate system of an Area always has an origin of (0,0) which maps to the top-left corner; all image.Points and image.Rectangles sent across Area's channels conform to this.
|
// The coordinate system of an Area always has an origin of (0,0) which maps to the top-left corner; all image.Points and image.Rectangles sent across Area's channels conform to this.
|
||||||
|
// The size of an Area must be at least 1x1 (that is, neither its width nor its height may be zero or negative).
|
||||||
//
|
//
|
||||||
// To handle events to the Area, an Area must be paired with an AreaHandler.
|
// To handle events to the Area, an Area must be paired with an AreaHandler.
|
||||||
// See AreaHandler for details.
|
// See AreaHandler for details.
|
||||||
|
@ -260,9 +262,16 @@ const (
|
||||||
// TODO add Super
|
// TODO add Super
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func checkAreaSize(width int, height int, which string) {
|
||||||
|
if width <= 0 || height <= 0 {
|
||||||
|
panic(fmt.Errorf("invalid size %dx%d in %s", width, height, which))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewArea creates a new Area with the given size and handler.
|
// NewArea creates a new Area with the given size and handler.
|
||||||
// It panics if handler is nil.
|
// It panics if handler is nil or if width or height is zero or negative.
|
||||||
func NewArea(width int, height int, handler AreaHandler) *Area {
|
func NewArea(width int, height int, handler AreaHandler) *Area {
|
||||||
|
checkAreaSize(width, height, "NewArea()")
|
||||||
if handler == nil {
|
if handler == nil {
|
||||||
panic("handler passed to NewArea() must not be nil")
|
panic("handler passed to NewArea() must not be nil")
|
||||||
}
|
}
|
||||||
|
@ -276,10 +285,12 @@ func NewArea(width int, height int, handler AreaHandler) *Area {
|
||||||
|
|
||||||
// SetSize sets the Area's internal drawing size.
|
// SetSize sets the Area's internal drawing size.
|
||||||
// It has no effect on the actual control size.
|
// It has no effect on the actual control size.
|
||||||
|
// It panics if width or height is zero or negative.
|
||||||
func (a *Area) SetSize(width int, height int) {
|
func (a *Area) SetSize(width int, height int) {
|
||||||
a.lock.Lock()
|
a.lock.Lock()
|
||||||
defer a.lock.Unlock()
|
defer a.lock.Unlock()
|
||||||
|
|
||||||
|
checkAreaSize(width, height, "Area.SetSize()")
|
||||||
if a.created {
|
if a.created {
|
||||||
a.sysData.setAreaSize(width, height)
|
a.sysData.setAreaSize(width, height)
|
||||||
return
|
return
|
||||||
|
|
29
test/main.go
29
test/main.go
|
@ -78,6 +78,7 @@ func invalidTest(c *Combobox, l *Listbox, s *Stack, g *Grid) {
|
||||||
func() {
|
func() {
|
||||||
defer x("Listbox.Delete > len"); l.Delete(c.Len() + 5); panic(nil)
|
defer x("Listbox.Delete > len"); l.Delete(c.Len() + 5); panic(nil)
|
||||||
}()
|
}()
|
||||||
|
// TODO get rid of arg != nil by creating dummy arg
|
||||||
if s != nil {
|
if s != nil {
|
||||||
func() {
|
func() {
|
||||||
defer x("Stack.SetStretchy < 0"); s.SetStretchy(-5); panic(nil)
|
defer x("Stack.SetStretchy < 0"); s.SetStretchy(-5); panic(nil)
|
||||||
|
@ -86,6 +87,7 @@ func invalidTest(c *Combobox, l *Listbox, s *Stack, g *Grid) {
|
||||||
defer x("Stack.SetStretchy > len"); s.SetStretchy(5555); panic(nil)
|
defer x("Stack.SetStretchy > len"); s.SetStretchy(5555); panic(nil)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
// TODO grid creation checks
|
||||||
if g != nil {
|
if g != nil {
|
||||||
func() {
|
func() {
|
||||||
defer x("Grid.SetFilling x < 0"); g.SetFilling(-5, 0); panic(nil)
|
defer x("Grid.SetFilling x < 0"); g.SetFilling(-5, 0); panic(nil)
|
||||||
|
@ -112,6 +114,33 @@ func invalidTest(c *Combobox, l *Listbox, s *Stack, g *Grid) {
|
||||||
defer x("Grid.SetStretchy y > len"); g.SetStretchy(0, 5555); panic(nil)
|
defer x("Grid.SetStretchy y > len"); g.SetStretchy(0, 5555); panic(nil)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
ah := &areaHandler{nil}
|
||||||
|
type at struct {
|
||||||
|
msg string
|
||||||
|
x, y int
|
||||||
|
}
|
||||||
|
var ats = []at{
|
||||||
|
at{"width < 0", -5, 5},
|
||||||
|
at{"width == 0", 0, 5},
|
||||||
|
at{"height < 0", 5, -5},
|
||||||
|
at{"height == 0", 5, 0},
|
||||||
|
at{"width/heght < 0", -5, -5},
|
||||||
|
at{"width < 0/height == 0", -5, 0},
|
||||||
|
at{"width == 0/height < 0", 0, -5},
|
||||||
|
at{"width/height == 0", 0, 0},
|
||||||
|
}
|
||||||
|
for _, q := range ats {
|
||||||
|
func() {
|
||||||
|
defer x("NewArea() " + q.msg); NewArea(q.x, q.y, ah); panic(nil)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
// no need to pass this in as an argument since it's handled by the portable code, not by sysData
|
||||||
|
a := NewArea(50, 50, ah)
|
||||||
|
for _, q := range ats {
|
||||||
|
func() {
|
||||||
|
defer x("Area.SetSize() " + q.msg); a.SetSize(q.x, q.y); panic(nil)
|
||||||
|
}()
|
||||||
|
}
|
||||||
MsgBox("test", "all working as intended")
|
MsgBox("test", "all working as intended")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
todo.md
1
todo.md
|
@ -1,5 +1,4 @@
|
||||||
so I don't forget:
|
so I don't forget:
|
||||||
- add bounds checking to Area's sizing methods
|
|
||||||
- describe thread-safety of Area.SetSize()
|
- describe thread-safety of Area.SetSize()
|
||||||
- should all instances of -1 as error returns from Windows functions be changed to ^0 or does the uintptr() conversion handle sign extension?
|
- should all instances of -1 as error returns from Windows functions be changed to ^0 or does the uintptr() conversion handle sign extension?
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue