function info = browser_kpfun(in,flag)

% browser_kpfun - key press function for browser figure
% -----------------------------------------------------
%
% browser_kpfun(h)
% browser_kpfun(key,info)
%
% Input:
% ------
%  h - handle of figure
%  key - key to trigger action
%  flag - keypress function info flag
%
% Output:
% -------
%  info - keypress function info

%--------------------------------
% Author: Harold Figueroa
%--------------------------------
% $Revision: 1681 $
% $Date: 2005-08-25 10:08:56 -0400 (Thu, 25 Aug 2005) $
%--------------------------------

% TODO: update to use 'currentkey' property of figure as well as
% 'currentcharacter'. correct use of these two should allow for significant
% improvements to key binding. eventually allow for programmable keys, this
% will require the enumeration of commands, this will come along with
% scripting

%--------------------------------------------
% HANDLE INPUT
%--------------------------------------------

%--
% set info handle
%--

if ((nargin < 2) || isempty(flag))
	flag = 0;
end

%--
% handle variable first input
%--

if (nargin)
	
	%--
	% key to trigger action input
	%--
	
	if (ischar(in))
		
		%--
		% get numeric code for key and current figure
		%--
		
		key = in; code = double(key);
		
	%--
	% handle to set keypress input
	%--
	
	elseif (nargin < 2)
		
		%--
		% attach key press function to handle
		%--
		
		h = in;
		
		if (ishandle(h) && strcmp(get(h,'type'),'figure'))
			set(h,'keypressfcn','browser_kpfun;');
		end
		
		return;
		
	%--
	% code to get keypress info input
	%--
	
	else
		
		code = in;
		
	end
	
	h = gcf;
	
else
	
	%--
	% get numeric code for current character
	%--
	
	h = gcf;
	
	key = get(h,'currentcharacter');
	
	code = double(key);
	
end

%--
% display code and key
%--

% NOTE: current key is essential to capturing the special key events

% disp(' ');
% disp(get(h,'tag'));
% disp([ ...
% 	'code = ', int2str(code), ', ', ...
% 	'char = ''', char(code), ''', ', ...
% 	'key = ''' get(gcf,'currentkey') '''' ...
% ]);

% NOTE: this is no longer in use because the java implementation of figures
% does not allow for the use of multiple screens

% %--
% % update state of flocking daemon
% %--
% 
% if (strcmp(get(h,'currentkey'),'shift'))
% 	
% 	tmp = timerfind('name','XBAT Palette Glue Daemon');
% 
% 	if (~isempty(tmp))
% 		set(tmp,'userdata',1);
% 	end
% 	
% end

%--
% set default output
%--

info = [];

%--
% handle function keys
%--

% NOTE: at the moment we use these for various visibility commands

% TODO: consider making some of these available to the users

key = get(h,'currentkey');

if (~isempty(key) && (key(1) == 'f'))
	
	switch (key)

		%--
		% toggle palette display
		%--
		
		case ('f1')
			browser_window_menu(h,'Hide Palettes');
		
		%--
		% toggle other sounds display
		%--
		
		case ('f2')
			browser_window_menu(h,'TOGGLE_OTHERS');
		
		%--
		% toggle desktop display
		%--
		
		case ('f3')
			browser_window_menu(h,'TOGGLE_DESKTOP');
		
		%--
		% cycle through open sounds, previous and next sound
		%--
		
		% NOTE: this is particularly useful when hiding other sounds
		
		% NOTE: 'f6' is back because forward is more intuitive and 'f5' more accesible
		
		case ('f5')
			show_browser(h,'next'); 
		
		case ('f6')
			show_browser(h,'previous');

	end
	
	return;
	
end 
	
%--
% return on empty characters
%--

if (isempty(code))
	return;
end

%--
% create keypress info
%--

info = kinfo_create(code);

%--------------------------------------------
% KEYSTROKE COMMANDS
%--------------------------------------------

switch (code)
	
	%--------------------------------------------
	% MODE COMMANDS
	%--------------------------------------------
		
	%--
	% Hand Mode
	%--
	
	case (double('h'))
		
		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'Hand Mode';
			info.category = 'Mode';
			info.description = ...
				'Put browser in hand selection mode. This permits fine scale time navigation.';
			
			return;
			
		end	
		
		% NOTE: this command may also be put into some menu
		
		set_browser_mode(gcf,'hand');
		
	%--
	% Select Mode
	%--
	
	case (double('s'))
		
		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'Select Mode';
			info.category = 'Mode';
			info.description = ...
				'Put browser in familiar rectangle selection mode. This permits creation of new rectangle selections.';
			
			return;
			
		end	
		
		% NOTE: this command may also be put into some menu
		
		set_browser_mode(gcf,'select');
				
	%--------------------------------------------
	% SOUND COMMANDS
	%--------------------------------------------
	
	%--
	% Play Page
	%--

	case (double('P'))

		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'Play Page';
			info.category = 'Play'; 
			info.description = [ ...
				'Play currently displayed page. ' ...
				'When there is no designated left and right channels are played, ' ...
				'otherwise only the selection channel is played' ...
			];
			
			return;
			
		end
		
		browser_sound_menu(gcf,'Page');
		
	%--
	% Play Selection
	%--
	
	case (double('p'))
		
		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'Play Selection';
			info.category = 'Play';
			info.description = ...
				'Play current selection. Only available when a selection is available.';
			
			return;
			
		end
		
		%--
		% get availability of selection from menu state
		%--
		
		data = get(gcf,'userdata');
		
		% NOTE: return if current figure is not a proper browser figure
		
		if (~isfield(data,'browser'))
			return;
		end
		
		tmp = get_menu(data.browser.sound_menu.play,'Selection');
		
		%--
		% play selection or page
		%--
				
		if (strcmp(get(tmp,'enable'),'on'))
			browser_sound_menu(gcf,'Selection');
		else
			browser_sound_menu(gcf,'Page');
		end
		
	%--
	% Other Rate
	%--
	
	case (double('r'))

		%-------
		% INFO
		%-------
		
		if (flag)

			info.name = 'Other Rate ...';
			info.category = 'Play';
			info.description = ...
				'Open ''Sound'' palette to edit playback rate.';
			
			return;
			
		end
		
		browser_sound_menu(gcf,'Other Rate ...');
		
	%--
	% Volume Control
	%--
	
	case (double('v'))
		
		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'Volume';
			info.category = 'Play';
			info.description = ...
				'Open ''Windows'' volume control.';
			
			return;
			
		end	
			
		browser_sound_menu(gcf,'Volume Control ...');
		
	%--------------------------------------------
	% NAVIGATE COMMANDS
	%--------------------------------------------
		
	% NOTE: the view navigation is currently unstable under the new
	% navigation framework
	
	%--
	% Previous Event
	%--
	
	case (double('E'))

		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'Previous Event';
			info.category = 'Navigate';
			info.description = ...
				'Go to previous event. This works according to event palette, so it only works when the event palette is open.';
			
			return;
			
		end	
		
		%--
		% try to get event palette, if not found  return
		%--
		
		g = get_palette(gcf,'Event');
		
		if (isempty(g))
			return;
		end
		
		%--
		% execute previous event callback
		%--
		
		control_callback([],g,'previous_event');
		
	%--
	% Next Event
	%--
	
	case (double('e'))

		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'Next Event';
			info.category = 'Navigate';
			info.description = ...
				'Go to next event. This works according to event palette, so it only works when the event palette is open.';
			
			return;
			
		end	
		
		%--
		% try to get event palette, if not found return
		%--
		
		g = get_palette(gcf,'Event');
		
		if (isempty(g))
			return;
		end
		
		%--
		% execute previous event callback
		%--
		
		control_callback([],g,'next_event');
		
	%--
	% Previous View
	%--
	
	case (double('<'))
		
		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'Previous View';
			info.category = 'Navigate';
			info.description = ...
				'Go to previous view. The view keeps track of a number of display variables.';
			
			return;
			
		end	
		
		browser_view_menu(gcf,'Previous View');
		
	%--
	% Next View
	%--
	
	case (double('>'))
		
		%-------
		% INFO
		%-------
		
		if (flag)
		
			info.name = 'Next View';
			info.category = 'Navigate';
			info.description = ...
				'Go to next view. The view keeps track of a number of display variables.';
			
			return;
			
		end	
		
		browser_view_menu(gcf,'Next View');
		
	%--
	% Previous Page (back arrow)
	%--
	
	case ({28, double('b')})
		
		%-------
		% INFO
		%-------
		
		if (flag)
		
			% at the moment there is no graceful way of documenting
			% multiple keys
			
			if (code == double('b'))
				info = [];
				return;
			end
			
			info.name = 'Previous Page';
			info.category = 'Navigate';
			info.description = ...
				'Move to previous page. Updates the start time of the page based on the page settings.';
			
			return;
			
		end
		
		browser_view_menu(gcf,'Previous Page');
		
	%--
	% Next Page (forward arrow)
	%--
	
	case ({29, double('n')})
		
		%-------
		% INFO
		%-------
		
		if (flag)
	
			% at the moment there is no graceful way of documenting
			% multiple keys
			
			if (code == double('n'))
				info = [];
				return;
			end
			
			info.name = 'Next Page';
			info.category = 'Navigate';
			info.description = ...
				'Move to next page. Updates the start time of the page based on the page settings.';
			
			return;
			
		end
		
		browser_view_menu(gcf,'Next Page');
		
	%--
	% First Page (up arrow)
	%--
	
	case (30)
		
		%-------
		% INFO
		%-------
		
		if (flag)
			
			% NOTE: at the moment there is no graceful way of documenting multiple shortcut keys
			
			if (code == double('s'))
				info = [];
				return;
			end
			
			info.name = 'First Page';
			info.category = 'Navigate';
			info.description = ...
				'Move to first page. Sets the start of the page to start of sound.';
			
			return;
			
		end
		
		browser_view_menu(gcf,'First Page');
		
	%--
	% Last Page (down arrow)
	%--
	
	case (31)
		
		%-------
		% INFO
		%-------
		
		if (flag)

			% NOTE: at the moment there is no graceful way of documenting
			% multiple keys
			
			if (code == double('e'))
				info = [];
				return;
			end
			
			info.name = 'Last Page';
			info.category = 'Navigate';
			info.description = ...
				'Move to last page. Sets the start time of the page to display last page given page settings.';
			
			return;
			
		end
		
		browser_view_menu(gcf,'Last Page');
		
	%--
	% Go To Page ...
	%--
	
	case (double('g'))
		
		%-------
		% INFO
		%-------
		
		if (flag)

			info.name = 'Go To Page ...';
			info.category = 'Navigate';
			info.description = ...
				'Opens ''Navigate'' palette so that a specific start of the page may be set.';
			
			return;
			
		end
		
		browser_view_menu(gcf,'Go To Page ...');
		
	%--
	% Previous File
	%--
	
	% this should be an idempotent commmand, look through the code
	
	case (double('['))
		
		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'Previous File';
			info.category = 'Navigate';
			info.description = ...
				'Move to start of previous file. Sets the start time of the page to the start of the current file.';
			
			return;
			
		end
		
		browser_view_menu(gcf,'Previous File');
		
	%--
	% Next File
	%--
	
	case (double(']'))
		
		%-------
		% INFO
		%-------
		
		if (flag)

			info.name = 'Next File';
			info.category = 'Navigate';
			info.description = ...
				'Move to start of next file. This sets the start time of the page to the start of the next file.';
			
			return;
			
		end
		
		browser_view_menu(gcf,'Next File');
		
	%--
	% Go To File ...
	%--
	
	case (double('f'))
		
		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'Go To File ...';
			info.category = 'Navigate';
			info.description = [ ...
				'Open the ''Navigate'' palette so that a specific file to jump to may be selected. ' ...
				'Only available when the sound is a ''File Stream'', a multiple file sound.' ...
			];
			
			return;
			
		end
		
		browser_view_menu(gcf,'Go To File ...');
		
	%--------------------------------------------
	% MODE COMMANDS
	%--------------------------------------------
	
	% these modes are not implemented, this code is here to reserve the
	% use of these keys
	
% 	%--
% 	% Zoom Mode
% 	%--
% 	
% 	case (double('Z'))
% 		
% 		set_ptr(gcf,'glass');
% 		
% 	%--
% 	% Selection Mode
% 	%--
% 	
% 	case (double('S'))
% 		
% 		set_ptr(gcf,'crosshair');
% 		
% 	%--
% 	% Arrow (Arrange) Mode
% 	%--
% 	
% 	% this should be called the grouping mode, however 'g' and 'G' are used
% 
% 	case (double('A'))
% 		
% 		set_ptr(gcf,'arrow');
		
	%--------------------------------------------
	% FILTERING COMMANDS
	%--------------------------------------------
	
	% this command is becoming obsolete, it no longer appears in a menu
	
	%--
	% Difference Signal
	%--
	
	case (double('d'))
		
		%-------
		% INFO
		%-------
		
		if (flag)
			info = [];
			return;
		end
		
		browser_view_menu(gcf,'Difference Signal');
		
	%--------------------------------------------
	% COLORMAP COMMANDS
	%--------------------------------------------
	
	%--
	% Gray 
	%--
	
	case (double('G'))
		
		%-------
		% INFO
		%-------
		
		if (flag)

			info.name = 'Gray';
			info.category = 'Colormap';
			info.description = ...
				'Set the ''Gray'' colormap as the current colormap.';
			
			return;
			
		end
		
		browser_view_menu(gcf,'Gray ');
	
	%--
	% Hot 
	%--
	
	case (double('H'))
		
		%-------
		% INFO
		%-------
		
		if (flag)

			info.name = 'Hot';
			info.category = 'Colormap';
			info.description = ...
				'Set the ''Hot'' colormap as the current colormap.';
			
			return;
			
		end
		
		browser_view_menu(gcf,'Hot');
		
	%--
	% Jet
	%--
	
	case (double('J'))
		
		%-------
		% INFO
		%-------
		
		if (flag)

			info.name = 'Jet';
			info.category = 'Colormap';
			info.description = ...
				'Set the ''Jet'' colormap as the current colormap.';
			
			return;
			
		end
		
		browser_view_menu(gcf,'Jet');
		
	%--
	% Bone
	%--
	
	case (double('B'))
		
		%-------
		% INFO
		%-------
		
		if (flag)

			info.name = 'Bone';
			info.category = 'Colormap';
			info.description = ...
				'Set the ''Bone'' colormap as the current colormap.';
			
			return;
			
		end
		
		browser_view_menu(gcf,'Bone');
		
	%--
	% HSV
	%--
	
	case (double('V'))
		
		%-------
		% INFO
		%-------
		
		if (flag)

			info.name = 'HSV';
			info.category = 'Colormap';
			info.description = ...
				'Set the ''HSV'' (Hue-Saturation-Value) colormap as the current colormap.';
			
			return;
			
		end
		
		browser_view_menu(gcf,'Jet');
		
	%--
	% Colorbar
	%--
	
	case (double('c'))
		
		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'Colorbar';
			info.category = 'Colormap';
			info.description = ...
				'Toggle display of colorbar.';
			
			return;
			
		end
		
		browser_view_menu(gcf,'Colorbar');
		
	%--
	% Auto Scale
	%--
	
	case (double('a'))
			
		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'Auto Scale';
			info.category = 'Colormap';
			info.description = [ ...
				'Toggle automatic scaling of colormap. ' ...
				'The automatically scaled colormap allocates more colors to be used for the higher energy spectrogram bins.' ...
			];
		
			return;
			
		end
		
		browser_view_menu(gcf,'Auto Scale');
			
	%--
	% Invert
	%--
	
	case (double('i'))

		%-------
		% INFO
		%-------
		
		if (flag)
		
			info.name = 'Invert';
			info.category = 'Colormap';
			info.description = ...
				'Toggle inversion of the colormap.';
			
			return;
			
		end
		
		browser_view_menu(gcf,'Invert');
		
	%--------------------------------------------
	% SELECTION COMMANDS
	%--------------------------------------------
	
	%--
	% Delete Selection (delete)
	%--
	
	% NOTE: this key is reused to stop play
	
	case (127)

		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'Delete Selection';
			info.category = 'Selection';
			info.description = ...
				'Delete the current selection.';
			
			return;
			
		end
		
		%--
		% check for sound player
		%--
		
		% NOTE: eventually there may be multiple players, one per parent
		
		player = timerfind('name','PLAY_TIMER');
		
		if (~isempty(player))
			stop(player); return;
		end
		
		%--
		% delete selection from current figure
		%--
		
		browser_edit_menu(gcf,'Delete Selection');
	
	%--
	% Log Selection To
	%--
	
	% there is some problem with the naming of this command
	
	case (double('l'))
		
		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'Log Selection';
			info.category = 'Selection';
			info.description = ...
				'Log the current selection to the active log.';
			
			return;
			
		end
		
		tmp = get_menu(gcf,'Log Selection To');
		tmp = get(tmp,'children');
		
		if (strcmp(get(tmp,'enable'),'on'))
			browser_edit_menu(gcf,'Log Selection To');
		end
		
	%--
	% Selection Grid
	%--
	
	case (double(''''))
			
		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'Selection Grid';
			info.category = 'Selection';
			info.description = ...
				'Toggle display of selection grid.';
			
			return;
			
		end
		
		browser_view_menu(gcf,'Grid');
				
	%--
	% Selection Labels
	%--
	
	case (double('"'))

		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'Selection Labels';
			info.category = 'Selection';
			info.description = ...
				'Toggle display of selection labels. The labels are only visible when the selection grid is visible.';
			
			return;
			
		end
		
		browser_view_menu(gcf,'Labels');
				
	%--
	% Control Points
	%--
	
	case (double('.'))

		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'Control Points';
			info.category = 'Selection';
			info.description = ...
				'Toggle display of selection control points.';
			
			return;
			
		end
		
		browser_view_menu(gcf,'Control Points');
		
	%--
	% Selection Zoom
	%--
	
	% NOTE: this is a mode, however it sometimes behaves as an action
	
	case (double('z'))
		
		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'Selection Zoom';
			info.category = 'Selection';
			info.description = ...
				'Toggle display of selection zoom.';
			
			return;
			
		end
		
		browser_view_menu(gcf,'Selection Zoom');
			
	%--------------------------------------------
	% GRID COMMANDS
	%--------------------------------------------
	
	%--
	% Time Grid (used to be 'Grid')
	%--
	
	case (double(';'))
	
		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'Time Grid';
			info.category = 'Grid';
			info.description = ...
				'Toggle display of time grid.';
			
			return;
			
		end
		
		browser_view_menu(gcf,'Time Grid');
				
	%--
	% File Grid
	%--
	
	case (double(':'))

		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'File Grid';
			info.category = 'Grid';
			info.description = ...
				'Toggle display of file grid.';
			
			return;
			
		end
		
		browser_view_menu(gcf,'File Grid');
			
	%--------------------------------------------
	% MISCELLANEOUS COMMANDS
	%--------------------------------------------
	
	%--
	% Actual Size
	%--
	
	case (double('='))
		
		%-------
		% INFO
		%-------
		
		if (flag)
	
			info.name = 'Actual Size';
			info.category = 'Window';
			info.description = [ ...
				'Resize the window to try produce a pixel to pixel display of spectrogram images. ' ...
				'Pixel to pixel display means there is a correspondence between image pixels and screen pixels.' ...
			];
		
			return;
			
		end
		
		browser_window_menu(gcf,'Actual Size');
		
	%--
	% Half Size
	%--
	
	case (double('-'))

		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'Half Size';
			info.category = 'Window';
			info.description = [ ...
				'Resize the window to try a half of actual size display of spectrogram images. ' ...
			];
		
			return;
			
		end
		
		browser_window_menu(gcf,'Half Size');
		
	%--
	% these commands are no longer used
	%--
	
% 	%--
% 	% Refresh
% 	%--
% 	
% 	case (double('w'))
%
% 		browser_window_menu(gcf,'Refresh');
% 	
% 	%--
% 	% Full Refresh
% 	%--
% 	
% 	case (double('W'))
% 		browser_display(gcf);
		
	%--------------------------------------------
	% PALETTE COMMANDS
	%--------------------------------------------
	
	case (double('x'))

		%-------
		% INFO
		%-------
		
		if (flag)
			
			info.name = 'XBAT';
			info.category = 'Window';
			info.description = [ ...
				'Display and position XBAT palette.' ...
			];
		
			return;
			
		end
		
		xbat_palette;
						
	%--------------------------------------------
	% SELECTION MODE COMMANDS
	%--------------------------------------------
	
% 	%--
% 	% toggle adding state
% 	%--
% 	
% 	case ({double('+'),double('=')})
% 		
% 		%--
% 		% get plus pointer image data
% 		%--
% 		
% 		[type,X] = set_custom_pointer([],'plus');
% 		
% 		% remove nans
% 		
% 		ix = find(isnan(X));
% 		X(ix) = 10;
% 		
% 		%--
% 		% get pointer state from figure
% 		%--
% 		
% 		ptr = get(gcf,'pointer');
% 		
% 		Y = get(gcf,'pointershapecdata');
% 			
% 		% remove nans
% 		
% 		ix = find(isnan(Y));
% 		Y(ix) = 10;
% 		
% 		%--
% 		% check whether we are in the plus state
% 		%--
% 		
% 		if (strcmp(ptr,'custom') && all(X == Y))
% 			
% 			% we are in plus return to default
% 			
% 			set(gcf,'pointer','arrow');
% 			
% 		else
% 			
% 			% we are in some other state move to plus
% 			
% 			set_custom_pointer(gcf,'plus');
% 			
% 		end
% 		
% 	%--
% 	% toggle deleting state
% 	%--
% 	
% 	case (double('-'))
% 		
% 		%--
% 		% get minus pointer image data
% 		%--
% 		
% 		[type,X] = set_custom_pointer([],'minus');
% 		
% 		% remove nans
% 		
% 		ix = find(isnan(X));
% 		X(ix) = 10;
% 		
% 		%--
% 		% get pointer state from figure
% 		%--
% 		
% 		ptr = get(gcf,'pointer');
% 		
% 		Y = get(gcf,'pointershapecdata');
% 			
% 		% remove nans
% 		
% 		ix = find(isnan(Y));
% 		Y(ix) = 10;
% 		
% 		%--
% 		% check whether we are in the minus state
% 		%--
% 		
% 		if (strcmp(ptr,'custom') && all(X == Y))
% 			
% 			% we are in minus return to default
% 			
% 			set(gcf,'pointer','arrow');
% 			
% 		else
% 			
% 			% we are in some other state move to minus
% 			
% 			set_custom_pointer(gcf,'minus');
% 			
% 		end
		
	%--
	% otherwise
	%--
	
	otherwise
		
		%--
		% there is no info output
		%--
		
		info = [];
		
end