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