function EyelinkEventExample
% Short MATLAB example program to demonstrate the use of events
% with the Eyelink and Psychophysics Toolboxes. When subject gazes at an object
% it changes color. When gaze moves away, it toggles back
%

% history
% 28-10-02	fwc	created it, based on eyelinkexample
% 27-11-02	fwc	changed dialog for dummy mode question, fixed dodriftcorrection bug
% 07-07-10  fwc adapted to use new psychtooblox/eyelink functions, finally
%           got toggling correct too ;-)
%

clear all;
commandwindow;
dummymode=0;       % set to 1 to run in dummymode (using mouse as pseudo-eyetracker)
showboxes=1;        % set to 1 to show boxes within which you have to fixate in order to toggle a number

try
    
    fprintf('EyelinkToolbox Event Example\n\n\t');
    
    % STEP 1
    % Open a graphics window on the main screen
    % using the PsychToolbox's Screen function.
    screenNumber=max(Screen('Screens'));
    window=Screen('OpenWindow', screenNumber);
    
    % STEP 2
    % Provide Eyelink with details about the graphics environment
    % and perform some initializations. The information is returned
    % in a structure that also contains useful defaults
    % and control codes (e.g. tracker state bit and Eyelink key values).
    el=EyelinkInitDefaults(window);
    % Disable key output to Matlab window:
    ListenChar(2);
    
    % STEP 3
    % Initialization of the connection with the Eyelink Gazetracker.
    % exit program if this fails.
    if ~EyelinkInit(dummymode, 1)
        fprintf('Eyelink Init aborted.\n');
        cleanup;  % cleanup function
        return;
    end
    
    [v vs]=Eyelink('GetTrackerVersion');
    fprintf('Running experiment on a ''%s'' tracker.\n', vs );
    
    % make sure that we get event data from the Eyelink
%         Eyelink('Command', 'link_sample_data = LEFT,RIGHT,GAZE,AREA');
    Eyelink('command', 'link_event_data = GAZE,GAZERES,HREF,AREA,VELOCITY');
    Eyelink('command', 'link_event_filter = LEFT,RIGHT,FIXATION,BLINK,SACCADE,BUTTON');
    
    % open file to record data to
    edfFile='demo.edf';
    Eyelink('Openfile', edfFile);
    
    % STEP 4
    % Calibrate the eye tracker
    EyelinkDoTrackerSetup(el);
    
    
    % STEP 5
    % draw a stimulus in a set of buffers
    [buffer, altbuffer, object]=DrawStimulus(window, showboxes);
    
    Screen('TextFont', buffer, el.msgfont);
    Screen('TextSize', buffer, el.msgfontsize);
    Screen('TextFont', altbuffer, el.msgfont);
    Screen('TextSize', altbuffer, el.msgfontsize);
    [width, height]=Screen('WindowSize', window);
    message='Press space to stop.';
    Screen('DrawText', buffer, message, 200, height-el.msgfontsize-20, el.msgfontcolour);
    Screen('DrawText', altbuffer, message, 200, height-el.msgfontsize-20, el.msgfontcolour);

    
    % STEP 6
    % do a final check of calibration using driftcorrection
    success=EyelinkDoDriftCorrection(el);
    if success~=1
        cleanup;
        return;
    end
    
    % STEP 7
    % some final preparations
    stopkey=KbName('space');
    lastchoice=-1;
    choice=-1;
    doflip=0;
    % put buffer on screen
    Screen('CopyWindow', buffer, window);
    Screen('Flip',  window, [], 1); % don't erase buffer
    
    % start recording eye position
    Eyelink('startrecording');
    % record a few samples before we actually start displaying
    waitsecs(0.1);
    % mark zero-plot time in data file
    Eyelink('message', 'SYNCTIME');
    
    % STEP 8
    % adapt display based on END-SACCADE events
    while 1 % loop till error or space bar is pressed
        error=Eyelink('checkrecording');        % Check recording status, stop display if error
        if(error~=0)
            break;
        end
        
        [keyIsDown,secs,keyCode] = KbCheck; % check for keyboard press
        if keyCode(stopkey) % if spacebar was pressed stop display
            break;
        end
        
        % check for endsaccade events
        if Eyelink('isconnected') == el.dummyconnected % in dummy mode use mousecoordinates
            [x,y,button] = GetMouse(window);
            evt.type=el.ENDSACC;
            evt.genx=x;
            evt.geny=y;
            evtype=el.ENDSACC;
        else % check for events
            evtype=Eyelink('getnextdatatype');
        end
        if evtype==el.ENDSACC		% if the subject finished a saccade check if it fell on an object
            if Eyelink('isconnected') == el.connected % if we're really measuring eye-movements
                evt = Eyelink('getfloatdata', evtype); % get data
            end
            % check if saccade landed on an object
            choice=-1;
            noobject=0;
            i=1;
            while 1
                if 1==IsInRect(evt.genx,evt.geny, object(i).rect )
                    choice=i;
                    break;
                end
                i=i+1;
                if i>length(object)
                    noobject=1;
                    break;
                end
            end
            if lastchoice>0 && (choice~=lastchoice || noobject==1) % toggle object color
                if object(lastchoice).on==1 % restore screen
                    Screen('CopyWindow', buffer, window, object(lastchoice).rect, object(lastchoice).rect);
                    object(lastchoice).on=0;
                    lastchoice=-1;
                    doflip=1;
                end
            end
            if choice>0 && choice~=lastchoice % toggle object color
                if object(choice).on==0 % toggle object on screen
                    Screen('CopyWindow', altbuffer, window, object(choice).rect, object(choice).rect);
                    object(choice).on=1;
                    doflip=1;
                end
                lastchoice=choice;
            end
            if doflip==1
                Screen('Flip',  window, [], 1);
                doflip=0;
            end
        end % saccade?
    end % main loop
    
    % STEP 9
    % finish demo
    waitsecs(0.1);	% wait a while to record a few more samples 
    cleanup;
    
catch myerr
    %this "catch" section executes in case of an error in the "try" section
    %above.  Importantly, it closes the onscreen window if its open.
    cleanup;
    commandwindow;
    myerr;
    myerr.message
    myerr.stack.line
end %try..catch.


% Cleanup routine:
function cleanup

% finish up: stop recording eye-movements,
% close graphics window, close data file and shut down tracker
% Eyelink('Stoprecording');
% Eyelink('CloseFile');
Eyelink('Shutdown');

% Close window:
sca;

% Restore keyboard output to Matlab:
ListenChar(0);

function [buffer, altbuffer, object]=DrawStimulus(window, showboxes)

if ~exist('showboxes', 'var') || isempty(showboxes)
    showboxes=0;
end
white=WhiteIndex(window);
black=BlackIndex(window);
gray=GrayIndex(window);
Screen(window, 'FillRect',gray);
[w,h]=WindowSize(window);
[x,y]=WindowCenter(window);
fontsize=round(w/100*5);
oldFont=Screen(window,'TextFont','Arial');
oldFontSize=Screen(window,'TextSize',fontsize);

buffer=Screen(window, 'OpenOffscreenWindow', gray);
altbuffer=Screen(window, 'OpenOffscreenWindow', gray);

cols=5;
rows=4;

Screen(buffer,'TextFont','Arial');
Screen(altbuffer,'TextFont','Arial');
Screen(buffer,'TextSize',fontsize);
Screen(altbuffer,'TextSize',fontsize);
k=1;
xdist=round(w/(cols));
ydist=round(h/(rows));
x0=x-((cols-1)/2)*xdist;
y0=y-((rows-1)/2)*ydist;
for i=1:rows
    for j=1:cols
        text=num2str(k);
        xpos=round(x0+(j-1)*xdist-fontsize/2);
        ypos=round(y0+(i-1)*ydist-fontsize/2);
        Screen(buffer,'DrawText',text,xpos,ypos,white);
        Screen(altbuffer,'DrawText',text,xpos,ypos,black);
        rect= Screen('TextBounds', window, text, xpos,ypos ); %[,yPositionIsBaseline] [,swapTextDirection]);
        object(k).rect=OffsetRect(rect, xpos, ypos);
        if showboxes==1
            Screen('FrameRect', buffer, black, object(k).rect);
            Screen('FrameRect', altbuffer, white, object(k).rect);
        end
        object(k).on=0;
        k=k+1;
    end
end

Screen(window,'TextFont',oldFont);
Screen(window,'TextSize',oldFontSize);
