listbox problem

I am facing a problem related to a listbox. The listbox resides in an external panel of a host panel and lists wave names. The corresponding waves are appended to a graph of the host panel when the listbox entry is clicked. This is established by a strucure-based action procedure (case 4 of lba.eventCode).
The problem is: When I set a cursor an a trace of the graph, I can't move this cursor by the keyboard arrow keys, also CMD-A for SetAxis/A does not work any longer. It seems that all keyboard strokes are intercepted by the listbox action procedure. I tried setting the active subwindow to the host window of the listbox panel, but without success.
Any hints are much appreciated.
I am using IP 6.10B06 on a MB Pro.
awirsing wrote: It seems that all keyboard strokes are intercepted by the listbox action procedure.


I could not reproduce this exactly, but noticed something curious that may be related.

Using the "default" ListBox Action Procedure (obtained by clicking on the "new" button in the dialog that opens when you double-click on an existing listbox control), my IP6.10B06 (Win) responded to keyboard strokes (at least to the arrow keys). This however relied on the graph window being the active subwindow (achieved by clicking on it). I let Igor figure out how to set the active subwindow properly, i.e. I looked at the Graph0 recreation macro generated by Igor.

I noticed something funny: Even with the active subwindow set up with the command
SetActiveSubwindow ##
, the cursor was redrawn in the exterior panel. I had to add a
ShowInfo;HideInfo
sequence to prevent this. You can find these two behaviors in the snippet below. Paste this into your Procedure window and choose "start1" or "start2" from the Macros menu.

Cheers,
Wolfgang Harneit


#pragma rtGlobals=1		// Use modern global access method.

Macro Start1()
	make/O w={1,2,4,5}
	display w
	Cursor A w 1
	Make/T/O tw={"abc","def"}
	Graph1()
End

Macro Start2()
	make/O w={1,2,4,5}
	display w
	Cursor A w 1
	Make/T/O tw={"abc","def"}
	Graph2()
End

Function ListBoxProc(lba) : ListBoxControl
	STRUCT WMListboxAction &lba
	return 0
End

Window Graph1() : Graph
	PauseUpdate; Silent 1		// building window...
	Display /W=(35.25,42.5,429.75,251) w
	Cursor/P A w 0
	NewPanel/HOST=#/EXT=0/W=(0,0,217,278) 
	ListBox list0,pos={1,2},size={150,103},proc=ListBoxProc,listWave=root:tw
	RenameWindow #,P0
	SetActiveSubwindow ##
	ShowInfo
	HideInfo
EndMacro

Window Graph2() : Graph
	PauseUpdate; Silent 1		// building window...
	Display /W=(35.25,42.5,429.75,251) w
	Cursor/P A w 0
	NewPanel/HOST=#/EXT=0/W=(0,0,217,278) 
	ListBox list0,pos={1,2},size={150,103},proc=ListBoxProc,listWave=root:tw
	RenameWindow #,P0
	SetActiveSubwindow ##
//	ShowInfo
//	HideInfo
EndMacro

I should had provided an example to clear things...
To illustrate the problem paste my snippet in the procedure window and choose Start3 from the macro menu.
I couldn't find a way to move the cursor by means of the keyboard's arrow keys. Hitting these keys invokes the listbox action procedure once you clicked in the listbox as you can see by the prints in the history although the active subwindow is set to the host window.


Macro Start3() : Graph
	make/O w1={1,2,4,5}
	make/O w2={5,4,2,3}
	Make/T/O tw={"w1","w2"}
	Graph3()
End

Window Graph3() : Graph
	PauseUpdate; Silent 1		// building window...
	Display /W=(155,82,550,290) w1
	Cursor/P A w1 0
	NewPanel/HOST=#/EXT=1/W=(0,0,15,100)/K=2
	ListBox list0,pos={1,2},size={150,103},mode=1,selrow=-1,proc=ListBoxProc3,listWave=tw
	RenameWindow #,P0
	SetActiveSubwindow ##
	ShowInfo
EndMacro

Function ListBoxProc3(lba) : ListBoxControl
	STRUCT WMListboxAction &lba

	Variable row = lba.row
	WAVE/T/Z listWave = lba.listWave

	switch( lba.eventCode )
		case 4: // cell selection
			switch(row)
				case 0:
					print "case 0"
					removefromgraph $removeending(tracenamelist("",",",1))
					appendtograph $(listwave[0])
					DoUpdate
					cursor/p a $(listwave[0]) 1
				break
				case 1:
					print "case 1"
					removefromgraph $removeending(tracenamelist("",",",1))
					appendtograph $(listwave[1])
					DoUpdate
					cursor/p a $(listwave[1]) 2
				break
			endswitch
		break
	endswitch

	return 0
End

@ Wolfgang: Also your Showinfo;Hideinfo trick doesn't aktually solve the problem. Once you click on the listbox moving the cursor with the arrow keys is disabled. This applies to both cases (Start1 and Start2).
I just did a quick & dirty hack to solve the issue. Now you can use the left/right arrow keys (or the mouse) to move the cursor and the up/down arrow keys (or the mouse) to operate the listbox control. The code is not so nice (e.g., too many hardwired references to "Graph3"), and may be fragile (see below). I did not get around to comment the code, please tell me if you want more documentation.

Details: in order to get the keyboard focus off the listbox control, I just put a dummy button somewhere in your panel where it can't be seen (some dirty trick). That was the "easy" part - the cursor immediately starts to respond. But the listbox is then definitely not responding to keyboard strokes anymore. So I tried to remedy that by introducing a window hook for the graph window that catches the keyboard strokes. Also quite easy. But then I had to come up with an update mechanism and I wanted to keep the listbox control synchronized with the updates. That was quite hard, and may be the fragile part. Please test & comment.
Wolfgang Harneit


Macro Start3() : Graph
	make/O w1={1,2,4,5}
	make/O w2={5,4,2,3}
	Make/T/O tw={"w1","w2"}
	Variable/G root:recentlyDisplayedWave = 0
	Make/O/N=(numpnts(tw)) cursorPositions=0
	Graph3()
End
 
Window Graph3() : Graph
	PauseUpdate; Silent 1		// building window...
	Display /W=(155,82,550,290) w1
	Cursor/P A w1 0
	NewPanel/HOST=#/EXT=1/W=(0,0,15,100)/K=2
	ListBox list0,pos={1,2},size={150,103},mode=1,selrow=0,proc=ListBoxProc3,listWave=tw
	RenameWindow #,P0
	SetActiveSubwindow ##
	ShowInfo
	SetWindow Graph3, hook(myhook)=GraphWinHook
EndMacro
 
Function ListBoxProc3(lba) : ListBoxControl
	STRUCT WMListboxAction &lba
	Variable row = lba.row
	WAVE/T/Z listWave = lba.listWave
	NVAR oldRow = root:recentlyDisplayedWave
	switch( lba.eventCode )
		case 4: // cell selection
			if( oldRow != row )
				SwapWaves(oldRow, row, listWave)
				oldRow = row
			endif
		break
	endswitch
	return 0
End

function SwapWaves(oldRow, newRow, listWave)
variable oldRow, newRow
Wave/T listWave
	WAVE cursorPos = root:cursorPositions
	cursorPos[oldRow] = pcsr(A)
	RemoveFromGraph/W=Graph3 $(listWave[oldRow])
	AppendToGraph/W=Graph3 $(listWave[newRow])
	Cursor/p a $(listWave[newRow]) cursorPos[newRow]
	Button dummy,pos={200,200},win=Graph3#P0	// makes listbox control lose keyboard focus
	DoUpdate
end

function GraphWinHook(whs)
struct WMWinHookStruct &whs
	if( whs.eventCode == 11 && (whs.keycode == 30 || whs.keycode == 31) )
		ControlInfo/W=Graph3#P0 list0
		wave/T listWave = $S_value
		variable oldRow = V_Value, newRow
		if( whs.keycode == 30 )	// cursor up
			newRow = max(0, oldRow - 1)
		else						// cursor down
			newRow = min(numpnts(listWave) - 1, oldRow + 1)
		endif
		SwapWaves(oldRow, newRow, listWave)
		ListBox list0, selRow= newRow, win= Graph3#P0
	endif
end
Thank you, Wolfgang. Your hack seems to work. The Start3 example was naturally only kept so simple to illustrate the issue properly.
For my purpose I established another quick and dirty solution: Clicking the listbox kills the external panel and I put a button on the host panel which invokes the external panel (and the listbox) again. I have anyway a lot of buttons on the host panel, so one more doesn't hurt. Thanks again, Wolfgang, for your effort.
This is clearly a bug in the Listbox control- it should relinquish the keyboard focus when the graph becomes the active window. But establishing that the graph is the active window is somewhat more complicated when the listbox is in an exterior panel attached to the graph.

I will put this on my list of things to look into.

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
I seem to have the same problem (I can not get rid of the keyboard focus on the listbox, which sits in an exterior subwindow of a graph).
Are there any news on this issue?

I'm using Igor 6.21 on Windows XP SP3.
thomas_braun wrote: Are there any news on this issue?


There are.
I had an off-list discussion with John several months ago. He suggested to disable the listbox temporarily:
	ListBox theList,win=pathToThe#ExtWin,disable=1
	ListBox theList,win=pathToThe#ExtWin,disable=0

This worked for me very nicely and replaced my 100-line workaround by just 2 lines.

A