go fmt. Precursor to bug report filing.
This commit is contained in:
parent
09db0bffff
commit
982004d050
16
area_unix.go
16
area_unix.go
|
@ -185,14 +185,14 @@ var areaCallbacks = []struct {
|
||||||
name string
|
name string
|
||||||
callback C.GCallback
|
callback C.GCallback
|
||||||
}{
|
}{
|
||||||
{ "draw", area_draw_callback },
|
{"draw", area_draw_callback},
|
||||||
{ "button-press-event", area_button_press_event_callback },
|
{"button-press-event", area_button_press_event_callback},
|
||||||
{ "button-release-event", area_button_release_event_callback },
|
{"button-release-event", area_button_release_event_callback},
|
||||||
{ "motion-notify-event", area_motion_notify_event_callback },
|
{"motion-notify-event", area_motion_notify_event_callback},
|
||||||
{ "enter-notify-event", area_enterleave_notify_event_callback },
|
{"enter-notify-event", area_enterleave_notify_event_callback},
|
||||||
{ "leave-notify-event", area_enterleave_notify_event_callback },
|
{"leave-notify-event", area_enterleave_notify_event_callback},
|
||||||
{ "key-press-event", area_key_press_event_callback },
|
{"key-press-event", area_key_press_event_callback},
|
||||||
{ "key-release-event", area_key_release_event_callback },
|
{"key-release-event", area_key_release_event_callback},
|
||||||
}
|
}
|
||||||
|
|
||||||
//export our_area_draw_callback
|
//export our_area_draw_callback
|
||||||
|
|
|
@ -122,7 +122,7 @@ func dotoARGB(img unsafe.Pointer, ppvBits unsafe.Pointer, toNRGBA C.BOOL) {
|
||||||
i := (*image.RGBA)(unsafe.Pointer(img))
|
i := (*image.RGBA)(unsafe.Pointer(img))
|
||||||
t := toNRGBA != C.FALSE
|
t := toNRGBA != C.FALSE
|
||||||
// the bitmap Windows gives us has a stride == width
|
// the bitmap Windows gives us has a stride == width
|
||||||
toARGB(i, uintptr(ppvBits), i.Rect.Dx() * 4, t)
|
toARGB(i, uintptr(ppvBits), i.Rect.Dx()*4, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export areaWidthLONG
|
//export areaWidthLONG
|
||||||
|
@ -184,19 +184,19 @@ func finishAreaMouseEvent(data unsafe.Pointer, cbutton C.DWORD, up C.BOOL, heldB
|
||||||
}
|
}
|
||||||
// though wparam will contain control and shift state, let's use just one function to get modifiers for both keyboard and mouse events; it'll work the same anyway since we have to do this for alt and windows key (super)
|
// though wparam will contain control and shift state, let's use just one function to get modifiers for both keyboard and mouse events; it'll work the same anyway since we have to do this for alt and windows key (super)
|
||||||
me.Modifiers = getModifiers()
|
me.Modifiers = getModifiers()
|
||||||
if button != 1 && (heldButtons & C.MK_LBUTTON) != 0 {
|
if button != 1 && (heldButtons&C.MK_LBUTTON) != 0 {
|
||||||
me.Held = append(me.Held, 1)
|
me.Held = append(me.Held, 1)
|
||||||
}
|
}
|
||||||
if button != 2 && (heldButtons & C.MK_MBUTTON) != 0 {
|
if button != 2 && (heldButtons&C.MK_MBUTTON) != 0 {
|
||||||
me.Held = append(me.Held, 2)
|
me.Held = append(me.Held, 2)
|
||||||
}
|
}
|
||||||
if button != 3 && (heldButtons & C.MK_RBUTTON) != 0 {
|
if button != 3 && (heldButtons&C.MK_RBUTTON) != 0 {
|
||||||
me.Held = append(me.Held, 3)
|
me.Held = append(me.Held, 3)
|
||||||
}
|
}
|
||||||
if button != 4 && (heldButtons & C.MK_XBUTTON1) != 0 {
|
if button != 4 && (heldButtons&C.MK_XBUTTON1) != 0 {
|
||||||
me.Held = append(me.Held, 4)
|
me.Held = append(me.Held, 4)
|
||||||
}
|
}
|
||||||
if button != 5 && (heldButtons & C.MK_XBUTTON2) != 0 {
|
if button != 5 && (heldButtons&C.MK_XBUTTON2) != 0 {
|
||||||
me.Held = append(me.Held, 5)
|
me.Held = append(me.Held, 5)
|
||||||
}
|
}
|
||||||
a.handler.Mouse(me)
|
a.handler.Mouse(me)
|
||||||
|
|
|
@ -19,7 +19,7 @@ var buttonclass = toUTF16("BUTTON")
|
||||||
|
|
||||||
func newButton(text string) *button {
|
func newButton(text string) *button {
|
||||||
hwnd := C.newControl(buttonclass,
|
hwnd := C.newControl(buttonclass,
|
||||||
C.BS_PUSHBUTTON | C.WS_TABSTOP,
|
C.BS_PUSHBUTTON|C.WS_TABSTOP,
|
||||||
0)
|
0)
|
||||||
b := &button{
|
b := &button{
|
||||||
_hwnd: hwnd,
|
_hwnd: hwnd,
|
||||||
|
@ -84,7 +84,7 @@ func (b *button) preferredSize(d *sizing) (width, height int) {
|
||||||
return int(size.cx), int(size.cy)
|
return int(size.cx), int(size.cy)
|
||||||
}
|
}
|
||||||
// that failed, fall back
|
// that failed, fall back
|
||||||
println("message failed; falling back")
|
println("message failed; falling back")
|
||||||
// don't worry about the error return from GetSystemMetrics(); there's no way to tell (explicitly documented as such)
|
// don't worry about the error return from GetSystemMetrics(); there's no way to tell (explicitly documented as such)
|
||||||
xmargins := 2 * int(C.GetSystemMetrics(C.SM_CXEDGE))
|
xmargins := 2 * int(C.GetSystemMetrics(C.SM_CXEDGE))
|
||||||
return xmargins + int(b._textlen), fromdlgunitsY(buttonHeight, d)
|
return xmargins + int(b._textlen), fromdlgunitsY(buttonHeight, d)
|
||||||
|
|
|
@ -19,7 +19,7 @@ func newCheckbox(text string) *checkbox {
|
||||||
// don't use BS_AUTOCHECKBOX here because it creates problems when refocusing (see http://blogs.msdn.com/b/oldnewthing/archive/2014/05/22/10527522.aspx)
|
// don't use BS_AUTOCHECKBOX here because it creates problems when refocusing (see http://blogs.msdn.com/b/oldnewthing/archive/2014/05/22/10527522.aspx)
|
||||||
// we'll handle actually toggling the check state ourselves (see controls_windows.c)
|
// we'll handle actually toggling the check state ourselves (see controls_windows.c)
|
||||||
hwnd := C.newControl(buttonclass,
|
hwnd := C.newControl(buttonclass,
|
||||||
C.BS_CHECKBOX | C.WS_TABSTOP,
|
C.BS_CHECKBOX|C.WS_TABSTOP,
|
||||||
0)
|
0)
|
||||||
c := &checkbox{
|
c := &checkbox{
|
||||||
_hwnd: hwnd,
|
_hwnd: hwnd,
|
||||||
|
|
|
@ -4,9 +4,9 @@ package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
"reflect"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// #include "winapi_windows.h"
|
// #include "winapi_windows.h"
|
||||||
|
@ -40,7 +40,7 @@ func getWindowText(hwnd C.HWND) string {
|
||||||
// WM_GETTEXTLENGTH and WM_GETTEXT return the count /without/ the terminating null character
|
// WM_GETTEXTLENGTH and WM_GETTEXT return the count /without/ the terminating null character
|
||||||
// but WM_GETTEXT expects the buffer size handed to it to /include/ the terminating null character
|
// but WM_GETTEXT expects the buffer size handed to it to /include/ the terminating null character
|
||||||
n := C.getWindowTextLen(hwnd)
|
n := C.getWindowTextLen(hwnd)
|
||||||
buf := make([]uint16, int(n + 1))
|
buf := make([]uint16, int(n+1))
|
||||||
C.getWindowText(hwnd, C.WPARAM(n),
|
C.getWindowText(hwnd, C.WPARAM(n),
|
||||||
C.LPWSTR(unsafe.Pointer(&buf[0])))
|
C.LPWSTR(unsafe.Pointer(&buf[0])))
|
||||||
return syscall.UTF16ToString(buf)
|
return syscall.UTF16ToString(buf)
|
||||||
|
|
|
@ -42,8 +42,8 @@ func (c *container) resize(x, y, width, height int) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d := c.beginResize()
|
d := c.beginResize()
|
||||||
allocations := c.child.allocate(x + d.xmargin, y + d.ymargintop,
|
allocations := c.child.allocate(x+d.xmargin, y+d.ymargintop,
|
||||||
width - (2 * d.xmargin), height - d.ymargintop - d.ymarginbottom, d)
|
width-(2*d.xmargin), height-d.ymargintop-d.ymarginbottom, d)
|
||||||
c.translateAllocationCoords(allocations, width, height)
|
c.translateAllocationCoords(allocations, width, height)
|
||||||
// move in reverse so as to approximate right->left order so neighbors make sense
|
// move in reverse so as to approximate right->left order so neighbors make sense
|
||||||
for i := len(allocations) - 1; i >= 0; i-- {
|
for i := len(allocations) - 1; i >= 0; i-- {
|
||||||
|
|
|
@ -57,7 +57,7 @@ func (c *container) setParent(hwnd C.HWND) {
|
||||||
|
|
||||||
// this is needed because Windows won't move/resize a child window for us
|
// this is needed because Windows won't move/resize a child window for us
|
||||||
func (c *container) move(r *C.RECT) {
|
func (c *container) move(r *C.RECT) {
|
||||||
C.moveWindow(c.hwnd, C.int(r.left), C.int(r.top), C.int(r.right - r.left), C.int(r.bottom - r.top))
|
C.moveWindow(c.hwnd, C.int(r.left), C.int(r.top), C.int(r.right-r.left), C.int(r.bottom-r.top))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *container) show() {
|
func (c *container) show() {
|
||||||
|
@ -78,7 +78,7 @@ func storeContainerHWND(data unsafe.Pointer, hwnd C.HWND) {
|
||||||
func containerResize(data unsafe.Pointer, r *C.RECT) {
|
func containerResize(data unsafe.Pointer, r *C.RECT) {
|
||||||
c := (*container)(data)
|
c := (*container)(data)
|
||||||
// the origin of any window's content area is always (0, 0), but let's use the values from the RECT just to be safe
|
// the origin of any window's content area is always (0, 0), but let's use the values from the RECT just to be safe
|
||||||
c.resize(int(r.left), int(r.top), int(r.right - r.left), int(r.bottom - r.top))
|
c.resize(int(r.left), int(r.top), int(r.right-r.left), int(r.bottom-r.top))
|
||||||
}
|
}
|
||||||
|
|
||||||
// For Windows, Microsoft just hands you a list of preferred control sizes as part of the MSDN documentation and tells you to roll with it.
|
// For Windows, Microsoft just hands you a list of preferred control sizes as part of the MSDN documentation and tells you to roll with it.
|
||||||
|
|
28
grid.go
28
grid.go
|
@ -31,6 +31,7 @@ type Grid interface {
|
||||||
|
|
||||||
// Align represents the alignment of a Control in its cell of a Grid.
|
// Align represents the alignment of a Control in its cell of a Grid.
|
||||||
type Align uint
|
type Align uint
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LeftTop Align = iota
|
LeftTop Align = iota
|
||||||
Center
|
Center
|
||||||
|
@ -40,6 +41,7 @@ const (
|
||||||
|
|
||||||
// Side represents a side of a Control to add other Controls to a Grid to.
|
// Side represents a side of a Control to add other Controls to a Grid to.
|
||||||
type Side uint
|
type Side uint
|
||||||
|
|
||||||
const (
|
const (
|
||||||
West Side = iota
|
West Side = iota
|
||||||
East
|
East
|
||||||
|
@ -105,10 +107,10 @@ func (g *grid) reorigin() {
|
||||||
for i := range g.controls {
|
for i := range g.controls {
|
||||||
g.controls[i].x += xmin
|
g.controls[i].x += xmin
|
||||||
g.controls[i].y += ymin
|
g.controls[i].y += ymin
|
||||||
if g.xmax < g.controls[i].x + g.controls[i].xspan {
|
if g.xmax < g.controls[i].x+g.controls[i].xspan {
|
||||||
g.xmax = g.controls[i].x + g.controls[i].xspan
|
g.xmax = g.controls[i].x + g.controls[i].xspan
|
||||||
}
|
}
|
||||||
if g.ymax < g.controls[i].y + g.controls[i].yspan {
|
if g.ymax < g.controls[i].y+g.controls[i].yspan {
|
||||||
g.ymax = g.controls[i].y + g.controls[i].yspan
|
g.ymax = g.controls[i].y + g.controls[i].yspan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,8 +178,8 @@ func (g *grid) mkgrid() (gg [][]int, colwidths []int, rowheights []int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := range g.controls {
|
for i := range g.controls {
|
||||||
for y := g.controls[i].y; y < g.controls[i].y + g.controls[i].yspan; y++ {
|
for y := g.controls[i].y; y < g.controls[i].y+g.controls[i].yspan; y++ {
|
||||||
for x := g.controls[i].x; x < g.controls[i].x + g.controls[i].xspan; x++ {
|
for x := g.controls[i].x; x < g.controls[i].x+g.controls[i].xspan; x++ {
|
||||||
gg[y][x] = i
|
gg[y][x] = i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,28 +243,28 @@ func (g *grid) allocate(x int, y int, width int, height int, d *sizing) (allocat
|
||||||
for i := range g.controls {
|
for i := range g.controls {
|
||||||
if g.controls[i].xexpand && g.controls[i].xspan != 1 {
|
if g.controls[i].xexpand && g.controls[i].xspan != 1 {
|
||||||
do := true
|
do := true
|
||||||
for x := g.controls[i].x; x < g.controls[i].x + g.controls[i].xspan; x++ {
|
for x := g.controls[i].x; x < g.controls[i].x+g.controls[i].xspan; x++ {
|
||||||
if xexpand[x] {
|
if xexpand[x] {
|
||||||
do = false
|
do = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if do {
|
if do {
|
||||||
for x := g.controls[i].x; x < g.controls[i].x + g.controls[i].xspan; x++ {
|
for x := g.controls[i].x; x < g.controls[i].x+g.controls[i].xspan; x++ {
|
||||||
xexpand[x] = true
|
xexpand[x] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if g.controls[i].yexpand && g.controls[i].yspan != 1 {
|
if g.controls[i].yexpand && g.controls[i].yspan != 1 {
|
||||||
do := true
|
do := true
|
||||||
for y := g.controls[i].y; y < g.controls[i].y + g.controls[i].yspan; y++ {
|
for y := g.controls[i].y; y < g.controls[i].y+g.controls[i].yspan; y++ {
|
||||||
if yexpand[y] {
|
if yexpand[y] {
|
||||||
do = false
|
do = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if do {
|
if do {
|
||||||
for y := g.controls[i].y; y < g.controls[i].y + g.controls[i].yspan; y++ {
|
for y := g.controls[i].y; y < g.controls[i].y+g.controls[i].yspan; y++ {
|
||||||
yexpand[y] = true
|
yexpand[y] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -372,7 +374,7 @@ func (g *grid) allocate(x int, y int, width int, height int, d *sizing) (allocat
|
||||||
for _, i := range ycol {
|
for _, i := range ycol {
|
||||||
if i != -1 { // treat empty cells like spaces
|
if i != -1 { // treat empty cells like spaces
|
||||||
as := g.controls[i].control.allocate(
|
as := g.controls[i].control.allocate(
|
||||||
g.controls[i].finalx + x, g.controls[i].finaly + y,
|
g.controls[i].finalx+x, g.controls[i].finaly+y,
|
||||||
g.controls[i].finalwidth, g.controls[i].finalheight, d)
|
g.controls[i].finalwidth, g.controls[i].finalheight, d)
|
||||||
if current != nil { // connect first left to first right
|
if current != nil { // connect first left to first right
|
||||||
current.neighbor = g.controls[i].control
|
current.neighbor = g.controls[i].control
|
||||||
|
@ -409,10 +411,10 @@ func (g *grid) preferredSize(d *sizing) (width, height int) {
|
||||||
}
|
}
|
||||||
w, h := g.controls[i].control.preferredSize(d)
|
w, h := g.controls[i].control.preferredSize(d)
|
||||||
// allot equal space in the presence of spanning to keep things sane
|
// allot equal space in the presence of spanning to keep things sane
|
||||||
if colwidths[x] < w / g.controls[i].xspan {
|
if colwidths[x] < w/g.controls[i].xspan {
|
||||||
colwidths[x] = w / g.controls[i].xspan
|
colwidths[x] = w / g.controls[i].xspan
|
||||||
}
|
}
|
||||||
if rowheights[y] < h / g.controls[i].yspan {
|
if rowheights[y] < h/g.controls[i].yspan {
|
||||||
rowheights[y] = h / g.controls[i].yspan
|
rowheights[y] = h / g.controls[i].yspan
|
||||||
}
|
}
|
||||||
// save these for step 6
|
// save these for step 6
|
||||||
|
@ -432,8 +434,8 @@ func (g *grid) preferredSize(d *sizing) (width, height int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// and that's it; just account for padding
|
// and that's it; just account for padding
|
||||||
return colwidth + (g.xmax - 1) * d.xpadding,
|
return colwidth + (g.xmax-1)*d.xpadding,
|
||||||
rowheight + (g.ymax - 1) * d.ypadding
|
rowheight + (g.ymax-1)*d.ypadding
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *grid) commitResize(a *allocation, d *sizing) {
|
func (g *grid) commitResize(a *allocation, d *sizing) {
|
||||||
|
|
|
@ -6,8 +6,8 @@ package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"unsafe"
|
|
||||||
"image"
|
"image"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// #include "gtk_unix.h"
|
// #include "gtk_unix.h"
|
||||||
|
|
|
@ -17,7 +17,7 @@ func finishNewLabel(text string, standalone bool) *label {
|
||||||
hwnd := C.newControl(labelclass,
|
hwnd := C.newControl(labelclass,
|
||||||
// SS_NOPREFIX avoids accelerator translation; SS_LEFTNOWORDWRAP clips text past the end
|
// SS_NOPREFIX avoids accelerator translation; SS_LEFTNOWORDWRAP clips text past the end
|
||||||
// controls are vertically aligned to the top by default (thanks Xeek in irc.freenode.net/#winapi)
|
// controls are vertically aligned to the top by default (thanks Xeek in irc.freenode.net/#winapi)
|
||||||
C.SS_NOPREFIX | C.SS_LEFTNOWORDWRAP,
|
C.SS_NOPREFIX|C.SS_LEFTNOWORDWRAP,
|
||||||
C.WS_EX_TRANSPARENT)
|
C.WS_EX_TRANSPARENT)
|
||||||
l := &label{
|
l := &label{
|
||||||
_hwnd: hwnd,
|
_hwnd: hwnd,
|
||||||
|
|
1
stack.go
1
stack.go
|
@ -192,7 +192,6 @@ func (s *stack) getAuxResizeInfo(d *sizing) {
|
||||||
// this is to satisfy Control; nothing to do here
|
// this is to satisfy Control; nothing to do here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Space returns a null Control intended for padding layouts with blank space.
|
// Space returns a null Control intended for padding layouts with blank space.
|
||||||
// It appears to its owner as a Control of 0x0 size.
|
// It appears to its owner as a Control of 0x0 size.
|
||||||
//
|
//
|
||||||
|
|
|
@ -40,7 +40,7 @@ func (t *tab) Append(name string, control Control) {
|
||||||
defer freegstr(cname)
|
defer freegstr(cname)
|
||||||
C.gtk_notebook_set_tab_label_text(t.notebook,
|
C.gtk_notebook_set_tab_label_text(t.notebook,
|
||||||
// unfortunately there does not seem to be a gtk_notebook_set_nth_tab_label_text()
|
// unfortunately there does not seem to be a gtk_notebook_set_nth_tab_label_text()
|
||||||
C.gtk_notebook_get_nth_page(t.notebook, C.gint(len(t.tabs) - 1)),
|
C.gtk_notebook_get_nth_page(t.notebook, C.gint(len(t.tabs)-1)),
|
||||||
cname)
|
cname)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ type tab struct {
|
||||||
|
|
||||||
func newTab() Tab {
|
func newTab() Tab {
|
||||||
hwnd := C.newControl(C.xWC_TABCONTROL,
|
hwnd := C.newControl(C.xWC_TABCONTROL,
|
||||||
C.TCS_TOOLTIPS | C.WS_TABSTOP,
|
C.TCS_TOOLTIPS|C.WS_TABSTOP,
|
||||||
0) // don't set WS_EX_CONTROLPARENT here; see uitask_windows.c
|
0) // don't set WS_EX_CONTROLPARENT here; see uitask_windows.c
|
||||||
t := &tab{
|
t := &tab{
|
||||||
_hwnd: hwnd,
|
_hwnd: hwnd,
|
||||||
|
@ -38,7 +38,7 @@ func (t *tab) Append(name string, control Control) {
|
||||||
t.tabs = append(t.tabs, c)
|
t.tabs = append(t.tabs, c)
|
||||||
// initially hide tab 1..n controls; if we don't, they'll appear over other tabs, resulting in weird behavior
|
// initially hide tab 1..n controls; if we don't, they'll appear over other tabs, resulting in weird behavior
|
||||||
if len(t.tabs) != 1 {
|
if len(t.tabs) != 1 {
|
||||||
t.tabs[len(t.tabs) - 1].hide()
|
t.tabs[len(t.tabs)-1].hide()
|
||||||
}
|
}
|
||||||
C.tabAppend(t._hwnd, toUTF16(name))
|
C.tabAppend(t._hwnd, toUTF16(name))
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"unsafe"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// #include "winapi_windows.h"
|
// #include "winapi_windows.h"
|
||||||
|
@ -26,7 +26,7 @@ type table struct {
|
||||||
func finishNewTable(b *tablebase, ty reflect.Type) Table {
|
func finishNewTable(b *tablebase, ty reflect.Type) Table {
|
||||||
t := &table{
|
t := &table{
|
||||||
_hwnd: C.newControl(C.xWC_LISTVIEW,
|
_hwnd: C.newControl(C.xWC_LISTVIEW,
|
||||||
C.LVS_REPORT | C.LVS_OWNERDATA | C.LVS_NOSORTHEADER | C.LVS_SHOWSELALWAYS | C.LVS_SINGLESEL | C.WS_HSCROLL | C.WS_VSCROLL | C.WS_TABSTOP,
|
C.LVS_REPORT|C.LVS_OWNERDATA|C.LVS_NOSORTHEADER|C.LVS_SHOWSELALWAYS|C.LVS_SINGLESEL|C.WS_HSCROLL|C.WS_VSCROLL|C.WS_TABSTOP,
|
||||||
C.WS_EX_CLIENTEDGE), // WS_EX_CLIENTEDGE without WS_BORDER will show the canonical visual styles border (thanks to MindChild in irc.efnet.net/#winprog)
|
C.WS_EX_CLIENTEDGE), // WS_EX_CLIENTEDGE without WS_BORDER will show the canonical visual styles border (thanks to MindChild in irc.efnet.net/#winprog)
|
||||||
tablebase: b,
|
tablebase: b,
|
||||||
hotrow: -1,
|
hotrow: -1,
|
||||||
|
@ -38,7 +38,7 @@ func finishNewTable(b *tablebase, ty reflect.Type) Table {
|
||||||
C.setTableSubclass(t._hwnd, unsafe.Pointer(t))
|
C.setTableSubclass(t._hwnd, unsafe.Pointer(t))
|
||||||
// LVS_EX_FULLROWSELECT gives us selection across the whole row, not just the leftmost column; this makes the list view work like on other platforms
|
// LVS_EX_FULLROWSELECT gives us selection across the whole row, not just the leftmost column; this makes the list view work like on other platforms
|
||||||
// LVS_EX_SUBITEMIMAGES gives us images in subitems, which will be important when both images and checkboxes are added
|
// LVS_EX_SUBITEMIMAGES gives us images in subitems, which will be important when both images and checkboxes are added
|
||||||
C.tableAddExtendedStyles(t._hwnd, C.LVS_EX_FULLROWSELECT | C.LVS_EX_SUBITEMIMAGES)
|
C.tableAddExtendedStyles(t._hwnd, C.LVS_EX_FULLROWSELECT|C.LVS_EX_SUBITEMIMAGES)
|
||||||
// this must come after the subclass because it uses one of our private messages
|
// this must come after the subclass because it uses one of our private messages
|
||||||
C.SendMessageW(t._hwnd, C.msgTableMakeInitialCheckboxImageList, 0, 0)
|
C.SendMessageW(t._hwnd, C.msgTableMakeInitialCheckboxImageList, 0, 0)
|
||||||
for i := 0; i < ty.NumField(); i++ {
|
for i := 0; i < ty.NumField(); i++ {
|
||||||
|
@ -89,18 +89,18 @@ func tableGetCell(data unsafe.Pointer, item *C.LVITEMW) {
|
||||||
d := reflect.Indirect(reflect.ValueOf(t.data))
|
d := reflect.Indirect(reflect.ValueOf(t.data))
|
||||||
datum := d.Index(int(item.iItem)).Field(int(item.iSubItem))
|
datum := d.Index(int(item.iItem)).Field(int(item.iSubItem))
|
||||||
isText := true
|
isText := true
|
||||||
if item.mask & C.LVIF_IMAGE != 0 {
|
if item.mask&C.LVIF_IMAGE != 0 {
|
||||||
if datum.Type() == reflect.TypeOf(ImageIndex(0)) {
|
if datum.Type() == reflect.TypeOf(ImageIndex(0)) {
|
||||||
item.iImage = C.int(datum.Interface().(ImageIndex))
|
item.iImage = C.int(datum.Interface().(ImageIndex))
|
||||||
isText = false
|
isText = false
|
||||||
}
|
}
|
||||||
// else let the default behavior work
|
// else let the default behavior work
|
||||||
}
|
}
|
||||||
if item.mask & C.LVIF_INDENT != 0 {
|
if item.mask&C.LVIF_INDENT != 0 {
|
||||||
// always have an indent of zero
|
// always have an indent of zero
|
||||||
item.iIndent = 0
|
item.iIndent = 0
|
||||||
}
|
}
|
||||||
if item.mask & C.LVIF_STATE != 0 {
|
if item.mask&C.LVIF_STATE != 0 {
|
||||||
// start by not changing any state
|
// start by not changing any state
|
||||||
item.stateMask = 0
|
item.stateMask = 0
|
||||||
if datum.Kind() == reflect.Bool {
|
if datum.Kind() == reflect.Bool {
|
||||||
|
@ -129,7 +129,7 @@ func tableGetCell(data unsafe.Pointer, item *C.LVITEMW) {
|
||||||
isText = false
|
isText = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if item.mask & C.LVIF_TEXT != 0 {
|
if item.mask&C.LVIF_TEXT != 0 {
|
||||||
if isText {
|
if isText {
|
||||||
s := fmt.Sprintf("%v", datum)
|
s := fmt.Sprintf("%v", datum)
|
||||||
item.pszText = toUTF16(s)
|
item.pszText = toUTF16(s)
|
||||||
|
|
|
@ -19,7 +19,7 @@ var editclass = toUTF16("EDIT")
|
||||||
|
|
||||||
func startNewTextField(style C.DWORD) *textfield {
|
func startNewTextField(style C.DWORD) *textfield {
|
||||||
hwnd := C.newControl(editclass,
|
hwnd := C.newControl(editclass,
|
||||||
style | C.textfieldStyle,
|
style|C.textfieldStyle,
|
||||||
C.textfieldExtStyle) // WS_EX_CLIENTEDGE without WS_BORDER will show the canonical visual styles border (thanks to MindChild in irc.efnet.net/#winprog)
|
C.textfieldExtStyle) // WS_EX_CLIENTEDGE without WS_BORDER will show the canonical visual styles border (thanks to MindChild in irc.efnet.net/#winprog)
|
||||||
t := &textfield{
|
t := &textfield{
|
||||||
_hwnd: hwnd,
|
_hwnd: hwnd,
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
"reflect"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Go initializes and runs package ui.
|
// Go initializes and runs package ui.
|
||||||
|
@ -131,7 +131,7 @@ type ForeignEvent struct {
|
||||||
func NewForeignEvent(channel interface{}, handler func(data interface{})) *ForeignEvent {
|
func NewForeignEvent(channel interface{}, handler func(data interface{})) *ForeignEvent {
|
||||||
c := reflect.ValueOf(channel)
|
c := reflect.ValueOf(channel)
|
||||||
t := c.Type()
|
t := c.Type()
|
||||||
if t.Kind() != reflect.Chan || (t.ChanDir() & reflect.RecvDir) == 0 {
|
if t.Kind() != reflect.Chan || (t.ChanDir()&reflect.RecvDir) == 0 {
|
||||||
panic("non-channel or non-receivable channel passed to NewForeignEvent()")
|
panic("non-channel or non-receivable channel passed to NewForeignEvent()")
|
||||||
}
|
}
|
||||||
fe := &ForeignEvent{
|
fe := &ForeignEvent{
|
||||||
|
|
|
@ -40,7 +40,7 @@ func newWindow(title string, width int, height int, control Control) *window {
|
||||||
if hwnd != w.hwnd {
|
if hwnd != w.hwnd {
|
||||||
panic(fmt.Errorf("inconsistency: hwnd returned by CreateWindowEx() (%p) and hwnd stored in Window (%p) differ", hwnd, w.hwnd))
|
panic(fmt.Errorf("inconsistency: hwnd returned by CreateWindowEx() (%p) and hwnd stored in Window (%p) differ", hwnd, w.hwnd))
|
||||||
}
|
}
|
||||||
hresult := C.EnableThemeDialogTexture(w.hwnd, C.ETDT_ENABLE | C.ETDT_USETABTEXTURE)
|
hresult := C.EnableThemeDialogTexture(w.hwnd, C.ETDT_ENABLE|C.ETDT_USETABTEXTURE)
|
||||||
if hresult != C.S_OK {
|
if hresult != C.S_OK {
|
||||||
panic(fmt.Errorf("error setting tab background texture on Window; HRESULT: 0x%X", hresult))
|
panic(fmt.Errorf("error setting tab background texture on Window; HRESULT: 0x%X", hresult))
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"image/draw"
|
"image/draw"
|
||||||
_ "image/png"
|
_ "image/png"
|
||||||
|
@ -42,10 +42,10 @@ func readIcons() ([]icon, ImageList) {
|
||||||
func tileImage(times int) *image.RGBA {
|
func tileImage(times int) *image.RGBA {
|
||||||
dx := firstimg.Rect.Dx()
|
dx := firstimg.Rect.Dx()
|
||||||
dy := firstimg.Rect.Dy()
|
dy := firstimg.Rect.Dy()
|
||||||
res := image.NewRGBA(image.Rect(0, 0, times * dx, times * dy))
|
res := image.NewRGBA(image.Rect(0, 0, times*dx, times*dy))
|
||||||
r := image.Rect(0, 0, dx, dy)
|
r := image.Rect(0, 0, dx, dy)
|
||||||
for y := 0; y < times; y++ {
|
for y := 0; y < times; y++ {
|
||||||
rr := r.Add(image.Pt(0, y * dy))
|
rr := r.Add(image.Pt(0, y*dy))
|
||||||
for x := 0; x < times; x++ {
|
for x := 0; x < times; x++ {
|
||||||
draw.Draw(res, rr, firstimg, image.ZP, draw.Src)
|
draw.Draw(res, rr, firstimg, image.ZP, draw.Src)
|
||||||
rr = rr.Add(image.Pt(dx, 0))
|
rr = rr.Add(image.Pt(dx, 0))
|
||||||
|
@ -58,12 +58,12 @@ var icons = []struct {
|
||||||
data []byte
|
data []byte
|
||||||
name string
|
name string
|
||||||
}{
|
}{
|
||||||
{ __16x16_categories_applications_accessories_png, "16x16/categories/applications-accessories.png", },
|
{__16x16_categories_applications_accessories_png, "16x16/categories/applications-accessories.png"},
|
||||||
{ __16x16_places_folder_png, "16x16/places/folder.png", },
|
{__16x16_places_folder_png, "16x16/places/folder.png"},
|
||||||
{ __16x16_mimetypes_x_office_spreadsheet_png, "16x16/mimetypes/x-office-spreadsheet.png", },
|
{__16x16_mimetypes_x_office_spreadsheet_png, "16x16/mimetypes/x-office-spreadsheet.png"},
|
||||||
{ __32x32_categories_applications_accessories_png, "32x32/categories/applications-accessories.png", },
|
{__32x32_categories_applications_accessories_png, "32x32/categories/applications-accessories.png"},
|
||||||
{ __32x32_places_folder_png, "32x32/places/folder.png", },
|
{__32x32_places_folder_png, "32x32/places/folder.png"},
|
||||||
{ __32x32_mimetypes_x_office_spreadsheet_png, "32x32/mimetypes/x-office-spreadsheet.png", },
|
{__32x32_mimetypes_x_office_spreadsheet_png, "32x32/mimetypes/x-office-spreadsheet.png"},
|
||||||
}
|
}
|
||||||
|
|
||||||
// from http://tango.freedesktop.org/releases/tango-icon-theme-0.8.90.tar.gz, which is public domain
|
// from http://tango.freedesktop.org/releases/tango-icon-theme-0.8.90.tar.gz, which is public domain
|
||||||
|
|
|
@ -116,7 +116,7 @@ func (r *repainter) alter(rect image.Rectangle, c color.Color) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *repainter) dorect() {
|
func (r *repainter) dorect() {
|
||||||
rect := image.Rect(r.xv, r.yv, r.xv + r.wv, r.yv + r.hv)
|
rect := image.Rect(r.xv, r.yv, r.xv+r.wv, r.yv+r.hv)
|
||||||
r.alter(rect, color.RGBA{255, 0, 255, 128})
|
r.alter(rect, color.RGBA{255, 0, 255, 128})
|
||||||
r.area.Repaint(rect)
|
r.area.Repaint(rect)
|
||||||
}
|
}
|
||||||
|
|
28
zz_test.go
28
zz_test.go
|
@ -5,15 +5,15 @@ 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)
|
// 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 (
|
import (
|
||||||
"fmt"
|
|
||||||
"flag"
|
"flag"
|
||||||
"reflect"
|
"fmt"
|
||||||
"testing"
|
|
||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
"image/draw"
|
"image/draw"
|
||||||
"time"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var closeOnClick = flag.Bool("close", false, "close on click")
|
var closeOnClick = flag.Bool("close", false, "close on click")
|
||||||
|
@ -23,12 +23,13 @@ type dtype struct {
|
||||||
Name string
|
Name string
|
||||||
Address string
|
Address string
|
||||||
}
|
}
|
||||||
|
|
||||||
var ddata = []dtype{
|
var ddata = []dtype{
|
||||||
{ "alpha", "beta" },
|
{"alpha", "beta"},
|
||||||
{ "gamma", "delta" },
|
{"gamma", "delta"},
|
||||||
{ "epsilon", "zeta" },
|
{"epsilon", "zeta"},
|
||||||
{ "eta", "theta" },
|
{"eta", "theta"},
|
||||||
{ "iota", "kappa" },
|
{"iota", "kappa"},
|
||||||
}
|
}
|
||||||
|
|
||||||
type testwin struct {
|
type testwin struct {
|
||||||
|
@ -67,9 +68,10 @@ type testwin struct {
|
||||||
type areaHandler struct {
|
type areaHandler struct {
|
||||||
handled bool
|
handled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *areaHandler) Paint(r image.Rectangle) *image.RGBA {
|
func (a *areaHandler) Paint(r image.Rectangle) *image.RGBA {
|
||||||
i := image.NewRGBA(r)
|
i := image.NewRGBA(r)
|
||||||
draw.Draw(i, r, &image.Uniform{color.RGBA{128,0,128,255}}, image.ZP, draw.Src)
|
draw.Draw(i, r, &image.Uniform{color.RGBA{128, 0, 128, 255}}, image.ZP, draw.Src)
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
func (a *areaHandler) Mouse(me MouseEvent) { fmt.Printf("%#v\n", me) }
|
func (a *areaHandler) Mouse(me MouseEvent) { fmt.Printf("%#v\n", me) }
|
||||||
|
@ -192,7 +194,7 @@ func (tw *testwin) make(done chan struct{}) {
|
||||||
NewCheckbox("hello"),
|
NewCheckbox("hello"),
|
||||||
NewTextField(),
|
NewTextField(),
|
||||||
NewPasswordField(),
|
NewPasswordField(),
|
||||||
NewTable(reflect.TypeOf(struct{A,B,C int}{})),
|
NewTable(reflect.TypeOf(struct{ A, B, C int }{})),
|
||||||
NewStandaloneLabel("hello"))
|
NewStandaloneLabel("hello"))
|
||||||
tw.t.Append("Pref Width", tw.spw)
|
tw.t.Append("Pref Width", tw.spw)
|
||||||
tw.sph = NewVerticalStack(
|
tw.sph = NewVerticalStack(
|
||||||
|
@ -200,7 +202,7 @@ func (tw *testwin) make(done chan struct{}) {
|
||||||
NewCheckbox("hello"),
|
NewCheckbox("hello"),
|
||||||
NewTextField(),
|
NewTextField(),
|
||||||
NewPasswordField(),
|
NewPasswordField(),
|
||||||
NewTable(reflect.TypeOf(struct{A,B,C int}{})),
|
NewTable(reflect.TypeOf(struct{ A, B, C int }{})),
|
||||||
NewStandaloneLabel("hello ÉÀÔ"))
|
NewStandaloneLabel("hello ÉÀÔ"))
|
||||||
tw.t.Append("Pref Height", tw.sph)
|
tw.t.Append("Pref Height", tw.sph)
|
||||||
stack1 := NewHorizontalStack(NewLabel("Test"), NewTextField())
|
stack1 := NewHorizontalStack(NewLabel("Test"), NewTextField())
|
||||||
|
@ -208,7 +210,7 @@ func (tw *testwin) make(done chan struct{}) {
|
||||||
stack2 := NewHorizontalStack(NewLabel("ÉÀÔ"), NewTextField())
|
stack2 := NewHorizontalStack(NewLabel("ÉÀÔ"), NewTextField())
|
||||||
stack2.SetStretchy(1)
|
stack2.SetStretchy(1)
|
||||||
stack3 := NewHorizontalStack(NewLabel("Test 2"),
|
stack3 := NewHorizontalStack(NewLabel("Test 2"),
|
||||||
NewTable(reflect.TypeOf(struct{A,B,C int}{})))
|
NewTable(reflect.TypeOf(struct{ A, B, C int }{})))
|
||||||
stack3.SetStretchy(1)
|
stack3.SetStretchy(1)
|
||||||
tw.s = NewVerticalStack(stack1, stack2, stack3)
|
tw.s = NewVerticalStack(stack1, stack2, stack3)
|
||||||
tw.s.SetStretchy(2)
|
tw.s.SetStretchy(2)
|
||||||
|
|
Loading…
Reference in New Issue