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 @ 93

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

Moved classes which represent elements of the main event editor frame to their own package, for clarity' sake.

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     * The map representing the properties of this incident's events. Keys:
65     * event types. Values: Properties objects for those events.
66     */
67    Map<ScriptEventType, Properties> eventTypeToPropertyMap;
68
69    /**
70     * Listener for the mouse. Receives notifications when the mouse enters,
71     * exits, moves through, or clicks inside the panel.
72     */
73    public class IncidentTimelineMouseListener extends MouseInputAdapter
74    {
75
76        /**
77         * Action to take when the mouse enters the panel. Here, the incident
78         * corresponding to this panel gains focus.
79         *
80         * @param e the mouse event
81         */
82        @Override
83        public void mouseEntered(MouseEvent e)
84        {
85            incident.setIncidentActive();
86            focused = true;
87        }
88
89        /**
90         * Action to take when the mouse leaves the panel. Here, the incident
91         * loses focus and the panel gets repainted.
92         *
93         * @param e the mouse event
94         */
95        @Override
96        public void mouseExited(MouseEvent e)
97        {
98            focused = false;
99            repaint();
100        }
101
102        /*
103         *   Popup menu for incident actions
104         */
105        private JPopupMenu createPopup()
106        {
107            JPopupMenu menu = new JPopupMenu();
108            JMenuItem eventsMenuItem = new JMenuItem("Events");
109            JMenuItem propsMenuItem = new JMenuItem("Properties");
110            JMenuItem deleteMenuItem = new JMenuItem("Delete");
111            eventsMenuItem.setActionCommand("Edit Events");
112            propsMenuItem.setActionCommand("Modify Incident Properties");
113            deleteMenuItem.setActionCommand("Delete Incident");
114
115            PopupMenuItemListener menuItemListener = new PopupMenuItemListener();
116
117            eventsMenuItem.addActionListener(menuItemListener);
118            propsMenuItem.addActionListener(menuItemListener);
119            deleteMenuItem.addActionListener(menuItemListener);
120
121            menu.add(eventsMenuItem);
122            menu.add(propsMenuItem);
123            menu.add(deleteMenuItem);
124            return menu;
125        }
126
127        class PopupMenuItemListener implements ActionListener
128        {
129
130            public void actionPerformed(ActionEvent e)
131            {
132                JFrame topFrame = (JFrame) getTopLevelAncestor();
133                if (topFrame instanceof ScriptBuilderFrame)
134                {
135                    SimulationScript script = ((ScriptBuilderFrame) topFrame).getScript();
136                    if (e.getActionCommand().equals("Edit Events"))
137                    {
138                        IncidentEditorFrame editor = new IncidentEditorFrame(incident);
139                        script.addObserver(editor);
140                        editor.setVisible(true);
141                        ((ScriptBuilderFrame) topFrame).update(script, script);
142                    }
143                    if (e.getActionCommand().equals("Modify Incident Properties"))
144                    {
145                        ((ScriptBuilderFrame) topFrame).incidentDetailsScreen(incident);
146                        ((ScriptBuilderFrame) topFrame).update(script, script);
147                    }
148                    if (e.getActionCommand().equals("Delete Incident"))
149                    {
150                        int confirm = JOptionPane.showConfirmDialog(((ScriptBuilderFrame) topFrame),
151                                "Are you sure you want to delete " + incident.toString() + "?");
152                        if (confirm == JOptionPane.YES_OPTION)
153                        {
154                            script.incidents.remove(incident);
155                            script.incidents.add(null);
156                            ((ScriptBuilderFrame) topFrame).update(script, script);
157                        }
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 (incident.slices.get(newSlice) != null)
228
229            {
230                for (I_ScriptEvent se : incident.slices.get(newSlice).events)
231                {
232                    if (ed != null)
233                    {
234                        ed.addProperty(eventTypeToPropertyMap.get(se.getScriptEventType()), se);
235                    }
236                }
237            }
238
239            /**
240             * Add a new icon if left mouse button was clicked *
241             */
242            if (e.getButton() == MouseEvent.BUTTON1)
243            {
244
245                if (getTopLevelAncestor() instanceof IncidentEditorFrame)
246                {
247                    if (g.currentEventType != null)
248                    {
249                        I_ScriptEvent s = ScriptEvent.factoryByType(g.currentEventType);
250                        if (ed != null)
251                        {
252                            ed.addProperty(eventTypeToPropertyMap.get(g.currentEventType), s);
253                        }
254                        if (incident.slices.get(newSlice) == null)
255                        {
256                            incident.addNewEvent(s, newSlice);
257                        }
258                        else
259                        {
260                            incident.slices.get(newSlice).addEvent(s);
261                        }
262                        g.update(null, g.getIncident());
263                    }
264                }
265            }
266
267            if (incident.slices.get(newSlice) != null
268                    && getTopLevelAncestor() instanceof IncidentEditorFrame)
269            {
270                ed.setVisible(true);
271            }
272        }
273
274        /**
275         * Determine if the mouse is now hovering over a valid timeslice; if so,
276         * alter tooltip text and info window text to reflect the new timeslice.
277         *
278         * @param e the mouse event
279         */
280        @Override
281        public void mouseMoved(MouseEvent e)
282        {
283            x = cursorTime = e.getX();
284            y = e.getY();
285
286            if (e.getX() % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK
287                    > ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK / 2)
288            {
289                cursorTime += ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK
290                        - e.getX()
291                        % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK;
292            }
293            else
294            {
295                cursorTime -= e.getX()
296                        % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK;
297            }
298
299            if (incident != null)
300            {
301                int newSlice = (cursorTime / ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK);
302                newSlice *= ScriptBuilderGuiConstants.HORIZONTAL_TICK_RESOLUTION;
303                if (newSlice >= 0 && incident.slices.get(newSlice) != null)
304                {
305                    incident.setSliceActive(newSlice);
306                    lastSlice = newSlice;
307                    String newToolTip;
308
309                    newToolTip = incident.slices.get(newSlice).getToolTipText(y);
310
311                    setToolTipText((newToolTip == null || newToolTip.equals(""))
312                            ? null : newToolTip);
313                }
314            }
315
316            repaint();
317        }
318    }
319
320    /**
321     * Constructor. Generates a HashMap of all possible event types.
322     */
323    public IncidentTimelinePanel()
324    {
325        super();
326
327//        FACILITATOR_EVAL_EVENT, RADIO_EVAL_EVENT
328        eventTypeToPropertyMap = new HashMap();
329        eventTypeToPropertyMap.put(ScriptEventType.AUDIO_EVENT, Properties.Audio);
330        eventTypeToPropertyMap.put(ScriptEventType.CAD_EVENT, Properties.CADLog);
331        eventTypeToPropertyMap.put(ScriptEventType.CCTV_EVENT, Properties.CCTV);
332        eventTypeToPropertyMap.put(ScriptEventType.CHP_RADIO_EVENT, Properties.CHPRadio);
333        eventTypeToPropertyMap.put(ScriptEventType.PARAMICS_EVENT, Properties.Paramics);
334        eventTypeToPropertyMap.put(ScriptEventType.TOW_EVENT, Properties.Tow);
335        eventTypeToPropertyMap.put(ScriptEventType.UNIT_EVENT, Properties.Unit);
336        eventTypeToPropertyMap.put(ScriptEventType.WITNESS_EVENT, Properties.Witness);
337        eventTypeToPropertyMap.put(ScriptEventType.MAINTENANCE_RADIO_EVENT, Properties.MaintenanceRadio);
338        eventTypeToPropertyMap.put(ScriptEventType.TMT_RADIO_EVENT, Properties.TMTRadio);
339        eventTypeToPropertyMap.put(ScriptEventType.TELEPHONE_EVENT, Properties.Telephone);
340        eventTypeToPropertyMap.put(ScriptEventType.ATMS_EVAL_EVENT, Properties.ATMS);
341        eventTypeToPropertyMap.put(ScriptEventType.ACTIVITY_LOG_EVAL_EVENT, Properties.ActivityLog);
342        eventTypeToPropertyMap.put(ScriptEventType.CAD_EVAL_EVENT, Properties.CAD);
343        eventTypeToPropertyMap.put(ScriptEventType.CMS_EVAL_EVENT, Properties.CMS);
344        eventTypeToPropertyMap.put(ScriptEventType.FACILITATOR_EVAL_EVENT, Properties.Facilitator);
345        eventTypeToPropertyMap.put(ScriptEventType.RADIO_EVAL_EVENT, Properties.Radio);
346
347        // Add the mouse listener
348        IncidentTimelineMouseListener mouseListener
349                = new IncidentTimelineMouseListener();
350        addMouseMotionListener(mouseListener);
351        addMouseListener(mouseListener);
352    }
353
354    /**
355     * Update the panel if it's changed collapsed status. Redraw it with the
356     * correct dimensions for its status.
357     *
358     * @param incident the incident this panel represents
359     */
360    public void timelinePanelUpdate(ScriptIncident incident)
361    {
362        this.incident = incident;
363        this.visible = incident != null;
364
365        Dimension newSize;
366        if (visible)
367        {
368
369            newSize = new Dimension(((incident.length + incident.offset)
370                    / ScriptBuilderGuiConstants.HORIZONTAL_TICK_RESOLUTION
371                    * ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK)
372                    + ScriptBuilderGuiConstants.EVENT_ICON_WIDTH,
373                    ScriptBuilderGuiConstants.TIMELINE_COLLAPSED_HEIGHT
374                    + ScriptBuilderGuiConstants.SCRIPT_EVENT_ICON_STEP * 2);
375
376        }
377        else
378        {
379            newSize = new Dimension(0, 0);
380        }
381        this.setSize(newSize);
382        this.setPreferredSize(newSize);
383
384        invalidate();
385    }
386
387    /**
388     * Redraw this panel and all the icons inside it. If user is holding an
389     * event, draw that icon under the mouse.
390     *
391     * @param g the graphics component
392     */
393    @Override
394    public void paint(Graphics g)
395    {
396        super.paint(g);
397
398        if (!visible)
399        {
400            return;
401        }
402
403        Graphics2D g2d = (Graphics2D) g;
404//        jdalbey removed this decision and replaced it with ELSE clause
405//                so it will work with any alternate ancestor.
406//        if (getTopLevelAncestor() instanceof ScriptBuilderFrame)
407//        {
408//            IncidentTimelineDrawer.DrawScriptBuilderTimeline(g2d, incident);
409//        }
410        if (getTopLevelAncestor() instanceof IncidentEditorFrame)
411        {
412            IncidentTimelineDrawer.DrawIncidentTimeline(g2d, incident, false);
413        }
414        else
415        {
416            IncidentTimelineDrawer.DrawScriptBuilderTimeline(g2d, incident);
417        }
418
419        if (focused)
420        {
421            CursorDrawer.DrawCursor(g2d, cursorTime, false);
422            if (this.getTopLevelAncestor() instanceof ScriptBuilderFrame)
423            {
424                if (((ScriptBuilderFrame) this.getTopLevelAncestor()).currentEventType != null)
425                {
426                    EventIconDrawer.DrawEventIcon(g2d,
427                            ((ScriptBuilderFrame) this.getTopLevelAncestor()).currentEventType,
428                            x + 5, y + 10);
429                }
430            }
431            if (this.getTopLevelAncestor() instanceof IncidentEditorFrame)
432            {
433                if (((IncidentEditorFrame) this.getTopLevelAncestor()).currentEventType != null)
434                {
435                    EventIconDrawer.DrawEventIcon(g2d,
436                            ((IncidentEditorFrame) this.getTopLevelAncestor()).currentEventType,
437                            x + 5, y + 10);
438                }
439            }
440        }
441    }
442
443    /**
444     * Local main for viewing this panel only.
445     *
446     * @author jdalbey
447     * @param args not used
448     */
449    public static void main(String[] args)
450    {
451        JFrame frame = new JFrame("ScriptBuilderTimelinePanel Demo");
452        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
453
454        IncidentTimelinePanel pnl = new IncidentTimelinePanel();
455
456        // Create a script
457        File inFile = new File("test/scriptbuilder/structures/test_input_file.xml");
458        SimulationScript script = new SimulationScript();
459        script.loadScriptFromFile(inFile);
460        // retrieve a single incident from the script
461        ScriptIncident inci = script.incidents.get(2);
462        // update this panel with an incident
463        pnl.timelinePanelUpdate(inci);
464
465        frame.getContentPane().add(pnl, BorderLayout.CENTER);
466        frame.pack();
467
468        frame.setVisible(true);
469
470    }
471}
Note: See TracBrowser for help on using the repository browser.