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

Revision 113, 19.1 KB checked in by bmcguffin, 9 years ago (diff)

Added constructor to IncidentTimelinePanel? with a boolean parameter to determine whether the panel can display a popup menu. The incident editor frame no longer displays the popup menu upon right-click.

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