m@0: /*============================================================================= m@0: * File: ExperimentGui.java m@0: * Author: Marcus Pearce m@0: * Created: <2007-02-14 16:42:31 marcusp> marcus@51: * Time-stamp: <2015-02-25 10:07:48 marcusp> m@0: *============================================================================= m@0: */ m@0: m@0: import java.awt.*; m@0: import javax.swing.*; m@0: import java.util.ArrayList; m@0: import java.util.Iterator; m@0: m@0: public class ExperimentGui extends JFrame implements Runnable { c@41: m@0: /* the Experiment */ m@0: private Experiment exp; m@0: m@0: /* The visual display indicating probe positions */ m@0: private Clock clock; m@0: m@0: /* The UI components */ m@0: private JPanel mainPanel; m@0: private InstructionsPanel instructionsPanel; m@0: private StimulusPanel stimulusPanel; m@0: private SubjectDataPanel subjectDataPanel; c@47: private InterBlockPanel interBlockPanel; c@47: private EndTestPanel endTestPanel; m@0: m@0: /* Whether we are accepting responses */ m@0: private Boolean acceptingResponses; m@0: m@0: /* accessors */ m@0: public Boolean getAcceptingResponses() { return acceptingResponses; } m@10: public void setAcceptingResponses(Boolean b) { jeremy@26: if (b) jeremy@26: debug("STARTED accepting responses"); jeremy@26: else jeremy@26: debug("STOPPED accepting responses"); m@10: acceptingResponses = b; jeremy@26: stimulusPanel.setResponseEnabled(b); m@10: } m@0: public Experiment getExperiment() { return exp; } m@0: public InstructionsPanel getInstructionsPanel() { return instructionsPanel; } m@0: public StimulusPanel getStimulusPanel() { return stimulusPanel; } m@0: public SubjectDataPanel getSubjectDataPanel() { return subjectDataPanel; } m@0: public InterBlockPanel getInterBlockPanel() { return interBlockPanel; } c@47: public EndTestPanel getEndTestPanel() { return endTestPanel; } m@0: m@0: /* Constructor */ m@0: public ExperimentGui(Experiment experiment) { m@0: c@41: c@41: m@0: // initialise experiment m@0: exp = experiment; m@0: acceptingResponses = false; m@0: m@0: // set up the clock jeremy@26: clock = new Clock(exp.getDebug()); m@0: m@0: // construct the frame m@0: JFrame.setDefaultLookAndFeelDecorated(true); m@0: this.getContentPane().setBackground (Color.black); m@0: this.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); m@0: this.setLayout (new BorderLayout()); m@0: m@0: // The different cards m@0: instructionsPanel = new InstructionsPanel(this); m@0: stimulusPanel = new StimulusPanel(this, clock); c@47: interBlockPanel = new InterBlockPanel(exp); c@47: endTestPanel = new EndTestPanel(exp); CBussey@39: subjectDataPanel = new SubjectDataPanel(this, exp.getSubjectResults(), !exp.getAskFamiliarity()); jeremy@26: jeremy@26: stimulusPanel.setResponseEnabled(false); m@0: m@0: // The Controller m@0: ExperimentController ec = new ExperimentController(this); m@0: m@0: // Show it all m@0: CardLayout cl = new CardLayout(); m@0: mainPanel = new JPanel(cl); m@0: mainPanel.add(instructionsPanel, "instructions"); c@47: mainPanel.add(interBlockPanel, "interblock"); c@47: mainPanel.add(endTestPanel, "endTest"); m@0: mainPanel.add(stimulusPanel, "stimulus"); m@0: mainPanel.add(subjectDataPanel, "subject"); m@0: c@41: this.add(mainPanel, BorderLayout.CENTER); m@0: } m@0: m@0: /* m@0: * Methods for changing displayed card m@0: */ m@0: m@0: public void showCard(String card) { m@0: CardLayout cl = (CardLayout)(mainPanel.getLayout()); m@0: cl.show(mainPanel, card); m@0: } m@0: m@0: public void nextCard() { m@0: CardLayout cl = (CardLayout)(mainPanel.getLayout()); m@0: cl.next(mainPanel); m@0: } m@0: m@0: /* Advance clock by 1 minute and redisplay. */ m@0: public void tick(int n) { m@0: clock.tick(n); m@0: clock.repaint(); m@0: } m@0: m@0: /* Show the Clock */ m@0: public void showClock() { m@3: if (exp.showClock()) { m@3: clock.showClock = true; m@3: clock.showFullClock = false; m@3: clock.repaint(); m@3: } m@0: } m@0: m@0: /* Show the Fixation Point */ m@0: public void showFixationPoint() { jeremy@26: debug("showFixationPoint"); m@0: clock.showClock = false; m@0: clock.showFullClock = false; m@0: clock.repaint(); m@0: } m@0: m@0: /* Run clock for r revolutions at a rate of 1 minute (6 degrees) m@0: * every n milliseconds. m@0: */ marcus@51: //public void runClock(int r, long n) { marcus@51: // clock.reset(); marcus@51: // showClock(); marcus@51: // for (int i = 0; i < (60 * r); i++) { marcus@51: // try { Thread.sleep (n); } catch (InterruptedException e) {} marcus@51: // clock.tick(1); marcus@51: // clock.repaint(); marcus@51: // } marcus@51: // try { Thread.sleep (1000); } catch (InterruptedException e) {} marcus@51: // showFixationPoint(); marcus@51: //} m@0: JShulver@23: jeremy@26: public void debug(String message) { jeremy@26: if (exp.getDebug()) { jeremy@26: System.out.println(message); jeremy@26: } jeremy@26: } jeremy@26: jeremy@26: public void debugList(String name, ArrayList list) { jeremy@26: if (exp.getDebug()) { jeremy@26: Iterator itr = list.iterator(); jeremy@26: System.out.print("\n" + name + " (" + list.size() + "): "); jeremy@26: while (itr.hasNext()) { jeremy@26: System.out.print(" " + itr.next()); jeremy@26: } jeremy@26: System.out.print("\n"); jeremy@26: } jeremy@26: } jeremy@26: m@0: /* Run method for this thread */ m@0: public void run() { jeremy@26: jeremy@26: boolean debug = exp.getDebug(); jeremy@26: jeremy@26: debug("\nBegin trial"); m@0: //showFixationPoint(); m@0: clock.reset(); m@0: showClock(); m@0: m@0: long tatum = exp.getCurrentBlock().getTatum(); m@0: long tatumInMilliseconds = tatum / 1000; jeremy@26: int nMinutes = 60 / exp.getNumUnits(); m@0: jeremy@26: debug("Tatum: " + tatum); jeremy@26: m@0: ArrayList onsets = exp.getCurrentBlock().getOnsets(); m@0: ArrayList probes = exp.getCurrentBlock().getProbePositions(); m@0: ArrayList clockStartTimes = exp.getCurrentBlock().getClockStartTimes(); jeremy@26: jeremy@26: debugList("Onset times", onsets); jeremy@26: debugList("Probe times", probes); jeremy@26: debugList("Clock start times", clockStartTimes); jeremy@26: m@0: Iterator oi = onsets.iterator(); m@0: Iterator pi = probes.iterator(); m@0: Iterator ci = clockStartTimes.iterator(); m@0: m@0: ProbeID probe = ProbeID.NOT_PROBE; m@0: jeremy@26: long currentTime = 0; m@0: long nextEventOnset = ((Long)(oi.next())).longValue(); m@0: long nextClockStartTime = ((Long)(ci.next())).longValue(); m@0: m@0: int clockUnit = 0; m@0: boolean clockTicking = false; m@0: jeremy@26: do {// Using a do-while construct allows the user to enter a value at the end jeremy@26: // this should not really be in the 'view' anyway... jeremy@26: jeremy@26: debug("\n\nTicking = " + clockTicking + jeremy@26: "; clockUnit = " + clockUnit + jeremy@26: "; currentTime = " + currentTime + jeremy@26: "; nextEventOnset = " + nextEventOnset + jeremy@26: "; nextClockStartTime = " + nextClockStartTime); jeremy@26: jeremy@26: // Tick the clock every cycles jeremy@26: if (clockTicking && clockUnit == 0) { jeremy@26: debug("Tick"); jeremy@26: tick(nMinutes); jeremy@26: } m@0: jeremy@26: // Start the clock jeremy@26: if (currentTime >= nextClockStartTime) { jeremy@26: debug("Start clock (" + (currentTime - nextClockStartTime) + " ago)"); m@0: //new Thread(clock).start(); m@0: clock.reset(); m@0: showClock(); m@0: clockTicking = true; jeremy@26: m@0: if (ci.hasNext()) m@0: nextClockStartTime = ((Long)(ci.next())).longValue(); jeremy@26: else JShulver@23: nextClockStartTime = Long.MAX_VALUE; m@0: } jeremy@26: jeremy@26: // Event onset jeremy@26: if (currentTime >= nextEventOnset) { jeremy@26: jeremy@26: // Update probe identifier and onset jeremy@26: jeremy@26: probe = (ProbeID) pi.next(); jeremy@26: debug("Event " + probe + " " + nextEventOnset + " (" + (currentTime - nextEventOnset) + " ago)"); jeremy@26: nextEventOnset = ((Long)(oi.next())).longValue(); jeremy@26: m@0: // Manipulate display depending on probe identifier m@0: switch (probe) { m@0: case NOT_PROBE: jeremy@26: // if (clock.showClock == true) m@0: // tick(nMinutes); m@0: break; jeremy@26: /* jeremy@26: case START_CLOCK: // No longer used... m@0: //clock.reset(); m@0: //showClock(); m@0: //tick(nMinutes); m@0: break; jeremy@26: */ m@0: case BEFORE_PROBE: jeremy@26: debug("BEFORE_PROBE: acceptingResponses = " + acceptingResponses); jeremy@26: if (acceptingResponses) { m@0: exp.getCurrentBlock().addResponse(0, System.nanoTime()); jeremy@26: debug("Recording zero response"); jeremy@26: } m@0: else m@10: setAcceptingResponses(true); marcus@51: clock.showFullClock = true; marcus@51: clock.repaint(); m@0: break; m@0: case PROBE: m@0: case PROBE_EX: m@0: case PROBE_UNEX: jeremy@26: debug("PROBE_{UN,}EX: acceptingResponses = " + acceptingResponses); marcus@51: clock.showFullClock = true; m@0: clock.repaint(); m@0: break; m@0: case AFTER_PROBE: jeremy@26: showFixationPoint(); marcus@51: clock.showFullClock = false; marcus@51: clockTicking = false; m@0: break; m@0: default: m@0: System.out.println("Unexpected probe id: " + probe); m@0: break; m@0: } jeremy@26: } JShulver@23: jeremy@26: // Sleep for tatum m@0: try { Thread.sleep(tatumInMilliseconds); } m@0: catch (InterruptedException e) {} jeremy@26: currentTime += tatum; jeremy@26: clockUnit = (clockUnit + 1) % exp.getClockUnits(); jeremy@26: JShulver@23: } while(oi.hasNext()); jeremy@26: m@0: showFixationPoint(); m@0: } jeremy@26: jeremy@26: jeremy@26: m@0: }