From a83dcb028242cb57f143a60a869cd64390809be3 Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Sat, 1 Mar 2014 13:29:24 -0500 Subject: [PATCH] Added initial Mac OS X sysData code. Almost ready for first test build, hopefully? --- bleh_darwin.m | 5 + objc_darwin.go | 6 ++ objc_darwin.h | 2 + sysdata_darwin.go | 237 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 250 insertions(+) create mode 100644 sysdata_darwin.go diff --git a/bleh_darwin.m b/bleh_darwin.m index 7b10134..5e4b277 100644 --- a/bleh_darwin.m +++ b/bleh_darwin.m @@ -40,6 +40,11 @@ id _objc_msgSend_rect(id obj, SEL sel, int64_t x, int64_t y, int64_t w, int64_t return objc_msgSend(obj, sel, OurRect()); } +id _objc_msgSend_rect_bool(id obj, SEL sel, int64_t x, int64_t y, int64_t w, int64_t h, BOOL b) +{ + return objc_msgSend(obj, sel, OurRect(), b); +} + id _objc_msgSend_rect_uint_uint_bool(id obj, SEL sel, int64_t x, int64_t y, int64_t w, int64_t h, uintptr_t b, uintptr_t c, BOOL d) { return objc_msgSend(obj, sel, OurRect(), (NSUInteger) b, (NSUInteger) c, d); diff --git a/objc_darwin.go b/objc_darwin.go index 234f7c0..6d9ce8e 100644 --- a/objc_darwin.go +++ b/objc_darwin.go @@ -82,6 +82,12 @@ func objc_msgSend_uint(obj C.id, sel C.SEL, a uintptr) C.id { return C._objc_msgSend_uint(obj, sel, C.uintptr_t(a)) } +func objc_msgSend_rect_bool(obj C.id, sel C.SEL, x int, y int, w int, h int, b C.BOOL) C.id { + return C._objc_msgSend_rect_bool(obj, sel, + C.int64_t(x), C.int64_t(y), C.int64_t(w), C.int64_t(h), + b) +} + func objc_msgSend_rect_uint_uint_bool(obj C.id, sel C.SEL, x int, y int, w int, h int, b uintptr, c uintptr, d C.BOOL) C.id { return C._objc_msgSend_rect_uint_uint_bool(obj, sel, C.int64_t(x), C.int64_t(y), C.int64_t(w), C.int64_t(h), diff --git a/objc_darwin.h b/objc_darwin.h index d094f7a..e73687e 100644 --- a/objc_darwin.h +++ b/objc_darwin.h @@ -58,8 +58,10 @@ extern id _objc_msgSend_rect(id obj, SEL sel, int64_t x, int64_t y, int64_t w, i m1(sel, SEL) extern id _objc_msgSend_uint(id obj, SEL sel, uintptr_t a); m1(ptr, void *) +m1(bool, BOOL) m2(id_id, id, id) +extern id _objc_msgSend_rect_bool(id obj, SEL sel, int64_t x, int64_t y, int64_t w, int64_t h, BOOL b); m3(id_id_id, id, id, id) m3(sel_id_bool, SEL, id, BOOL) diff --git a/sysdata_darwin.go b/sysdata_darwin.go new file mode 100644 index 0000000..0c6208c --- /dev/null +++ b/sysdata_darwin.go @@ -0,0 +1,237 @@ +// 1 march 2014 +package ui + +import ( + "unsafe" +) + +// #cgo LDFLAGS: -lobjc -framework Foundation -framework AppKit +// #include "objc_darwin.h" +import "C" + +type sysData struct { + cSysData + + id C.id +} + +type classData struct { + make: func(parentWindow C.id) C.id + show: func(what C.id) + hide: func(what C.id) + settextsel C.SEL + textsel C.SEL +} + +var ( + _NSWindow = objc_getClass("NSWindow") + + _initWithContentRect = sel_getUid("initWithContentRect:styleMask:backing:defer:") + _makeKeyAndOrderFront = sel_getUid("makeKeyAndOrderFront:") + _orderOut = sel_getUid("orderOut:") + _setHidden = sel_getUid("setHidden:") + _setTitle = sel_getUid("setTitle:") + _setStringValue = sel_getUid("setStringValue:") + _setFrame = sel_getUid("setFrame:") + _state = sel_getUid("state") + _title = sel_getUid("title") + _stringValue = sel_getUid("stringValue") + // TODO others + _setFrameDisplay = sel_getUid("setFrame:display:") +) + +func controlShow(what C.id) { + C.objc_msgSend_bool(what, _setHidden, C.BOOL(C.NO)) +} + +func controlHide(what C.id) { + C.objc_msgSend_bool(what, _setHidden, C.BOOL(C.YES)) +} + +var classTypes = [nctypes]*classData{ + c_window: &classData{ + make: func(parentWindow C.id) C.id { + const ( + NSBorderlessWindowMask = 0 + NSTitledWindowMask = 1 << 0 + NSClosableWindowMask = 1 << 1 + NSMiniaturizableWindowMask = 1 << 2 + NSResizableWindowMask = 1 << 3 + NSTexturedBackgroundWindowMask = 1 << 8 + ) + + // we have to specify a content rect to start; it will be overridden soon though + win := objc_alloc(_NSWindow) + return objc_msgSend_rect_uint_uint_bool(win, + _initWithContentRect, + 0, 0, 100, 100, + NSTitledWindowMask | NSClosableWindowMask | NSClosableWindowMask | NSResizableWindowMask, + 2, // NSBackingStoreBuffered - the only backing store method that Apple says we should use (the others are legacy) + C.BOOL(C.YES)) // defer creation of device until we show the window + }, + show: func(what C.id) { + C.objc_sendMsg_id(what, _makeKeyAndOrderFront, what) + }, + hide: func(what C.id) { + C.objc_sendMsg_id(what, _orderOut, what) + }, + settextsel: _setTitle, + textsel: _title, + }, + c_button: &classData{ + }, + c_checkbox: &classData{ + }, + c_combobox: &classData{ + }, + c_lineedit: &classData{ + }, + c_label: &classData{ + }, + c_listbox: &classData{ + }, + c_progressbar: &classData{ + }, +} + +func (s *sysData) make(initText string, window *sysData) error { + var parentWindow C.id + + ct := classTypes[s.ctype] + if ct.make == nil { + println(s.ctype, "not implemented") + return nil + } + if window != nil { + parentWindow = window.id + } + ret := make(chan C.id) + defer close(ret) + uitask <- func() { + ret <- ct.make(parentWindow) + } + s.id = <-ret + err := s.setText(initText) + if err != nil { + return fmt.Errorf("error setting initial text of new window/control: %v", err) + } + return nil +} + +func (s *sysData) show() error { +if classTypes[s.ctype].show == nil { return nil } + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { + classTypes[s.ctype].show(s.id) + ret <- struct{}{} + } + <-ret + return nil +} + +func (s *sysData) hide() error { +if classTypes[s.ctype].hide == nil { return nil } + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { + classTypes[s.ctype].hide(s.id) + ret <- struct{}{} + } + <-ret + return nil +} + +func (s *sysData) setText(text string) error { +var zero C.SEL +if classTypes[s.ctype].settextsel == zero { return nil } + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { + C.objc_msgSend_id(s.id, classTypes[s.ctype].settextsel, toNSString(text)) + ret <- struct{}{} + } + <-ret + return nil +} + +func (s *sysData) setRect(x int, y int, width int, height int) error { +if classTypes[s.ctype].make == nil { return nil } + C.objc_msgSend_rect(s.id, _setFrame, + C.int64_t(x), C.int64_t(y), C.int64_t(width), C.int64_t(height)) + return nil +} + +func (s *sysData) isChecked() bool { +if classTypes[s.ctype].make == nil { return nil } + const ( + NSOnState = 1 + ) + + ret := make(chan bool) + defer close(ret) + uitask <- func() { + k := C.objc_msgSend_noargs(s.id, _state) + ret <- uintptr(unsafe.Pointer(k)) == NSOnState + } + return <-ret +} + +func (s *sysData) text() string { +var zero C.SEL +if classTypes[s.ctype].textsel == zero { return nil } + ret := make(chan string) + defer close(ret) + uitask <- func() { + str := C.objc_msgSend_noargs(s.id, classTypes[s.ctype].textsel) + ret <- fromNSString(str) + } + return <-ret +} + +func (s *sysData) append(what string) error { + // TODO + return nil +} + +func (s *sysData) insertBefore(what string, before int) error { + // TODO + return nil +} + +func (s *sysData) selectedIndex() int { + // TODO + reteurn -1 +} + +func (s *sysData) selectedIndices() []int { + // TODO + return nil +} + +func (s *sysData) selectedTexts() []string { + // TODO + return nil +} + +func (s *sysData) setWindowSize(x int, y int, width int, height int) error { + ret := make(chan struct{}) + defer close(ret) + uitask <- func() { + objc_msgSend_rect_bool(s.id, _setFrameDisplay, + x, y, w, h, + C.BOOL(C.YES)) // TODO set to NO to prevent subviews from being redrawn before they are resized? + ret <- struct{}{} + } + <-ret + return nil +} + +func (s *sysData) delete(index int) error { + // TODO + return nil +} + +func (s *sysData) setProgress(percent int) { + // TODO +}