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

Revision 90, 15.2 KB checked in by bmcguffin, 9 years ago (diff)

Removed the call to Editor.java from mouseClicked() when the parent window is ScriptBuilderFrame?.

RevLine 
1package scriptbuilder.gui.panels;
2
3import event.editor.Editor;
4import event.editor.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                JOptionPane.showMessageDialog(null, e.getActionCommand() + " will be handled here.");
133            }
134        }
135
136        @Override
137        public void mousePressed(MouseEvent e)
138        {
139            int currentMouseX = e.getX();
140            int currentMouseY = e.getY();
141
142            // Does user want a popup menu?
143            if (e.isPopupTrigger())
144            {
145                JPopupMenu popup = createPopup();
146                popup.show(e.getComponent(), currentMouseX, currentMouseY);
147            }
148        }
149
150        /**
151         * Determine if the mouse click happened within a valid timeSlice on
152         * this incident; if so, activate the Editor window for that timeSlice.
153         *
154         * @param e the mouse event
155         */
156        @Override
157        public void mouseClicked(MouseEvent e)
158        {
159            Editor ed = null;
160            ScriptBuilderFrame f = null;
161            IncidentEditorFrame g = null;
162            if (getTopLevelAncestor() instanceof ScriptBuilderFrame)
163            {
164                f = (ScriptBuilderFrame) getTopLevelAncestor();
165
166            }
167            else if (getTopLevelAncestor() instanceof IncidentEditorFrame)
168            {
169                g = (IncidentEditorFrame) getTopLevelAncestor();
170                ed = new Editor(g);
171            }
172
173            x = cursorTime = e.getX();
174            y = e.getY();
175
176            if (e.getX() % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK
177                    > ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK / 2)
178            {
179                cursorTime += ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK
180                        - e.getX()
181                        % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK;
182            }
183            else
184            {
185                cursorTime -= e.getX()
186                        % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK;
187            }
188
189            int newSlice = (cursorTime / ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK);
190            newSlice *= ScriptBuilderGuiConstants.HORIZONTAL_TICK_RESOLUTION;
191            /**
192             * Check if click is out of bounds *
193             */
194            if (newSlice < 0 || incident == null)
195            {
196                return;
197            }
198
199            if (incident.slices.get(newSlice) != null)
200
201            {
202                for (I_ScriptEvent se : incident.slices.get(newSlice).events)
203                {
204                    if (ed != null)
205                    {
206                        ed.addProperty(eventTypeToPropertyMap.get(se.getScriptEventType()), se);
207                    }
208                }
209            }
210
211            /**
212             * Add a new icon if left mouse button was clicked *
213             */
214            if (e.getButton() == MouseEvent.BUTTON1)
215            {
216
217                if (getTopLevelAncestor() instanceof IncidentEditorFrame)
218                {
219                    if (g.currentEventType != null)
220                    {
221                        I_ScriptEvent s = ScriptEvent.factoryByType(g.currentEventType);
222                        if (ed != null)
223                        {
224                            ed.addProperty(eventTypeToPropertyMap.get(g.currentEventType), s);
225                        }
226                        if (incident.slices.get(newSlice) == null)
227                        {
228                            incident.addNewEvent(s, newSlice);
229                        }
230                        else
231                        {
232                            incident.slices.get(newSlice).addEvent(s);
233                        }
234                        g.update(null, g.getIncident());
235                    }
236                }
237            }
238
239            if (incident.slices.get(newSlice) != null
240                    && getTopLevelAncestor() instanceof IncidentEditorFrame)
241            {
242                ed.setVisible(true);
243            }
244        }
245
246        /**
247         * Determine if the mouse is now hovering over a valid timeslice; if so,
248         * alter tooltip text and info window text to reflect the new timeslice.
249         *
250         * @param e the mouse event
251         */
252        @Override
253        public void mouseMoved(MouseEvent e)
254        {
255            x = cursorTime = e.getX();
256            y = e.getY();
257
258            if (e.getX() % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK
259                    > ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK / 2)
260            {
261                cursorTime += ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK
262                        - e.getX()
263                        % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK;
264            }
265            else
266            {
267                cursorTime -= e.getX()
268                        % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK;
269            }
270
271            if (incident != null)
272            {
273                int newSlice = (cursorTime / ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK);
274                newSlice *= ScriptBuilderGuiConstants.HORIZONTAL_TICK_RESOLUTION;
275                if (newSlice >= 0 && incident.slices.get(newSlice) != null)
276                {
277                    incident.setSliceActive(newSlice);
278                    lastSlice = newSlice;
279                    String newToolTip;
280
281                    newToolTip = incident.slices.get(newSlice).getToolTipText(y);
282
283                    setToolTipText((newToolTip == null || newToolTip.equals(""))
284                            ? null : newToolTip);
285                }
286            }
287
288            repaint();
289        }
290    }
291
292    /**
293     * Constructor. Generates a HashMap of all possible event types.
294     */
295    public IncidentTimelinePanel()
296    {
297        super();
298
299//        FACILITATOR_EVAL_EVENT, RADIO_EVAL_EVENT
300        eventTypeToPropertyMap = new HashMap();
301        eventTypeToPropertyMap.put(ScriptEventType.AUDIO_EVENT, Properties.Audio);
302        eventTypeToPropertyMap.put(ScriptEventType.CAD_EVENT, Properties.CADLog);
303        eventTypeToPropertyMap.put(ScriptEventType.CCTV_EVENT, Properties.CCTV);
304        eventTypeToPropertyMap.put(ScriptEventType.CHP_RADIO_EVENT, Properties.CHPRadio);
305        eventTypeToPropertyMap.put(ScriptEventType.PARAMICS_EVENT, Properties.Paramics);
306        eventTypeToPropertyMap.put(ScriptEventType.TOW_EVENT, Properties.Tow);
307        eventTypeToPropertyMap.put(ScriptEventType.UNIT_EVENT, Properties.Unit);
308        eventTypeToPropertyMap.put(ScriptEventType.WITNESS_EVENT, Properties.Witness);
309        eventTypeToPropertyMap.put(ScriptEventType.MAINTENANCE_RADIO_EVENT, Properties.MaintenanceRadio);
310        eventTypeToPropertyMap.put(ScriptEventType.TMT_RADIO_EVENT, Properties.TMTRadio);
311        eventTypeToPropertyMap.put(ScriptEventType.TELEPHONE_EVENT, Properties.Telephone);
312        eventTypeToPropertyMap.put(ScriptEventType.ATMS_EVAL_EVENT, Properties.ATMS);
313        eventTypeToPropertyMap.put(ScriptEventType.ACTIVITY_LOG_EVAL_EVENT, Properties.ActivityLog);
314        eventTypeToPropertyMap.put(ScriptEventType.CAD_EVAL_EVENT, Properties.CAD);
315        eventTypeToPropertyMap.put(ScriptEventType.CMS_EVAL_EVENT, Properties.CMS);
316        eventTypeToPropertyMap.put(ScriptEventType.FACILITATOR_EVAL_EVENT, Properties.Facilitator);
317        eventTypeToPropertyMap.put(ScriptEventType.RADIO_EVAL_EVENT, Properties.Radio);
318
319        // Add the mouse listener
320        IncidentTimelineMouseListener mouseListener
321                = new IncidentTimelineMouseListener();
322        addMouseMotionListener(mouseListener);
323        addMouseListener(mouseListener);
324    }
325
326    /**
327     * Update the panel if it's changed collapsed status. Redraw it with the
328     * correct dimensions for its status.
329     *
330     * @param incident the incident this panel represents
331     */
332    public void timelinePanelUpdate(ScriptIncident incident)
333    {
334        this.incident = incident;
335        this.visible = incident != null;
336
337        Dimension newSize;
338        if (visible)
339        {
340
341            newSize = new Dimension(((incident.length + incident.offset)
342                    / ScriptBuilderGuiConstants.HORIZONTAL_TICK_RESOLUTION
343                    * ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK)
344                    + ScriptBuilderGuiConstants.EVENT_ICON_WIDTH,
345                    ScriptBuilderGuiConstants.TIMELINE_COLLAPSED_HEIGHT
346                    + ScriptBuilderGuiConstants.SCRIPT_EVENT_ICON_STEP * 2);
347
348        }
349        else
350        {
351            newSize = new Dimension(0, 0);
352        }
353        this.setSize(newSize);
354        this.setPreferredSize(newSize);
355
356        invalidate();
357    }
358
359    /**
360     * Redraw this panel and all the icons inside it. If user is holding an
361     * event, draw that icon under the mouse.
362     *
363     * @param g the graphics component
364     */
365    @Override
366    public void paint(Graphics g)
367    {
368        super.paint(g);
369
370        if (!visible)
371        {
372            return;
373        }
374
375        Graphics2D g2d = (Graphics2D) g;
376//        jdalbey removed this decision and replaced it with ELSE clause
377//                so it will work with any alternate ancestor.
378//        if (getTopLevelAncestor() instanceof ScriptBuilderFrame)
379//        {
380//            IncidentTimelineDrawer.DrawScriptBuilderTimeline(g2d, incident);
381//        }
382        if (getTopLevelAncestor() instanceof IncidentEditorFrame)
383        {
384            IncidentTimelineDrawer.DrawIncidentTimeline(g2d, incident, false);
385        }
386        else
387        {
388            IncidentTimelineDrawer.DrawScriptBuilderTimeline(g2d, incident);
389        }
390
391        if (focused)
392        {
393            CursorDrawer.DrawCursor(g2d, cursorTime, false);
394            if (this.getTopLevelAncestor() instanceof ScriptBuilderFrame)
395            {
396                if (((ScriptBuilderFrame) this.getTopLevelAncestor()).currentEventType != null)
397                {
398                    EventIconDrawer.DrawEventIcon(g2d,
399                            ((ScriptBuilderFrame) this.getTopLevelAncestor()).currentEventType,
400                            x + 5, y + 10);
401                }
402            }
403            if (this.getTopLevelAncestor() instanceof IncidentEditorFrame)
404            {
405                if (((IncidentEditorFrame) this.getTopLevelAncestor()).currentEventType != null)
406                {
407                    EventIconDrawer.DrawEventIcon(g2d,
408                            ((IncidentEditorFrame) this.getTopLevelAncestor()).currentEventType,
409                            x + 5, y + 10);
410                }
411            }
412        }
413    }
414
415    /**
416     * Local main for viewing this panel only.
417     *
418     * @author jdalbey
419     * @param args not used
420     */
421    public static void main(String[] args)
422    {
423        JFrame frame = new JFrame("ScriptBuilderTimelinePanel Demo");
424        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
425
426        IncidentTimelinePanel pnl = new IncidentTimelinePanel();
427
428        // Create a script
429        File inFile = new File("test/scriptbuilder/structures/test_input_file.xml");
430        SimulationScript script = new SimulationScript();
431        script.loadScriptFromFile(inFile);
432        // retrieve a single incident from the script
433        ScriptIncident inci = script.incidents.get(2);
434        // update this panel with an incident
435        pnl.timelinePanelUpdate(inci);
436
437        frame.getContentPane().add(pnl, BorderLayout.CENTER);
438        frame.pack();
439
440        frame.setVisible(true);
441
442    }
443}
Note: See TracBrowser for help on using the repository browser.