view ExperimentGui.java @ 23:9fc8683b8fed

Fixed GUI button presses, had their background change as feedback and added ability to record responses for a probe tone at the end of a sequence
author JShulver
date Wed, 07 Nov 2012 18:22:01 +0000
parents 3dd7636ca811
children c5db34797ff3
line wrap: on
line source
/*=============================================================================
 * File:       ExperimentGui.java
 * Author:     Marcus Pearce <m.pearce@gold.ac.uk>
 * Created:    <2007-02-14 16:42:31 marcusp>
 * Time-stamp: <2011-11-04 17:41:45 marcusp>
 *=============================================================================
 */

import java.awt.*;
import javax.swing.*;
import java.util.ArrayList; 
import java.util.Iterator;

public class ExperimentGui extends JFrame implements Runnable {

    /* the Experiment */ 
    private Experiment exp; 

    /* The visual display indicating probe positions */ 
    private Clock clock; 

    /* The UI components */ 
    private JPanel mainPanel; 
    private InstructionsPanel instructionsPanel;
    private StimulusPanel stimulusPanel; 
    private SubjectDataPanel subjectDataPanel; 
    private InterBlockPanel interBlockPanel; 
    
    /* Whether we are accepting responses */ 
    private Boolean acceptingResponses; 
    
    /* accessors */ 
    public Boolean getAcceptingResponses() { return acceptingResponses; }
    public void setAcceptingResponses(Boolean b) { 
        if (exp.getDebug()) 
            System.out.println("\n\nChanging acceptingResponses from " + acceptingResponses + " to " + b); 
        acceptingResponses = b;
    }
    public Experiment getExperiment() { return exp; }
    public InstructionsPanel getInstructionsPanel() { return instructionsPanel; }
    public StimulusPanel getStimulusPanel() { return stimulusPanel; } 
    public SubjectDataPanel getSubjectDataPanel() { return subjectDataPanel; }
    public InterBlockPanel getInterBlockPanel() { return interBlockPanel; }
    
    /* Constructor */ 
    public ExperimentGui(Experiment experiment) {

        // initialise experiment 
        exp = experiment; 
        acceptingResponses = false; 

        // set up the clock 
        clock = new Clock(); 
        
        // construct the frame
        JFrame.setDefaultLookAndFeelDecorated(true);
        this.getContentPane().setBackground (Color.black);
        this.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
        this.setLayout (new BorderLayout());
                
        // The different cards 
        instructionsPanel = new InstructionsPanel(this);
        stimulusPanel = new StimulusPanel(this, clock); 
        interBlockPanel = new InterBlockPanel(exp); 
        subjectDataPanel = new SubjectDataPanel(this, exp.getSubjectResults()); 
        
        // The Controller 
        ExperimentController ec = new ExperimentController(this); 

        // Show it all 
        CardLayout cl = new CardLayout(); 
        mainPanel = new JPanel(cl); 
        mainPanel.add(instructionsPanel, "instructions"); 
        mainPanel.add(interBlockPanel, "interblock"); 
        mainPanel.add(stimulusPanel, "stimulus"); 
        mainPanel.add(subjectDataPanel, "subject"); 

        this.add(mainPanel, BorderLayout.CENTER); 
    }

    /* 
     * Methods for changing displayed card 
     */ 
    
    public void showCard(String card) { 
        CardLayout cl = (CardLayout)(mainPanel.getLayout());
        cl.show(mainPanel, card);
    }

    public void nextCard() { 
        CardLayout cl = (CardLayout)(mainPanel.getLayout());
        cl.next(mainPanel); 
    }
    
    /* Advance clock by 1 minute and redisplay. */
    public void tick(int n) {
        clock.tick(n);
        clock.repaint();
    }

    /* Show the Clock */ 
    public void showClock() { 
        if (exp.showClock()) {
            clock.showClock = true;
            clock.showFullClock = false; 
            clock.repaint();
        }
    } 

    /* Show the Fixation Point */ 
    public void showFixationPoint() { 
        System.out.println("showFixationPoint");
        clock.showClock = false; 
        clock.showFullClock = false; 
        clock.repaint(); 
    } 
    
    /* Run clock for r revolutions at a rate of 1 minute (6 degrees)
     * every n milliseconds. 
     */
    public void runClock(int r, long n) {
        clock.reset(); 
        showClock(); 
        for (int i = 0; i < (60 * r); i++) {
            try { Thread.sleep (n); } catch (InterruptedException e) {}
               clock.tick(1);
               clock.repaint();
        }
        try { Thread.sleep (1000); } catch (InterruptedException e) {}
        showFixationPoint(); 
    }
    

    /* Run method for this thread */
    public void run() { 
        System.out.println("Run!");
        //showFixationPoint(); 
        clock.reset(); 
        showClock(); 

        int clockUnits = exp.getClockUnits(); 
        int numUnits = exp.getNumUnits(); 
        long tatum = exp.getCurrentBlock().getTatum(); 
        long tatumInMilliseconds = tatum / 1000; 
        int nMinutes = 60 / numUnits; 
        
        ArrayList onsets = exp.getCurrentBlock().getOnsets(); 
        ArrayList probes = exp.getCurrentBlock().getProbePositions(); 
        ArrayList clockStartTimes = exp.getCurrentBlock().getClockStartTimes(); 
            
        Iterator oi = onsets.iterator(); 
        Iterator pi = probes.iterator(); 
        Iterator ci = clockStartTimes.iterator(); 
        
        ProbeID probe = ProbeID.NOT_PROBE; 

        long currentOnset = 0; 
        long nextEventOnset = ((Long)(oi.next())).longValue();
        long nextClockStartTime = ((Long)(ci.next())).longValue();

        int clockUnit = 0; 
        boolean clockTicking = false; 

         do { //using a do-while construct allows the user to enter a value at the end
         //this should not really be in the 'view' anyway...
            System.out.println("TATUM: " +tatum);
            tatumInMilliseconds = tatum/1000;   
            if (exp.getDebug())
                System.out.println("Ticking = " + clockTicking + 
                                   "; clockUnit = " + clockUnit + 
                                   "; currentOnset = " + currentOnset + 
                                   "; nextEventOnset = " + nextEventOnset + 
                                   "; nextClockStartTime = " + nextClockStartTime + 
                                   "; probe = " + probe); 
            if (clockTicking == true && clockUnit == 0)
                tick(nMinutes); 
            
            if (currentOnset >= nextClockStartTime) { 
                //new Thread(clock).start(); 
                clock.reset(); 
                showClock(); 
                clockTicking = true; 
                if (ci.hasNext())
                    nextClockStartTime = ((Long)(ci.next())).longValue();
                else
                    nextClockStartTime = Long.MAX_VALUE;
            }
            if (currentOnset >= nextEventOnset) { 
                 probe = (ProbeID)pi.next(); 
                // Manipulate display depending on probe identifier
                switch (probe) { 
                case NOT_PROBE: 
                    // if (clock.showClock == true) 
                    //    tick(nMinutes); 
                    break; 
                case START_CLOCK: 
                    //clock.reset(); 
                    //showClock(); 
                    //tick(nMinutes); 
                    break; 
                case BEFORE_PROBE:
                    if (exp.getDebug())
                        System.out.println("BEFORE_PROBE: acceptingResponses = " + 
                                           acceptingResponses); 
                    if (acceptingResponses == true) 
                        exp.getCurrentBlock().addResponse(0, System.nanoTime());
                    else 
                        setAcceptingResponses(true);
                    //tick(nMinutes); 
                    clockTicking = false; 
                    break; 
                case PROBE:
                case PROBE_EX:
                case PROBE_UNEX:
                    if (exp.getDebug())
                        System.out.println("PROBE_{UN,}EX: acceptingResponses = " 
                                           + acceptingResponses); 
                    clock.showFullClock = false; 
                    clock.repaint(); 
                    break; 
                case AFTER_PROBE: 
                    //clock.showFullClock = false; 
                    //clock.repaint(); 
                    //showFixationPoint(); 
                    break; 
                default: 
                    System.out.println("Unexpected probe id: " + probe); 
                    break; 
                }
                // Update probe identifier and onset 

                if (exp.getDebug())
                    System.out.println("Next probe = " + probe);
                nextEventOnset =((Long)(oi.next())).longValue();
            } 
            // sleep for a tatum 
            try { Thread.sleep(tatumInMilliseconds); }
            catch (InterruptedException e) {}
            currentOnset += tatum; 
            clockUnit = (clockUnit + 1) % clockUnits; 
        } while(oi.hasNext());
        showFixationPoint(); 
    }
}