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

Revision 31, 11.6 KB checked in by bmcguffin, 9 years ago (diff)

Fixed bug in which event icons failed to be rendered past the end of an incident. Also fixed a bug in which new events could not be added past the end of an incident.

RevLine 
1package scriptbuilder.gui.panels;
2
3import event.editor.Editor;
4import event.editor.Properties;
5import java.awt.Dimension;
6import java.awt.Graphics;
7import java.awt.Graphics2D;
8import java.awt.event.MouseEvent;
9import java.util.HashMap;
10import java.util.Map;
11import javax.swing.JPanel;
12import javax.swing.event.MouseInputAdapter;
13import scriptbuilder.gui.ScriptBuilderFrame;
14import scriptbuilder.gui.ScriptBuilderGuiConstants;
15import scriptbuilder.gui.drawers.CursorDrawer;
16import scriptbuilder.gui.drawers.EventIconDrawer;
17import scriptbuilder.gui.drawers.IncidentTimelineDrawer;
18import scriptbuilder.structures.ScriptEvent;
19import scriptbuilder.structures.ScriptEvent.ScriptEventType;
20import scriptbuilder.structures.ScriptIncident;
21import scriptbuilder.structures.TimeSlice;
22import scriptbuilder.structures.events.I_ScriptEvent;
23
24/**
25 * Represents a single incident timeline in the GUI. Listens for mouse actions.
26 *
27 * @author Greg Eddington <geddingt@calpoly.edu>
28 * @author Bryan McGuffin
29 * @version 2017/06/30
30 */
31public class IncidentTimelinePanel extends JPanel
32{
33
34    /**
35     * The incident this panel represents.
36     */
37    ScriptIncident incident;
38    /**
39     * If true, this panel is in its minimized state.
40     */
41    boolean collapsed;
42    /**
43     * If false, this panel won't be drawn.
44     */
45    boolean visible;
46    /**
47     * If true, this panel has focus.
48     */
49    boolean focused;
50
51    int cursorTime, lastSlice, x, y;
52
53    /**
54     * The map representing the properties of this incident's events. Keys:
55     * event types. Values: Properties objects for those events.
56     */
57    Map<ScriptEventType, Properties> eventTypeToPropertyMap;
58
59    /**
60     * Listener for the mouse. Receives notifications when the mouse enters,
61     * exits, moves through, or clicks inside the panel.
62     */
63    public class IncidentTimelineMouseListener extends MouseInputAdapter
64    {
65
66        /**
67         * Action to take when the mouse enters the panel. Here, the incident
68         * corresponding to this panel gains focus.
69         *
70         * @param e the mouse event
71         */
72        @Override
73        public void mouseEntered(MouseEvent e)
74        {
75            incident.setIncidentActive();
76            focused = true;
77        }
78
79        /**
80         * Action to take when the mouse leaves the panel. Here, the incident
81         * loses focus and the panel gets repainted.
82         *
83         * @param e the mouse event
84         */
85        @Override
86        public void mouseExited(MouseEvent e)
87        {
88            focused = false;
89            repaint();
90        }
91
92        /**
93         * Determine if the mouse click happened within a valid timeSlice on
94         * this incident; if so, activate the Editor window for that timeSlice.
95         *
96         * @param e the mouse event
97         */
98        @Override
99        public void mouseClicked(MouseEvent e)
100        {
101            Editor ed = new Editor();
102            ScriptBuilderFrame f = (ScriptBuilderFrame) getTopLevelAncestor();
103
104            x = cursorTime = e.getX();
105            y = e.getY();
106
107            if (e.getX() % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK
108                    > ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK / 2)
109            {
110                cursorTime += ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK
111                        - e.getX()
112                        % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK;
113            }
114            else
115            {
116                cursorTime -= e.getX()
117                        % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK;
118            }
119
120            int newSlice = (cursorTime / ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK);
121            newSlice *= ScriptBuilderGuiConstants.HORIZONTAL_TICK_RESOLUTION;
122            /**
123             * Check if click is out of bounds *
124             */
125            if (newSlice < 0 || incident == null)
126            {
127                return;
128            }
129
130            if (incident.slices.get(newSlice) != null)
131
132            {
133                for (I_ScriptEvent se : incident.slices.get(newSlice).events)
134                {
135                    ed.addProperty(eventTypeToPropertyMap.get(se.getScriptEventType()), se);
136                }
137            }
138
139            /**
140             * Add a new icon if left mouse button was clicked *
141             */
142            if (e.getButton() == MouseEvent.BUTTON1)
143            {
144                if (f.currentEventType != null)
145                {
146                    I_ScriptEvent s = ScriptEvent.factoryByType(f.currentEventType);
147                    ed.addProperty(eventTypeToPropertyMap.get(f.currentEventType), s);
148                    if (incident.slices.get(newSlice) == null)
149                    {
150                        incident.addNewEvent(s, newSlice);
151                    }
152                    else
153                    {
154                        incident.slices.get(newSlice).addEvent(s);
155                    }
156                    f.update(f.getScript(), f.getScript());
157                }
158            }
159
160            if (incident.slices.get(newSlice) != null)
161            {
162                ed.setVisible(true);
163                System.out.println(incident.slices.get(newSlice).toXML());
164            }
165        }
166
167        /**
168         * Determine if the mouse is now hovering over a valid timeslice; if so,
169         * alter tooltip text and info window text to reflect the new timeslice.
170         *
171         * @param e the mouse event
172         */
173        @Override
174        public void mouseMoved(MouseEvent e)
175        {
176            x = cursorTime = e.getX();
177            y = e.getY();
178
179            if (e.getX() % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK
180                    > ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK / 2)
181            {
182                cursorTime += ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK
183                        - e.getX()
184                        % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK;
185            }
186            else
187            {
188                cursorTime -= e.getX()
189                        % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK;
190            }
191
192            if (incident != null)
193            {
194                int newSlice = (cursorTime / ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK);
195                newSlice *= ScriptBuilderGuiConstants.HORIZONTAL_TICK_RESOLUTION;
196                if (newSlice >= 0 && incident.slices.get(newSlice) != null)
197                {
198                    incident.setSliceActive(newSlice);
199                    lastSlice = newSlice;
200                    String newToolTip;
201                    if (collapsed)
202                    {
203                        newToolTip = incident.slices.get(newSlice).toString();
204                    }
205                    else
206                    {
207                        newToolTip = incident.slices.get(newSlice).getToolTipText(y);
208                    }
209                    setToolTipText((newToolTip == null || newToolTip.equals(""))
210                            ? null : newToolTip);
211                }
212            }
213
214            repaint();
215        }
216    }
217
218    /**
219     * Constructor. Generates a HashMap of all possible event types.
220     */
221    public IncidentTimelinePanel()
222    {
223        super();
224
225//        FACILITATOR_EVAL_EVENT, RADIO_EVAL_EVENT
226        eventTypeToPropertyMap = new HashMap();
227        eventTypeToPropertyMap.put(ScriptEventType.AUDIO_EVENT, Properties.Audio);
228        eventTypeToPropertyMap.put(ScriptEventType.CAD_EVENT, Properties.CADLog);
229        eventTypeToPropertyMap.put(ScriptEventType.CCTV_EVENT, Properties.CCTV);
230        eventTypeToPropertyMap.put(ScriptEventType.CHP_RADIO_EVENT, Properties.CHPRadio);
231        eventTypeToPropertyMap.put(ScriptEventType.PARAMICS_EVENT, Properties.Paramics);
232        eventTypeToPropertyMap.put(ScriptEventType.TOW_EVENT, Properties.Tow);
233        eventTypeToPropertyMap.put(ScriptEventType.UNIT_EVENT, Properties.Unit);
234        eventTypeToPropertyMap.put(ScriptEventType.WITNESS_EVENT, Properties.Witness);
235        eventTypeToPropertyMap.put(ScriptEventType.MAINTENANCE_RADIO_EVENT, Properties.MaintenanceRadio);
236        eventTypeToPropertyMap.put(ScriptEventType.TMT_RADIO_EVENT, Properties.TMTRadio);
237        eventTypeToPropertyMap.put(ScriptEventType.TELEPHONE_EVENT, Properties.Telephone);
238        eventTypeToPropertyMap.put(ScriptEventType.ATMS_EVAL_EVENT, Properties.ATMS);
239        eventTypeToPropertyMap.put(ScriptEventType.ACTIVITY_LOG_EVAL_EVENT, Properties.ActivityLog);
240        eventTypeToPropertyMap.put(ScriptEventType.CAD_EVAL_EVENT, Properties.CAD);
241        eventTypeToPropertyMap.put(ScriptEventType.CMS_EVAL_EVENT, Properties.CMS);
242        eventTypeToPropertyMap.put(ScriptEventType.FACILITATOR_EVAL_EVENT, Properties.Facilitator);
243        eventTypeToPropertyMap.put(ScriptEventType.RADIO_EVAL_EVENT, Properties.Radio);
244
245        // Add the mouse listener
246        IncidentTimelineMouseListener mouseListener
247                = new IncidentTimelineMouseListener();
248        addMouseMotionListener(mouseListener);
249        addMouseListener(mouseListener);
250    }
251
252    /**
253     * Update the panel if it's changed collapsed status. Redraw it with the
254     * correct dimensions for its status.
255     *
256     * @param incident the incident this panel represents
257     */
258    public void timelinePanelUpdate(ScriptIncident incident)
259    {
260        this.incident = incident;
261        if (incident != null)
262        {
263            this.collapsed = incident.collapsed;
264        }
265        this.visible = incident != null;
266
267        Dimension newSize;
268        if (visible)
269        {
270            if (collapsed)
271            {
272                newSize = new Dimension((incident.length + incident.offset)
273                        / ScriptBuilderGuiConstants.HORIZONTAL_TICK_RESOLUTION
274                        * ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK,
275                        ScriptBuilderGuiConstants.TIMELINE_COLLAPSED_HEIGHT);
276            }
277            else
278            {
279                int mostEvents = 0;
280                for (TimeSlice slice : incident.getSlices())
281                {
282                    if (slice.events.size() > mostEvents)
283                    {
284                        mostEvents = slice.events.size();
285                    }
286                }
287
288                newSize = new Dimension((ScriptBuilderGuiConstants.MAX_SIMULATION_LENGTH)
289                        / ScriptBuilderGuiConstants.HORIZONTAL_TICK_RESOLUTION
290                        * ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK,
291                        ScriptBuilderGuiConstants.TIMELINE_COLLAPSED_HEIGHT
292                        + ScriptBuilderGuiConstants.SCRIPT_EVENT_ICON_STEP * (mostEvents + 1));
293            }
294        }
295        else
296        {
297            newSize = new Dimension(0, 0);
298        }
299        this.setSize(newSize);
300        this.setPreferredSize(newSize);
301
302        invalidate();
303    }
304
305    /**
306     * Redraw this panel and all the icons inside it. If user is holding an
307     * event, draw that icon under the mouse.
308     *
309     * @param g the graphics component
310     */
311    @Override
312    public void paint(Graphics g)
313    {
314        super.paint(g);
315
316        if (!visible)
317        {
318            return;
319        }
320
321        Graphics2D g2d = (Graphics2D) g;
322        IncidentTimelineDrawer.DrawIncidentTimeline(g2d, incident, collapsed);
323
324        if (focused)
325        {
326            CursorDrawer.DrawCursor(g2d, cursorTime, false);
327            if (((ScriptBuilderFrame) this.getTopLevelAncestor()).currentEventType != null)
328            {
329                EventIconDrawer.DrawEventIcon(g2d,
330                        ((ScriptBuilderFrame) this.getTopLevelAncestor()).currentEventType,
331                        x + 5, y + 10);
332            }
333        }
334    }
335}
Note: See TracBrowser for help on using the repository browser.