m@0
|
1 /*=============================================================================
|
m@0
|
2 * File: ExperimentGui.java
|
m@0
|
3 * Author: Marcus Pearce <m.pearce@gold.ac.uk>
|
m@0
|
4 * Created: <2007-02-14 16:42:31 marcusp>
|
m@10
|
5 * Time-stamp: <2011-11-04 17:41:45 marcusp>
|
m@0
|
6 *=============================================================================
|
m@0
|
7 */
|
m@0
|
8
|
m@0
|
9 import java.awt.*;
|
m@0
|
10 import javax.swing.*;
|
m@0
|
11 import java.util.ArrayList;
|
m@0
|
12 import java.util.Iterator;
|
m@0
|
13
|
m@0
|
14 public class ExperimentGui extends JFrame implements Runnable {
|
m@0
|
15
|
m@0
|
16 /* the Experiment */
|
m@0
|
17 private Experiment exp;
|
m@0
|
18
|
m@0
|
19 /* The visual display indicating probe positions */
|
m@0
|
20 private Clock clock;
|
m@0
|
21
|
m@0
|
22 /* The UI components */
|
m@0
|
23 private JPanel mainPanel;
|
m@0
|
24 private InstructionsPanel instructionsPanel;
|
m@0
|
25 private StimulusPanel stimulusPanel;
|
m@0
|
26 private SubjectDataPanel subjectDataPanel;
|
m@0
|
27 private InterBlockPanel interBlockPanel;
|
m@0
|
28
|
m@0
|
29 /* Whether we are accepting responses */
|
m@0
|
30 private Boolean acceptingResponses;
|
m@0
|
31
|
m@0
|
32 /* accessors */
|
m@0
|
33 public Boolean getAcceptingResponses() { return acceptingResponses; }
|
m@10
|
34 public void setAcceptingResponses(Boolean b) {
|
jeremy@26
|
35 if (b)
|
jeremy@26
|
36 debug("STARTED accepting responses");
|
jeremy@26
|
37 else
|
jeremy@26
|
38 debug("STOPPED accepting responses");
|
m@10
|
39 acceptingResponses = b;
|
jeremy@26
|
40 stimulusPanel.setResponseEnabled(b);
|
m@10
|
41 }
|
m@0
|
42 public Experiment getExperiment() { return exp; }
|
m@0
|
43 public InstructionsPanel getInstructionsPanel() { return instructionsPanel; }
|
m@0
|
44 public StimulusPanel getStimulusPanel() { return stimulusPanel; }
|
m@0
|
45 public SubjectDataPanel getSubjectDataPanel() { return subjectDataPanel; }
|
m@0
|
46 public InterBlockPanel getInterBlockPanel() { return interBlockPanel; }
|
m@0
|
47
|
m@0
|
48 /* Constructor */
|
m@0
|
49 public ExperimentGui(Experiment experiment) {
|
m@0
|
50
|
m@0
|
51 // initialise experiment
|
m@0
|
52 exp = experiment;
|
m@0
|
53 acceptingResponses = false;
|
m@0
|
54
|
m@0
|
55 // set up the clock
|
jeremy@26
|
56 clock = new Clock(exp.getDebug());
|
m@0
|
57
|
m@0
|
58 // construct the frame
|
m@0
|
59 JFrame.setDefaultLookAndFeelDecorated(true);
|
m@0
|
60 this.getContentPane().setBackground (Color.black);
|
m@0
|
61 this.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
|
m@0
|
62 this.setLayout (new BorderLayout());
|
m@0
|
63
|
m@0
|
64 // The different cards
|
m@0
|
65 instructionsPanel = new InstructionsPanel(this);
|
m@0
|
66 stimulusPanel = new StimulusPanel(this, clock);
|
m@0
|
67 interBlockPanel = new InterBlockPanel(exp);
|
m@0
|
68 subjectDataPanel = new SubjectDataPanel(this, exp.getSubjectResults());
|
jeremy@26
|
69
|
jeremy@26
|
70 stimulusPanel.setResponseEnabled(false);
|
m@0
|
71
|
m@0
|
72 // The Controller
|
m@0
|
73 ExperimentController ec = new ExperimentController(this);
|
m@0
|
74
|
m@0
|
75 // Show it all
|
m@0
|
76 CardLayout cl = new CardLayout();
|
m@0
|
77 mainPanel = new JPanel(cl);
|
m@0
|
78 mainPanel.add(instructionsPanel, "instructions");
|
m@0
|
79 mainPanel.add(interBlockPanel, "interblock");
|
m@0
|
80 mainPanel.add(stimulusPanel, "stimulus");
|
m@0
|
81 mainPanel.add(subjectDataPanel, "subject");
|
m@0
|
82
|
m@0
|
83 this.add(mainPanel, BorderLayout.CENTER);
|
m@0
|
84 }
|
m@0
|
85
|
m@0
|
86 /*
|
m@0
|
87 * Methods for changing displayed card
|
m@0
|
88 */
|
m@0
|
89
|
m@0
|
90 public void showCard(String card) {
|
m@0
|
91 CardLayout cl = (CardLayout)(mainPanel.getLayout());
|
m@0
|
92 cl.show(mainPanel, card);
|
m@0
|
93 }
|
m@0
|
94
|
m@0
|
95 public void nextCard() {
|
m@0
|
96 CardLayout cl = (CardLayout)(mainPanel.getLayout());
|
m@0
|
97 cl.next(mainPanel);
|
m@0
|
98 }
|
m@0
|
99
|
m@0
|
100 /* Advance clock by 1 minute and redisplay. */
|
m@0
|
101 public void tick(int n) {
|
m@0
|
102 clock.tick(n);
|
m@0
|
103 clock.repaint();
|
m@0
|
104 }
|
m@0
|
105
|
m@0
|
106 /* Show the Clock */
|
m@0
|
107 public void showClock() {
|
m@3
|
108 if (exp.showClock()) {
|
m@3
|
109 clock.showClock = true;
|
m@3
|
110 clock.showFullClock = false;
|
m@3
|
111 clock.repaint();
|
m@3
|
112 }
|
m@0
|
113 }
|
m@0
|
114
|
m@0
|
115 /* Show the Fixation Point */
|
m@0
|
116 public void showFixationPoint() {
|
jeremy@26
|
117 debug("showFixationPoint");
|
m@0
|
118 clock.showClock = false;
|
m@0
|
119 clock.showFullClock = false;
|
m@0
|
120 clock.repaint();
|
m@0
|
121 }
|
m@0
|
122
|
m@0
|
123 /* Run clock for r revolutions at a rate of 1 minute (6 degrees)
|
m@0
|
124 * every n milliseconds.
|
m@0
|
125 */
|
m@0
|
126 public void runClock(int r, long n) {
|
m@0
|
127 clock.reset();
|
m@0
|
128 showClock();
|
m@0
|
129 for (int i = 0; i < (60 * r); i++) {
|
m@0
|
130 try { Thread.sleep (n); } catch (InterruptedException e) {}
|
m@0
|
131 clock.tick(1);
|
m@0
|
132 clock.repaint();
|
m@0
|
133 }
|
m@0
|
134 try { Thread.sleep (1000); } catch (InterruptedException e) {}
|
m@0
|
135 showFixationPoint();
|
m@0
|
136 }
|
m@0
|
137
|
JShulver@23
|
138
|
jeremy@26
|
139 public void debug(String message) {
|
jeremy@26
|
140 if (exp.getDebug()) {
|
jeremy@26
|
141 System.out.println(message);
|
jeremy@26
|
142 }
|
jeremy@26
|
143 }
|
jeremy@26
|
144
|
jeremy@26
|
145 public void debugList(String name, ArrayList list) {
|
jeremy@26
|
146 if (exp.getDebug()) {
|
jeremy@26
|
147 Iterator itr = list.iterator();
|
jeremy@26
|
148 System.out.print("\n" + name + " (" + list.size() + "): ");
|
jeremy@26
|
149 while (itr.hasNext()) {
|
jeremy@26
|
150 System.out.print(" " + itr.next());
|
jeremy@26
|
151 }
|
jeremy@26
|
152 System.out.print("\n");
|
jeremy@26
|
153 }
|
jeremy@26
|
154 }
|
jeremy@26
|
155
|
m@0
|
156 /* Run method for this thread */
|
m@0
|
157 public void run() {
|
jeremy@26
|
158
|
jeremy@26
|
159 boolean debug = exp.getDebug();
|
jeremy@26
|
160
|
jeremy@26
|
161 debug("\nBegin trial");
|
m@0
|
162 //showFixationPoint();
|
m@0
|
163 clock.reset();
|
m@0
|
164 showClock();
|
m@0
|
165
|
m@0
|
166 long tatum = exp.getCurrentBlock().getTatum();
|
m@0
|
167 long tatumInMilliseconds = tatum / 1000;
|
jeremy@26
|
168 int nMinutes = 60 / exp.getNumUnits();
|
m@0
|
169
|
jeremy@26
|
170 debug("Tatum: " + tatum);
|
jeremy@26
|
171
|
m@0
|
172 ArrayList onsets = exp.getCurrentBlock().getOnsets();
|
m@0
|
173 ArrayList probes = exp.getCurrentBlock().getProbePositions();
|
m@0
|
174 ArrayList clockStartTimes = exp.getCurrentBlock().getClockStartTimes();
|
jeremy@26
|
175
|
jeremy@26
|
176 debugList("Onset times", onsets);
|
jeremy@26
|
177 debugList("Probe times", probes);
|
jeremy@26
|
178 debugList("Clock start times", clockStartTimes);
|
jeremy@26
|
179
|
m@0
|
180 Iterator oi = onsets.iterator();
|
m@0
|
181 Iterator pi = probes.iterator();
|
m@0
|
182 Iterator ci = clockStartTimes.iterator();
|
m@0
|
183
|
m@0
|
184 ProbeID probe = ProbeID.NOT_PROBE;
|
m@0
|
185
|
jeremy@26
|
186 long currentTime = 0;
|
m@0
|
187 long nextEventOnset = ((Long)(oi.next())).longValue();
|
m@0
|
188 long nextClockStartTime = ((Long)(ci.next())).longValue();
|
m@0
|
189
|
m@0
|
190 int clockUnit = 0;
|
m@0
|
191 boolean clockTicking = false;
|
m@0
|
192
|
jeremy@26
|
193 do {// Using a do-while construct allows the user to enter a value at the end
|
jeremy@26
|
194 // this should not really be in the 'view' anyway...
|
jeremy@26
|
195
|
jeremy@26
|
196 debug("\n\nTicking = " + clockTicking +
|
jeremy@26
|
197 "; clockUnit = " + clockUnit +
|
jeremy@26
|
198 "; currentTime = " + currentTime +
|
jeremy@26
|
199 "; nextEventOnset = " + nextEventOnset +
|
jeremy@26
|
200 "; nextClockStartTime = " + nextClockStartTime);
|
jeremy@26
|
201
|
jeremy@26
|
202 // Tick the clock every <clockUnit> cycles
|
jeremy@26
|
203 if (clockTicking && clockUnit == 0) {
|
jeremy@26
|
204 debug("Tick");
|
jeremy@26
|
205 tick(nMinutes);
|
jeremy@26
|
206 }
|
m@0
|
207
|
jeremy@26
|
208 // Start the clock
|
jeremy@26
|
209 if (currentTime >= nextClockStartTime) {
|
jeremy@26
|
210 debug("Start clock (" + (currentTime - nextClockStartTime) + " ago)");
|
m@0
|
211 //new Thread(clock).start();
|
m@0
|
212 clock.reset();
|
m@0
|
213 showClock();
|
m@0
|
214 clockTicking = true;
|
jeremy@26
|
215
|
m@0
|
216 if (ci.hasNext())
|
m@0
|
217 nextClockStartTime = ((Long)(ci.next())).longValue();
|
jeremy@26
|
218 else
|
JShulver@23
|
219 nextClockStartTime = Long.MAX_VALUE;
|
m@0
|
220 }
|
jeremy@26
|
221
|
jeremy@26
|
222 // Event onset
|
jeremy@26
|
223 if (currentTime >= nextEventOnset) {
|
jeremy@26
|
224
|
jeremy@26
|
225 // Update probe identifier and onset
|
jeremy@26
|
226
|
jeremy@26
|
227 probe = (ProbeID) pi.next();
|
jeremy@26
|
228 debug("Event " + probe + " " + nextEventOnset + " (" + (currentTime - nextEventOnset) + " ago)");
|
jeremy@26
|
229 nextEventOnset = ((Long)(oi.next())).longValue();
|
jeremy@26
|
230
|
m@0
|
231 // Manipulate display depending on probe identifier
|
m@0
|
232 switch (probe) {
|
m@0
|
233 case NOT_PROBE:
|
jeremy@26
|
234 // if (clock.showClock == true)
|
m@0
|
235 // tick(nMinutes);
|
m@0
|
236 break;
|
jeremy@26
|
237 /*
|
jeremy@26
|
238 case START_CLOCK: // No longer used...
|
m@0
|
239 //clock.reset();
|
m@0
|
240 //showClock();
|
m@0
|
241 //tick(nMinutes);
|
m@0
|
242 break;
|
jeremy@26
|
243 */
|
m@0
|
244 case BEFORE_PROBE:
|
jeremy@26
|
245 debug("BEFORE_PROBE: acceptingResponses = " + acceptingResponses);
|
jeremy@26
|
246 if (acceptingResponses) {
|
m@0
|
247 exp.getCurrentBlock().addResponse(0, System.nanoTime());
|
jeremy@26
|
248 debug("Recording zero response");
|
jeremy@26
|
249 }
|
m@0
|
250 else
|
m@10
|
251 setAcceptingResponses(true);
|
m@0
|
252 //tick(nMinutes);
|
m@0
|
253 clockTicking = false;
|
m@0
|
254 break;
|
m@0
|
255 case PROBE:
|
m@0
|
256 case PROBE_EX:
|
m@0
|
257 case PROBE_UNEX:
|
jeremy@26
|
258 debug("PROBE_{UN,}EX: acceptingResponses = " + acceptingResponses);
|
m@0
|
259 clock.showFullClock = false;
|
m@0
|
260 clock.repaint();
|
m@0
|
261 break;
|
m@0
|
262 case AFTER_PROBE:
|
jeremy@26
|
263 showFixationPoint();
|
m@0
|
264 break;
|
m@0
|
265 default:
|
m@0
|
266 System.out.println("Unexpected probe id: " + probe);
|
m@0
|
267 break;
|
m@0
|
268 }
|
jeremy@26
|
269 }
|
JShulver@23
|
270
|
jeremy@26
|
271 // Sleep for tatum
|
m@0
|
272 try { Thread.sleep(tatumInMilliseconds); }
|
m@0
|
273 catch (InterruptedException e) {}
|
jeremy@26
|
274 currentTime += tatum;
|
jeremy@26
|
275 clockUnit = (clockUnit + 1) % exp.getClockUnits();
|
jeremy@26
|
276
|
JShulver@23
|
277 } while(oi.hasNext());
|
jeremy@26
|
278
|
m@0
|
279 showFixationPoint();
|
m@0
|
280 }
|
jeremy@26
|
281
|
jeremy@26
|
282
|
jeremy@26
|
283
|
m@0
|
284 }
|