Fixed Mac OS X control placement flipping. This is done by passing the height of the window around setRect() calls to avoid polling the content view frame each time.

This commit is contained in:
Pietro Gagliardi 2014-03-03 17:44:03 -05:00
parent 6c33892831
commit 962a84e056
17 changed files with 37 additions and 30 deletions

View File

@ -62,11 +62,11 @@ func (b *Button) make(window *sysData) error {
return nil return nil
} }
func (b *Button) setRect(x int, y int, width int, height int) error { func (b *Button) setRect(x int, y int, width int, height int, winheight int) error {
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
return b.sysData.setRect(x, y, width, height) return b.sysData.setRect(x, y, width, height, winheight)
} }
func (b *Button) preferredSize() (width int, height int, err error) { func (b *Button) preferredSize() (width int, height int, err error) {

View File

@ -68,11 +68,11 @@ func (c *Checkbox) make(window *sysData) error {
return nil return nil
} }
func (c *Checkbox) setRect(x int, y int, width int, height int) error { func (c *Checkbox) setRect(x int, y int, width int, height int, winheight int) error {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
return c.sysData.setRect(x, y, width, height) return c.sysData.setRect(x, y, width, height, winheight)
} }
func (c *Checkbox) preferredSize() (width int, height int, err error) { func (c *Checkbox) preferredSize() (width int, height int, err error) {

View File

@ -113,11 +113,11 @@ func (c *Combobox) make(window *sysData) (err error) {
return nil return nil
} }
func (c *Combobox) setRect(x int, y int, width int, height int) error { func (c *Combobox) setRect(x int, y int, width int, height int, winheight int) error {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
return c.sysData.setRect(x, y, width, height) return c.sysData.setRect(x, y, width, height, winheight)
} }
func (c *Combobox) preferredSize() (width int, height int, err error) { func (c *Combobox) preferredSize() (width int, height int, err error) {

View File

@ -8,6 +8,6 @@ import (
// A Control represents an UI control. Note that Control contains unexported members; this has the consequence that you can't build custom controls that interface directly with the system-specific code (fo rinstance, to import an unsupported control), or at least not without some hackery. If you want to make your own controls, embed Area and provide its necessities. // A Control represents an UI control. Note that Control contains unexported members; this has the consequence that you can't build custom controls that interface directly with the system-specific code (fo rinstance, to import an unsupported control), or at least not without some hackery. If you want to make your own controls, embed Area and provide its necessities.
type Control interface { type Control interface {
make(window *sysData) error make(window *sysData) error
setRect(x int, y int, width int, height int) error setRect(x int, y int, width int, height int, winheight int) error
preferredSize() (width int, height int, err error) preferredSize() (width int, height int, err error)
} }

View File

@ -88,7 +88,8 @@ func appDelegate_windowDidResize(self C.id, sel C.SEL, notification C.id) {
wincv := C.objc_msgSend_noargs(win, _contentView) // we want the content view's size, not the window's; selector defined in sysdata_darwin.go wincv := C.objc_msgSend_noargs(win, _contentView) // we want the content view's size, not the window's; selector defined in sysdata_darwin.go
r := C.objc_msgSend_stret_rect_noargs(wincv, _frame) r := C.objc_msgSend_stret_rect_noargs(wincv, _frame)
if sysData.resize != nil { if sysData.resize != nil {
err := sysData.resize(int(r.x), int(r.y), int(r.width), int(r.height)) // winheight is used here because (0,0) is the bottom-left corner, not the top-left corner
err := sysData.resize(int(r.x), int(r.y), int(r.width), int(r.height), int(r.height))
if err != nil { if err != nil {
panic("child resize failed: " + err.Error()) panic("child resize failed: " + err.Error())
} }

View File

@ -109,7 +109,7 @@ func (g *Grid) make(window *sysData) error {
return nil return nil
} }
func (g *Grid) setRect(x int, y int, width int, height int) error { func (g *Grid) setRect(x int, y int, width int, height int, winheight int) error {
g.lock.Lock() g.lock.Lock()
defer g.lock.Unlock() defer g.lock.Unlock()
@ -165,7 +165,7 @@ func (g *Grid) setRect(x int, y int, width int, height int) error {
w = g.colwidths[col] w = g.colwidths[col]
h = g.rowheights[row] h = g.rowheights[row]
} }
err := c.setRect(x, y, w, h) err := c.setRect(x, y, w, h, winheight)
if err != nil { if err != nil {
return fmt.Errorf("error setting size of control (%d,%d) in Grid.setRect(): %v", row, col, err) return fmt.Errorf("error setting size of control (%d,%d) in Grid.setRect(): %v", row, col, err)
} }

View File

@ -56,11 +56,11 @@ func (l *Label) make(window *sysData) error {
return nil return nil
} }
func (l *Label) setRect(x int, y int, width int, height int) error { func (l *Label) setRect(x int, y int, width int, height int, winheight int) error {
l.lock.Lock() l.lock.Lock()
defer l.lock.Unlock() defer l.lock.Unlock()
return l.sysData.setRect(x, y, width, height) return l.sysData.setRect(x, y, width, height, winheight)
} }
func (l *Label) preferredSize() (width int, height int, err error) { func (l *Label) preferredSize() (width int, height int, err error) {

View File

@ -68,11 +68,11 @@ func (l *LineEdit) make(window *sysData) error {
return nil return nil
} }
func (l *LineEdit) setRect(x int, y int, width int, height int) error { func (l *LineEdit) setRect(x int, y int, width int, height int, winheight int) error {
l.lock.Lock() l.lock.Lock()
defer l.lock.Unlock() defer l.lock.Unlock()
return l.sysData.setRect(x, y, width, height) return l.sysData.setRect(x, y, width, height, winheight)
} }
func (l *LineEdit) preferredSize() (width int, height int, err error) { func (l *LineEdit) preferredSize() (width int, height int, err error) {

View File

@ -104,11 +104,11 @@ func (l *Listbox) make(window *sysData) (err error) {
return nil return nil
} }
func (l *Listbox) setRect(x int, y int, width int, height int) error { func (l *Listbox) setRect(x int, y int, width int, height int, winheight int) error {
l.lock.Lock() l.lock.Lock()
defer l.lock.Unlock() defer l.lock.Unlock()
return l.sysData.setRect(x, y, width, height) return l.sysData.setRect(x, y, width, height, winheight)
} }
func (l *Listbox) preferredSize() (width int, height int, err error) { func (l *Listbox) preferredSize() (width int, height int, err error) {

View File

@ -49,11 +49,11 @@ func (p *ProgressBar) make(window *sysData) error {
return nil return nil
} }
func (p *ProgressBar) setRect(x int, y int, width int, height int) error { func (p *ProgressBar) setRect(x int, y int, width int, height int, winheight int) error {
p.lock.Lock() p.lock.Lock()
defer p.lock.Unlock() defer p.lock.Unlock()
return p.sysData.setRect(x, y, width, height) return p.sysData.setRect(x, y, width, height, winheight)
} }
func (p *ProgressBar) preferredSize() (width int, height int, err error) { func (p *ProgressBar) preferredSize() (width int, height int, err error) {

View File

@ -63,7 +63,7 @@ func (s *Stack) make(window *sysData) error {
return nil return nil
} }
func (s *Stack) setRect(x int, y int, width int, height int) error { func (s *Stack) setRect(x int, y int, width int, height int, winheight int) error {
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock() defer s.lock.Unlock()
@ -112,7 +112,7 @@ func (s *Stack) setRect(x int, y int, width int, height int) error {
} }
// 3) now actually place controls // 3) now actually place controls
for i, c := range s.controls { for i, c := range s.controls {
err := c.setRect(x, y, s.width[i], s.height[i]) err := c.setRect(x, y, s.width[i], s.height[i], winheight)
if err != nil { if err != nil {
return fmt.Errorf("error setting size of control %d in Stack.setRect(): %v", i, err) return fmt.Errorf("error setting size of control %d in Stack.setRect(): %v", i, err)
} }

View File

@ -51,7 +51,8 @@ func stdWndProc(s *sysData) func(hwnd _HWND, uMsg uint32, wParam _WPARAM, lParam
if r1 == 0 { if r1 == 0 {
panic("GetClientRect failed: " + err.Error()) panic("GetClientRect failed: " + err.Error())
} }
err = s.resize(int(r.Left), int(r.Top), int(r.Right), int(r.Bottom)) // top-left corner is (0,0) so no need for winheight
err = s.resize(int(r.Left), int(r.Top), int(r.Right), int(r.Bottom), 0)
if err != nil { if err != nil {
panic("child resize failed: " + err.Error()) panic("child resize failed: " + err.Error())
} }

View File

@ -16,7 +16,7 @@ func Event() chan struct{} {
type cSysData struct { type cSysData struct {
ctype int ctype int
event chan struct{} event chan struct{}
resize func(x int, y int, width int, height int) error resize func(x int, y int, width int, height int, winheight int) error
alternate bool // editable for Combobox, multi-select for listbox, password for lineedit alternate bool // editable for Combobox, multi-select for listbox, password for lineedit
} }
func (c *cSysData) make(initText string, window *sysData) error { func (c *cSysData) make(initText string, window *sysData) error {
@ -31,7 +31,7 @@ func (c *cSysData) hide() error {
func (c *cSysData) setText(text string) error { func (c *cSysData) setText(text string) error {
panic(runtime.GOOS + " sysData does not define setText()") panic(runtime.GOOS + " sysData does not define setText()")
} }
func (c *cSysData) setRect(x int, y int, width int, height int) error { func (c *cSysData) setRect(x int, y int, width int, height int, winheight int) error {
panic(runtime.GOOS + " sysData does not define setRect()") panic(runtime.GOOS + " sysData does not define setRect()")
} }
func (c *cSysData) isChecked() bool { func (c *cSysData) isChecked() bool {

View File

@ -346,8 +346,10 @@ func (s *sysData) setText(text string) error {
return nil return nil
} }
func (s *sysData) setRect(x int, y int, width int, height int) error { func (s *sysData) setRect(x int, y int, width int, height int, winheight int) error {
objc_msgSend_rect(s.id, _setFrame, x, y, width, height) // winheight - y because (0,0) is the bottom-left corner of the window and not the top-left corner
// (winheight - y) - height because (x, y) is the bottom-left corner of the control and not the top-left
objc_msgSend_rect(s.id, _setFrame, x, (winheight - y) - height, width, height)
return nil return nil
} }

View File

@ -45,7 +45,8 @@ var classTypes = [nctypes]*classData{
return func() bool { return func() bool {
if s.container != nil && s.resize != nil { // wait for init if s.container != nil && s.resize != nil { // wait for init
width, height := gtk_window_get_size(s.widget) width, height := gtk_window_get_size(s.widget)
err := s.resize(0, 0, width, height) // top-left is (0,0) so no need for winheight
err := s.resize(0, 0, width, height, 0)
if err != nil { if err != nil {
panic("child resize failed: " + err.Error()) panic("child resize failed: " + err.Error())
} }
@ -189,7 +190,7 @@ func (s *sysData) setText(text string) error {
return nil return nil
} }
func (s *sysData) setRect(x int, y int, width int, height int) error { func (s *sysData) setRect(x int, y int, width int, height int, winheight int) error {
gtk_fixed_move(s.container, s.widget, x, y) gtk_fixed_move(s.container, s.widget, x, y)
gtk_widget_set_size_request(s.widget, width, height) gtk_widget_set_size_request(s.widget, width, height)
return nil return nil

View File

@ -251,7 +251,7 @@ func (s *sysData) setText(text string) error {
return nil return nil
} }
func (s *sysData) setRect(x int, y int, width int, height int) error { func (s *sysData) setRect(x int, y int, width int, height int, winheight int) error {
r1, _, err := _moveWindow.Call( r1, _, err := _moveWindow.Call(
uintptr(s.hwnd), uintptr(s.hwnd),
uintptr(x), uintptr(x),
@ -481,7 +481,8 @@ func (s *sysData) setWindowSize(width int, height int) error {
if r.ret == 0 { if r.ret == 0 {
return fmt.Errorf("error getting upper-left of window for resize: %v", r.err) return fmt.Errorf("error getting upper-left of window for resize: %v", r.err)
} }
err := s.setRect(int(rect.Left), int(rect.Top), width, height) // 0 because (0,0) is top-left so no winheight
err := s.setRect(int(rect.Left), int(rect.Top), width, height, 0)
if err != nil { if err != nil {
return fmt.Errorf("error actually resizing window: %v", err) return fmt.Errorf("error actually resizing window: %v", err)
} }

View File

@ -27,7 +27,8 @@ so I don't forget:
important things: important things:
- ui.Go() should exit when the main() you pass in exits - ui.Go() should exit when the main() you pass in exits
- because the main event loop is not called if initialization fails, it is presently impossible for MsgBoxError() to work if UI initialization fails; this basically means we cannot allow initializiation to fail on Mac OS X if we want to be able to report UI init failures to the user with one - because the main event loop is not called if initialization fails, it is presently impossible for MsgBoxError() to work if UI initialization fails; this basically means we cannot allow initializiation to fail on Mac OS X if we want to be able to report UI init failures to the user with one
- Cocoa coordinates have (0,0) at the bottom left: need to fix this somehow - figure out where to auto-place windows in Cocoa (also window coordinates are still not flipped properly so (0,0) on screen is the bottom-left)
- also provide a method to center windoes; Cocoa provides one for us but
- I think Cocoa NSButton text is not vertically aligned properly...? - I think Cocoa NSButton text is not vertically aligned properly...?
- NSPopUpButton doesn't seem to allow no initial selection? need to be sure - NSPopUpButton doesn't seem to allow no initial selection? need to be sure
- NSComboBox scans the entered text to see if it matches one of the items and returns the index of that item if it does; find out how to suppress this so that it returns -1 unless the item was chosen from the list (like the other platforms) - NSComboBox scans the entered text to see if it matches one of the items and returns the index of that item if it does; find out how to suppress this so that it returns -1 unless the item was chosen from the list (like the other platforms)