Warning: Can't use blame annotator:
svn blame failed on trunk/src/scriptbuilder/gui/panels/IncidentTimelinePanel.java: ("Can't find a temporary directory: Internal error", 20014)

source: tmcsimulator-scriptbuilder/trunk/src/scriptbuilder/gui/panels/IncidentTimelinePanel.java @ 101

Revision 101, 16.7 KB checked in by bmcguffin, 9 years ago (diff)

Added text field, txtEventStart, to bottom of event editor screen. This text field by default displays the time that the event starts. Altering this field will change the start time of the selected event to the new value.

RevLine 
1package scriptbuilder.gui.panels;
2
3import event.editor.frame.Editor;
4import event.editor.frame.Properties;
5import java.awt.BorderLayout;
6import java.awt.Dimension;
7import java.awt.Graphics;
8import java.awt.Graphics2D;
9import java.awt.event.ActionEvent;
10import java.awt.event.ActionListener;
11import java.awt.event.MouseEvent;
12import java.io.File;
13import java.util.HashMap;
14import java.util.Map;
15import javax.swing.JFrame;
16import javax.swing.JMenuItem;
17import javax.swing.JOptionPane;
18import javax.swing.JPanel;
19import javax.swing.JPopupMenu;
20import javax.swing.event.MouseInputAdapter;
21import scriptbuilder.gui.IncidentEditorFrame;
22import scriptbuilder.gui.ScriptBuilderFrame;
23import scriptbuilder.gui.ScriptBuilderGuiConstants;
24import scriptbuilder.gui.drawers.CursorDrawer;
25import scriptbuilder.gui.drawers.EventIconDrawer;
26import scriptbuilder.gui.drawers.IncidentTimelineDrawer;
27import scriptbuilder.structures.ScriptEvent;
28import scriptbuilder.structures.ScriptEvent.ScriptEventType;
29import scriptbuilder.structures.ScriptIncident;
30import scriptbuilder.structures.SimulationScript;
31import scriptbuilder.structures.TimeSlice;
32import scriptbuilder.structures.events.I_ScriptEvent;
33
34/**
35 * Represents a single incident timeline in the GUI. Listens for mouse actions.
36 *
37 * @author Greg Eddington <geddingt@calpoly.edu>
38 * @author Bryan McGuffin
39 * @version 2017/06/30
40 */
41public class IncidentTimelinePanel extends JPanel
42{
43
44    /**
45     * The incident this panel represents.
46     */
47    ScriptIncident incident;
48    /**
49     * If true, this panel is in its minimized state.
50     */
51    //boolean collapsed;
52    /**
53     * If false, this panel won't be drawn.
54     */
55    boolean visible;
56    /**
57     * If true, this panel has focus.
58     */
59    boolean focused;
60
61    int cursorTime, lastSlice, x, y;
62
63    /**
64     * Filler time at the end of the screen for a particular incident
65     */
66    public int requestedEditorFillerTime;
67
68    /**
69     * Filler time at the end of the screen for the whole script
70     */
71    public static int requestedScriptBuilderFillerTime = 0;
72
73    /**
74     * Constant for amount of filler to add, in seconds. Set to 15 minutes
75     */
76    public static final int FILLER_INTERVAL_SECONDS = 900;
77
78    /**
79     * The map representing the properties of this incident's events. Keys:
80     * event types. Values: Properties objects for those events.
81     */
82    public static Map<ScriptEventType, Properties> eventTypeToPropertyMap;
83
84    /**
85     * Listener for the mouse. Receives notifications when the mouse enters,
86     * exits, moves through, or clicks inside the panel.
87     */
88    public class IncidentTimelineMouseListener extends MouseInputAdapter
89    {
90
91        /**
92         * Action to take when the mouse enters the panel. Here, the incident
93         * corresponding to this panel gains focus.
94         *
95         * @param e the mouse event
96         */
97        @Override
98        public void mouseEntered(MouseEvent e)
99        {
100            incident.setIncidentActive();
101            focused = true;
102        }
103
104        /**
105         * Action to take when the mouse leaves the panel. Here, the incident
106         * loses focus and the panel gets repainted.
107         *
108         * @param e the mouse event
109         */
110        @Override
111        public void mouseExited(MouseEvent e)
112        {
113            focused = false;
114            repaint();
115        }
116
117        /*
118         *   Popup menu for incident actions
119         */
120        private JPopupMenu createPopup()
121        {
122            JPopupMenu menu = new JPopupMenu();
123            JMenuItem eventsMenuItem = new JMenuItem("Events");
124            JMenuItem propsMenuItem = new JMenuItem("Properties");
125            eventsMenuItem.setActionCommand("Edit Events");
126            propsMenuItem.setActionCommand("Modify Incident Properties");
127
128            PopupMenuItemListener menuItemListener = new PopupMenuItemListener();
129
130            eventsMenuItem.addActionListener(menuItemListener);
131            propsMenuItem.addActionListener(menuItemListener);
132
133            menu.add(eventsMenuItem);
134            menu.add(propsMenuItem);
135            return menu;
136        }
137
138        class PopupMenuItemListener implements ActionListener
139        {
140
141            public void actionPerformed(ActionEvent e)
142            {
143                JFrame topFrame = (JFrame) getTopLevelAncestor();
144                if (topFrame instanceof ScriptBuilderFrame)
145                {
146                    SimulationScript script = ((ScriptBuilderFrame) topFrame).getScript();
147                    if (e.getActionCommand().equals("Edit Events"))
148                    {
149                        IncidentEditorFrame editor = new IncidentEditorFrame(incident);
150                        script.addObserver(editor);
151                        editor.setVisible(true);
152                        ((ScriptBuilderFrame) topFrame).update(script, script);
153                    }
154                    if (e.getActionCommand().equals("Modify Incident Properties"))
155                    {
156                        ((ScriptBuilderFrame) topFrame).incidentDetailsScreen(incident);
157                        ((ScriptBuilderFrame) topFrame).update(script, script);
158                    }
159                }
160                topFrame.repaint();
161            }
162        }
163
164        @Override
165        public void mousePressed(MouseEvent e)
166        {
167            int currentMouseX = e.getX();
168            int currentMouseY = e.getY();
169
170            // Does user want a popup menu?
171            if (e.isPopupTrigger())
172            {
173                JPopupMenu popup = createPopup();
174                popup.show(e.getComponent(), currentMouseX, currentMouseY);
175            }
176        }
177
178        /**
179         * Determine if the mouse click happened within a valid timeSlice on
180         * this incident; if so, activate the Editor window for that timeSlice.
181         *
182         * @param e the mouse event
183         */
184        @Override
185        public void mouseClicked(MouseEvent e)
186        {
187            Editor ed = null;
188            ScriptBuilderFrame f = null;
189            IncidentEditorFrame g = null;
190            if (getTopLevelAncestor() instanceof ScriptBuilderFrame)
191            {
192                f = (ScriptBuilderFrame) getTopLevelAncestor();
193
194            }
195            else if (getTopLevelAncestor() instanceof IncidentEditorFrame)
196            {
197                g = (IncidentEditorFrame) getTopLevelAncestor();
198                ed = new Editor(g);
199            }
200
201            x = cursorTime = e.getX();
202            y = e.getY();
203
204            if (e.getX() % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK
205                    > ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK / 2)
206            {
207                cursorTime += ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK
208                        - e.getX()
209                        % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK;
210            }
211            else
212            {
213                cursorTime -= e.getX()
214                        % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK;
215            }
216
217            int newSlice = (cursorTime / ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK);
218            newSlice *= ScriptBuilderGuiConstants.HORIZONTAL_TICK_RESOLUTION;
219            /**
220             * Check if click is out of bounds *
221             */
222            if (newSlice < 0 || incident == null)
223            {
224                return;
225            }
226
227            if (ed != null)
228            {
229                ed.setSlice(incident.slices.get(newSlice));
230            }
231           
232
233            /**
234             * Add a new icon if left mouse button was clicked *
235             */
236            if (e.getButton() == MouseEvent.BUTTON1)
237            {
238
239                if (getTopLevelAncestor() instanceof IncidentEditorFrame)
240                {
241                    if (g.currentEventType != null)
242                    {
243                        I_ScriptEvent s = ScriptEvent.factoryByType(g.currentEventType);
244                        if (ed != null)
245                        {
246                            ed.addEvent(eventTypeToPropertyMap.get(g.currentEventType), s);
247                        }
248                        if (incident.slices.get(newSlice) == null)
249                        {
250                            incident.addNewEvent(s, newSlice);
251                        }
252                        else
253                        {
254                            incident.slices.get(newSlice).addEvent(s);
255                        }
256                        g.update(null, g.getIncident());
257                    }
258                }
259            }
260
261            if (incident.slices.get(newSlice) != null
262                    && getTopLevelAncestor() instanceof IncidentEditorFrame)
263            {
264                ed.setVisible(true);
265            }
266        }
267
268        /**
269         * Determine if the mouse is now hovering over a valid timeslice; if so,
270         * alter tooltip text and info window text to reflect the new timeslice.
271         *
272         * @param e the mouse event
273         */
274        @Override
275        public void mouseMoved(MouseEvent e)
276        {
277            x = cursorTime = e.getX();
278            y = e.getY();
279
280            if (e.getX() % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK
281                    > ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK / 2)
282            {
283                cursorTime += ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK
284                        - e.getX()
285                        % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK;
286            }
287            else
288            {
289                cursorTime -= e.getX()
290                        % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK;
291            }
292
293            if (incident != null)
294            {
295                int newSlice = (cursorTime / ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK);
296                newSlice *= ScriptBuilderGuiConstants.HORIZONTAL_TICK_RESOLUTION;
297                if (newSlice >= 0 && incident.slices.get(newSlice) != null)
298                {
299                    incident.setSliceActive(newSlice);
300                    lastSlice = newSlice;
301                    String newToolTip;
302
303                    newToolTip = incident.slices.get(newSlice).getToolTipText(y);
304
305                    setToolTipText((newToolTip == null || newToolTip.equals(""))
306                            ? null : newToolTip);
307                }
308            }
309
310            repaint();
311        }
312    }
313
314    /**
315     * Constructor. Generates a HashMap of all possible event types.
316     */
317    public IncidentTimelinePanel()
318    {
319        super();
320
321        requestedEditorFillerTime = 0;
322//        FACILITATOR_EVAL_EVENT, RADIO_EVAL_EVENT
323        eventTypeToPropertyMap = new HashMap();
324        eventTypeToPropertyMap.put(ScriptEventType.AUDIO_EVENT, Properties.Audio);
325        eventTypeToPropertyMap.put(ScriptEventType.CAD_EVENT, Properties.CADLog);
326        eventTypeToPropertyMap.put(ScriptEventType.CCTV_EVENT, Properties.CCTV);
327        eventTypeToPropertyMap.put(ScriptEventType.CHP_RADIO_EVENT, Properties.CHPRadio);
328        eventTypeToPropertyMap.put(ScriptEventType.PARAMICS_EVENT, Properties.Paramics);
329        eventTypeToPropertyMap.put(ScriptEventType.TOW_EVENT, Properties.Tow);
330        eventTypeToPropertyMap.put(ScriptEventType.UNIT_EVENT, Properties.Unit);
331        eventTypeToPropertyMap.put(ScriptEventType.WITNESS_EVENT, Properties.Witness);
332        eventTypeToPropertyMap.put(ScriptEventType.MAINTENANCE_RADIO_EVENT, Properties.MaintenanceRadio);
333        eventTypeToPropertyMap.put(ScriptEventType.TMT_RADIO_EVENT, Properties.TMTRadio);
334        eventTypeToPropertyMap.put(ScriptEventType.TELEPHONE_EVENT, Properties.Telephone);
335        eventTypeToPropertyMap.put(ScriptEventType.ATMS_EVAL_EVENT, Properties.ATMS);
336        eventTypeToPropertyMap.put(ScriptEventType.ACTIVITY_LOG_EVAL_EVENT, Properties.ActivityLog);
337        eventTypeToPropertyMap.put(ScriptEventType.CAD_EVAL_EVENT, Properties.CAD);
338        eventTypeToPropertyMap.put(ScriptEventType.CMS_EVAL_EVENT, Properties.CMS);
339        eventTypeToPropertyMap.put(ScriptEventType.FACILITATOR_EVAL_EVENT, Properties.Facilitator);
340        eventTypeToPropertyMap.put(ScriptEventType.RADIO_EVAL_EVENT, Properties.Radio);
341
342        // Add the mouse listener
343        IncidentTimelineMouseListener mouseListener
344                = new IncidentTimelineMouseListener();
345        addMouseMotionListener(mouseListener);
346        addMouseListener(mouseListener);
347    }
348
349    /**
350     * Update the panel if it's changed collapsed status. Redraw it with the
351     * correct dimensions for its status.
352     *
353     * @param incident the incident this panel represents
354     */
355    public void timelinePanelUpdate(ScriptIncident incident)
356    {
357        this.incident = incident;
358        this.visible = incident != null;
359
360        Dimension newSize;
361        if (visible)
362        {
363
364            if (getTopLevelAncestor() instanceof IncidentEditorFrame)
365            {
366
367                newSize = new Dimension(((incident.length + incident.offset + requestedEditorFillerTime)
368                        / ScriptBuilderGuiConstants.HORIZONTAL_TICK_RESOLUTION
369                        * ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK)
370                        + ScriptBuilderGuiConstants.EVENT_ICON_WIDTH,
371                        ScriptBuilderGuiConstants.TIMELINE_COLLAPSED_HEIGHT
372                        + ScriptBuilderGuiConstants.SCRIPT_EVENT_ICON_STEP * 2);
373            }
374            else
375            {
376                newSize = new Dimension(((incident.length + incident.offset + requestedScriptBuilderFillerTime)
377                        / ScriptBuilderGuiConstants.HORIZONTAL_TICK_RESOLUTION
378                        * ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK)
379                        + ScriptBuilderGuiConstants.EVENT_ICON_WIDTH,
380                        ScriptBuilderGuiConstants.TIMELINE_COLLAPSED_HEIGHT
381                        + ScriptBuilderGuiConstants.SCRIPT_EVENT_ICON_STEP * 2);
382            }
383
384        }
385        else
386        {
387            newSize = new Dimension(0, 0);
388        }
389        this.setSize(newSize);
390        this.setPreferredSize(newSize);
391
392        invalidate();
393    }
394
395    /**
396     * Redraw this panel and all the icons inside it. If user is holding an
397     * event, draw that icon under the mouse.
398     *
399     * @param g the graphics component
400     */
401    @Override
402    public void paint(Graphics g)
403    {
404        super.paint(g);
405
406        if (!visible)
407        {
408            return;
409        }
410
411        Graphics2D g2d = (Graphics2D) g;
412//        jdalbey removed this decision and replaced it with ELSE clause
413//                so it will work with any alternate ancestor.
414//        if (getTopLevelAncestor() instanceof ScriptBuilderFrame)
415//        {
416//            IncidentTimelineDrawer.DrawScriptBuilderTimeline(g2d, incident);
417//        }
418        if (getTopLevelAncestor() instanceof IncidentEditorFrame)
419        {
420            IncidentTimelineDrawer.DrawIncidentTimeline(g2d, incident, false);
421        }
422        else
423        {
424            IncidentTimelineDrawer.DrawScriptBuilderTimeline(g2d, incident);
425        }
426
427        if (focused)
428        {
429            CursorDrawer.DrawCursor(g2d, cursorTime, false);
430            if (this.getTopLevelAncestor() instanceof ScriptBuilderFrame)
431            {
432                if (((ScriptBuilderFrame) this.getTopLevelAncestor()).currentEventType != null)
433                {
434                    EventIconDrawer.DrawEventIcon(g2d,
435                            ((ScriptBuilderFrame) this.getTopLevelAncestor()).currentEventType,
436                            x + 5, y + 10);
437                }
438            }
439            if (this.getTopLevelAncestor() instanceof IncidentEditorFrame)
440            {
441                if (((IncidentEditorFrame) this.getTopLevelAncestor()).currentEventType != null)
442                {
443                    EventIconDrawer.DrawEventIcon(g2d,
444                            ((IncidentEditorFrame) this.getTopLevelAncestor()).currentEventType,
445                            x + 5, y + 10);
446                }
447            }
448        }
449    }
450
451    /**
452     * Local main for viewing this panel only.
453     *
454     * @author jdalbey
455     * @param args not used
456     */
457    public static void main(String[] args)
458    {
459        JFrame frame = new JFrame("ScriptBuilderTimelinePanel Demo");
460        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
461
462        IncidentTimelinePanel pnl = new IncidentTimelinePanel();
463
464        // Create a script
465        File inFile = new File("test/scriptbuilder/structures/test_input_file.xml");
466        SimulationScript script = new SimulationScript();
467        script.loadScriptFromFile(inFile);
468        // retrieve a single incident from the script
469        ScriptIncident inci = script.incidents.get(2);
470        // update this panel with an incident
471        pnl.timelinePanelUpdate(inci);
472
473        frame.getContentPane().add(pnl, BorderLayout.CENTER);
474        frame.pack();
475
476        frame.setVisible(true);
477
478    }
479}
Note: See TracBrowser for help on using the repository browser.