
ListBoxes and Mouse Cases

rhjpires
In trying to understand how to program with panels and controls, I came across a spinet that allows one to shuffle (drag and drop) items within a list. Please, have a look at the code bellow. The case of double-clicking should be ignored. However, when I double-click an item, I receive the notice: " ** a wave read gave error: Index out of range for wave "testList"." and Igor replaces the value of the list I have doubled-clicked by the last value on that list. Can anyone explain why Igor is doing this?
#pragma rtGlobals=3 // Use modern global access method and strict wave access. Function OpenDragNDropExample() Make/O/T/N=4 root:testList = {"item 1", "item 2", "item 3", "item 4"} Make/O/N=4 root:testSel DoWindow/K Panel_DragNDrop Execute/Q "Panel_DragNDrop()" End Window Panel_DragNDrop() : Panel PauseUpdate; Silent 1 // building window... NewPanel /W=(350,125,650,325) as "Drag List Items Example" ListBox list0,pos={1,2},size={298,197},proc=ListBoxProc_DragNDropLB ListBox list0,listWave=root:testList,selWave=root:testSel,mode= 1,selRow= 1 EndMacro Function ListBoxProc_DragNDropLB(lba) : ListBoxControl STRUCT WMListboxAction &lba Variable row = lba.row Variable col = lba.col WAVE/T/Z listWave = lba.listWave WAVE/Z selWave = lba.selWave switch( lba.eventCode ) case -1: // control being killed break case 1: // mouse down Variable/G V_MouseDownRow = row break case 2: // mouse up if(row != V_MouseDownRow) // dragged? NVAR V_MouseDownRow String item = listWave[V_MouseDownRow] DeletePoints V_MouseDownRow, 1, listWave // do swap InsertPoints row, 1, listWave listWave[row] = item endif KillVariables V_MouseDownRow // cleanup variable break case 3: // double click break case 4: // cell selection case 5: // cell selection plus shift key break case 6: // begin edit break case 7: // finish edit break endswitch return 0 End
See the Debugger screenshot I've attached.
--Jim Prouty
Software Engineer, WaveMetrics, Inc.
October 19, 2015 at 10:13 am - Permalink
The second problem is that the first execution of case 2 kills your V_MouseDownRow global variable. So the second time case 2 is called, this variable is null. The check for row != null is true, so the following code executes and as Jim pointed out, row is greater than the last index in your wave. The default Igor behavior is to substitute the last value in a wave if the last index is exceeded.
Hence the error message and the reason row is replaced with the last value in the wave.
I've modified your list box proc somewhat and it seems to work for my limited testing.
As a final comment, you can learn a lot about how code works by judiciously sprinkling it with diagnostic print statements, also learning to use the debugger pays off quite handsomely.
Hope this helps.
October 19, 2015 at 11:08 am - Permalink
Thanks for the suggestions also!
R.
October 19, 2015 at 11:34 am - Permalink