Added Table.OnSelected() and implemented it on Windows.
This commit is contained in:
parent
f60e888c38
commit
b964c564e7
|
@ -62,6 +62,7 @@ windows
|
||||||
- OpenFile() not modal
|
- OpenFile() not modal
|
||||||
- OpenFile() won't stop Do()
|
- OpenFile() won't stop Do()
|
||||||
- labels draw over themselves
|
- labels draw over themselves
|
||||||
|
- fine-tune Table checkbox behavior (especially with regards to selection)
|
||||||
gtk+
|
gtk+
|
||||||
- Area: figure out how Enter is processed in Entry
|
- Area: figure out how Enter is processed in Entry
|
||||||
https://git.gnome.org/browse/gtk+/tree/gtk/gtkwindow.c#n1229
|
https://git.gnome.org/browse/gtk+/tree/gtk/gtkwindow.c#n1229
|
||||||
|
|
|
@ -47,6 +47,9 @@ type Table interface {
|
||||||
// TODO bounds checking
|
// TODO bounds checking
|
||||||
Selected() int
|
Selected() int
|
||||||
Select(index int)
|
Select(index int)
|
||||||
|
|
||||||
|
// OnSelected is an event that gets triggered after the selection in the Table changes in whatever way (item selected or item deselected).
|
||||||
|
OnSelected(func())
|
||||||
}
|
}
|
||||||
|
|
||||||
type tablebase struct {
|
type tablebase struct {
|
||||||
|
|
|
@ -25,39 +25,11 @@ static void handle(HWND hwnd, WPARAM wParam, LPARAM lParam, void (*handler)(void
|
||||||
(*handler)(data, ht.iItem, ht.iSubItem);
|
(*handler)(data, ht.iItem, ht.iSubItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct {int code; char *name;} lvnnames[] = {
|
|
||||||
{ LVN_ITEMCHANGING, "LVN_ITEMCHANGING" },
|
|
||||||
{ LVN_ITEMCHANGED, "LVN_ITEMCHANGED" },
|
|
||||||
{ LVN_INSERTITEM, "LVN_INSERTITEM" },
|
|
||||||
{ LVN_DELETEITEM, "LVN_DELETEITEM" },
|
|
||||||
{ LVN_DELETEALLITEMS, "LVN_DELETEALLITEMS" },
|
|
||||||
{ LVN_BEGINLABELEDITA, "LVN_BEGINLABELEDITA" },
|
|
||||||
{ LVN_BEGINLABELEDITW, "LVN_BEGINLABELEDITW" },
|
|
||||||
{ LVN_ENDLABELEDITA, "LVN_ENDLABELEDITA" },
|
|
||||||
{ LVN_ENDLABELEDITW, "LVN_ENDLABELEDITW" },
|
|
||||||
{ LVN_COLUMNCLICK, "LVN_COLUMNCLICK" },
|
|
||||||
{ LVN_BEGINDRAG, "LVN_BEGINDRAG" },
|
|
||||||
{ LVN_BEGINRDRAG, "LVN_BEGINRDRAG" },
|
|
||||||
//{ LVN_ODCACHEHINT, "LVN_ODCACHEHINT" },
|
|
||||||
{ LVN_ODFINDITEMA, "LVN_ODFINDITEMA" },
|
|
||||||
{ LVN_ODFINDITEMW, "LVN_ODFINDITEMW" },
|
|
||||||
{ LVN_ITEMACTIVATE, "LVN_ITEMACTIVATE" },
|
|
||||||
{ LVN_ODSTATECHANGED, "LVN_ODSTATECHANGED" },
|
|
||||||
{ LVN_SETDISPINFOA, "LVN_SETDISPINFOA" },
|
|
||||||
{ LVN_SETDISPINFOW, "LVN_SETDISPINFOW" },
|
|
||||||
//{ LVN_KEYDOWN, "LVN_KEYDOWN" },
|
|
||||||
{ LVN_MARQUEEBEGIN, "LVN_MARQUEEBEGIN" },
|
|
||||||
{ LVN_GETINFOTIPA, "LVN_GETINFOTIPA" },
|
|
||||||
{ LVN_GETINFOTIPW, "LVN_GETINFOTIPW" },
|
|
||||||
{ LVN_BEGINSCROLL, "LVN_BEGINSCROLL" },
|
|
||||||
{ LVN_ENDSCROLL, "LVN_ENDSCROLL" },
|
|
||||||
{ 0, NULL },
|
|
||||||
};
|
|
||||||
|
|
||||||
static LRESULT CALLBACK tableSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR id, DWORD_PTR data)
|
static LRESULT CALLBACK tableSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR id, DWORD_PTR data)
|
||||||
{
|
{
|
||||||
NMHDR *nmhdr = (NMHDR *) lParam;
|
NMHDR *nmhdr = (NMHDR *) lParam;
|
||||||
NMLVDISPINFOW *fill = (NMLVDISPINFO *) lParam;
|
NMLVDISPINFOW *fill = (NMLVDISPINFO *) lParam;
|
||||||
|
NMLISTVIEW *nlv = (NMLISTVIEW *) lParam;
|
||||||
|
|
||||||
switch (uMsg) {
|
switch (uMsg) {
|
||||||
case msgNOTIFY:
|
case msgNOTIFY:
|
||||||
|
@ -65,8 +37,15 @@ static LRESULT CALLBACK tableSubProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM
|
||||||
case LVN_GETDISPINFO:
|
case LVN_GETDISPINFO:
|
||||||
tableGetCell((void *) data, &(fill->item));
|
tableGetCell((void *) data, &(fill->item));
|
||||||
return 0;
|
return 0;
|
||||||
|
case LVN_ITEMCHANGED:
|
||||||
|
if ((nlv->uChanged & LVIF_STATE) == 0)
|
||||||
|
break;
|
||||||
|
// if both old and new states have the same value for the selected bit, then the selection state did not change, regardless of selected or deselected
|
||||||
|
if ((nlv->uOldState & LVIS_SELECTED) == (nlv->uNewState & LVIS_SELECTED))
|
||||||
|
break;
|
||||||
|
tableOnSelected((void *) data);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
for(int i=0;lvnnames[i].code!=0;i++)if(lvnnames[i].code==nmhdr->code)printf("%s\n",lvnnames[i].name);
|
|
||||||
return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam);
|
return (*fv_DefSubclassProc)(hwnd, uMsg, wParam, lParam);
|
||||||
case WM_MOUSEMOVE:
|
case WM_MOUSEMOVE:
|
||||||
handle(hwnd, wParam, lParam, tableSetHot, (void *) data);
|
handle(hwnd, wParam, lParam, tableSetHot, (void *) data);
|
||||||
|
|
|
@ -20,6 +20,7 @@ type table struct {
|
||||||
hotcol C.int
|
hotcol C.int
|
||||||
pushedrow C.int
|
pushedrow C.int
|
||||||
pushedcol C.int
|
pushedcol C.int
|
||||||
|
selected *event
|
||||||
}
|
}
|
||||||
|
|
||||||
func finishNewTable(b *tablebase, ty reflect.Type) Table {
|
func finishNewTable(b *tablebase, ty reflect.Type) Table {
|
||||||
|
@ -32,6 +33,7 @@ func finishNewTable(b *tablebase, ty reflect.Type) Table {
|
||||||
hotcol: -1,
|
hotcol: -1,
|
||||||
pushedrow: -1,
|
pushedrow: -1,
|
||||||
pushedcol: -1,
|
pushedcol: -1,
|
||||||
|
selected: newEvent(),
|
||||||
}
|
}
|
||||||
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
|
||||||
|
@ -74,6 +76,10 @@ func (t *table) Select(index int) {
|
||||||
C.tableSelectItem(t._hwnd, C.intptr_t(index))
|
C.tableSelectItem(t._hwnd, C.intptr_t(index))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *table) OnSelected(f func()) {
|
||||||
|
t.selected.set(f)
|
||||||
|
}
|
||||||
|
|
||||||
//export tableGetCell
|
//export tableGetCell
|
||||||
func tableGetCell(data unsafe.Pointer, item *C.LVITEMW) {
|
func tableGetCell(data unsafe.Pointer, item *C.LVITEMW) {
|
||||||
t := (*table)(data)
|
t := (*table)(data)
|
||||||
|
@ -181,6 +187,12 @@ func tableToggled(data unsafe.Pointer, row C.int, col C.int) {
|
||||||
panic(fmt.Errorf("tableSetHot() on non-checkbox at (%d, %d)", row, col))
|
panic(fmt.Errorf("tableSetHot() on non-checkbox at (%d, %d)", row, col))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//export tableOnSelected
|
||||||
|
func tableOnSelected(data unsafe.Pointer) {
|
||||||
|
t := (*table)(data)
|
||||||
|
t.selected.fire()
|
||||||
|
}
|
||||||
|
|
||||||
func (t *table) hwnd() C.HWND {
|
func (t *table) hwnd() C.HWND {
|
||||||
return t._hwnd
|
return t._hwnd
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,6 +140,16 @@ func (tw *testwin) make(done chan struct{}) {
|
||||||
*idq = tw.icons
|
*idq = tw.icons
|
||||||
tw.icontbl.Unlock()
|
tw.icontbl.Unlock()
|
||||||
tw.icontbl.LoadImageList(tw.il)
|
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.t.Append("Image List Table", tw.icontbl)
|
||||||
tw.group2 = NewGroup("Group", NewButton("Button in Group"))
|
tw.group2 = NewGroup("Group", NewButton("Button in Group"))
|
||||||
tw.t.Append("Filled Group", tw.group2)
|
tw.t.Append("Filled Group", tw.group2)
|
||||||
|
|
Loading…
Reference in New Issue