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

Revision 1, 11.2 KB checked in by bmcguffin, 9 years ago (diff)

2017/07/18: Uploaded entire prototype to SVN repo.

Line 
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.ScriptEventInterface;
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 (incident.slices.get(newSlice) == null || incident == null
126                    || newSlice < 0)
127            {
128                return;
129            }
130
131            for (ScriptEventInterface se : incident.slices.get(newSlice).events)
132            {
133                ed.addProperty(eventTypeToPropertyMap.get(se.getScriptEventType()), se);
134            }
135
136            /**
137             * Add a new icon if left mouse button was clicked *
138             */
139            if (e.getButton() == MouseEvent.BUTTON1)
140            {
141                if (f.currentEventType != null)
142                {
143                    ScriptEventInterface s = ScriptEvent.factoryByType(f.currentEventType);
144                    ed.addProperty(eventTypeToPropertyMap.get(f.currentEventType), s);
145                    incident.slices.get(newSlice).addEvent(s);
146                    f.update(f.getScript(), f.getScript());
147                }
148            }
149
150            ed.setVisible(true);
151        }
152
153        /**
154         * Determine if the mouse is now hovering over a valid timeslice; if so,
155         * alter tooltip text and info window text to reflect the new timeslice.
156         *
157         * @param e the mouse event
158         */
159        @Override
160        public void mouseMoved(MouseEvent e)
161        {
162            x = cursorTime = e.getX();
163            y = e.getY();
164
165            if (e.getX() % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK
166                    > ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK / 2)
167            {
168                cursorTime += ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK
169                        - e.getX()
170                        % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK;
171            }
172            else
173            {
174                cursorTime -= e.getX()
175                        % ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK;
176            }
177
178            if (incident != null)
179            {
180                int newSlice = (cursorTime / ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK);
181                newSlice *= ScriptBuilderGuiConstants.HORIZONTAL_TICK_RESOLUTION;
182                if (newSlice >= 0 && incident.slices.get(newSlice) != null)
183                {
184                    incident.setSliceActive(newSlice);
185                    lastSlice = newSlice;
186                    String newToolTip;
187                    if (collapsed)
188                    {
189                        newToolTip = incident.slices.get(newSlice).toString();
190                    }
191                    else
192                    {
193                        newToolTip = incident.slices.get(newSlice).getToolTipText(y);
194                    }
195                    setToolTipText((newToolTip == null || newToolTip.equals(""))
196                            ? null : newToolTip);
197                }
198            }
199
200            repaint();
201        }
202    }
203
204    /**
205     * Constructor. Generates a HashMap of all possible event types.
206     */
207    public IncidentTimelinePanel()
208    {
209        super();
210
211//        FACILITATOR_EVAL_EVENT, RADIO_EVAL_EVENT
212        eventTypeToPropertyMap = new HashMap();
213        eventTypeToPropertyMap.put(ScriptEventType.AUDIO_EVENT, Properties.Audio);
214        eventTypeToPropertyMap.put(ScriptEventType.CAD_EVENT, Properties.CADLog);
215        eventTypeToPropertyMap.put(ScriptEventType.CCTV_EVENT, Properties.CCTV);
216        eventTypeToPropertyMap.put(ScriptEventType.CHP_RADIO_EVENT, Properties.CHPRadio);
217        eventTypeToPropertyMap.put(ScriptEventType.PARAMICS_EVENT, Properties.Paramics);
218        eventTypeToPropertyMap.put(ScriptEventType.TOW_EVENT, Properties.Tow);
219        eventTypeToPropertyMap.put(ScriptEventType.UNIT_EVENT, Properties.Unit);
220        eventTypeToPropertyMap.put(ScriptEventType.WITNESS_EVENT, Properties.Witness);
221        eventTypeToPropertyMap.put(ScriptEventType.MAINTENANCE_RADIO_EVENT, Properties.MaintenanceRadio);
222        eventTypeToPropertyMap.put(ScriptEventType.TMT_RADIO_EVENT, Properties.TMTRadio);
223        eventTypeToPropertyMap.put(ScriptEventType.TELEPHONE_EVENT, Properties.Telephone);
224        eventTypeToPropertyMap.put(ScriptEventType.ATMS_EVAL_EVENT, Properties.ATMS);
225        eventTypeToPropertyMap.put(ScriptEventType.ACTIVITY_LOG_EVAL_EVENT, Properties.ActivityLog);
226        eventTypeToPropertyMap.put(ScriptEventType.CAD_EVAL_EVENT, Properties.CAD);
227        eventTypeToPropertyMap.put(ScriptEventType.CMS_EVAL_EVENT, Properties.CMS);
228        eventTypeToPropertyMap.put(ScriptEventType.FACILITATOR_EVAL_EVENT, Properties.Facilitator);
229        eventTypeToPropertyMap.put(ScriptEventType.RADIO_EVAL_EVENT, Properties.Radio);
230
231        // Add the mouse listener
232        IncidentTimelineMouseListener mouseListener
233                = new IncidentTimelineMouseListener();
234        addMouseMotionListener(mouseListener);
235        addMouseListener(mouseListener);
236    }
237
238    /**
239     * Update the panel if it's changed collapsed status. Redraw it with the
240     * correct dimensions for its status.
241     *
242     * @param incident the incident this panel represents
243     */
244    public void timelinePanelUpdate(ScriptIncident incident)
245    {
246        this.incident = incident;
247        if (incident != null)
248        {
249            this.collapsed = incident.collapsed;
250        }
251        this.visible = incident != null;
252
253        Dimension newSize;
254        if (visible)
255        {
256            if (collapsed)
257            {
258                newSize = new Dimension((incident.length + incident.offset)
259                        / ScriptBuilderGuiConstants.HORIZONTAL_TICK_RESOLUTION
260                        * ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK,
261                        ScriptBuilderGuiConstants.TIMELINE_COLLAPSED_HEIGHT);
262            }
263            else
264            {
265                int mostEvents = 0;
266                for (TimeSlice slice : incident.getSlices())
267                {
268                    if (slice.events.size() > mostEvents)
269                    {
270                        mostEvents = slice.events.size();
271                    }
272                }
273
274                newSize = new Dimension((incident.length + incident.offset)
275                        / ScriptBuilderGuiConstants.HORIZONTAL_TICK_RESOLUTION
276                        * ScriptBuilderGuiConstants.PIXEL_WIDTH_PER_HORIZONTAL_TICK,
277                        ScriptBuilderGuiConstants.TIMELINE_COLLAPSED_HEIGHT
278                        + ScriptBuilderGuiConstants.SCRIPT_EVENT_ICON_STEP * (mostEvents + 1));
279            }
280        }
281        else
282        {
283            newSize = new Dimension(0, 0);
284        }
285        this.setSize(newSize);
286        this.setPreferredSize(newSize);
287
288        invalidate();
289    }
290
291    /**
292     * Redraw this panel and all the icons inside it. If user is holding an
293     * event, draw that icon under the mouse.
294     *
295     * @param g the graphics component
296     */
297    @Override
298    public void paint(Graphics g)
299    {
300        super.paint(g);
301
302        if (!visible)
303        {
304            return;
305        }
306
307        Graphics2D g2d = (Graphics2D) g;
308        IncidentTimelineDrawer.DrawIncidentTimeline(g2d, incident, collapsed);
309
310        if (focused)
311        {
312            CursorDrawer.DrawCursor(g2d, cursorTime, false);
313            if (((ScriptBuilderFrame) this.getTopLevelAncestor()).currentEventType != null)
314            {
315                EventIconDrawer.DrawEventIcon(g2d,
316                        ((ScriptBuilderFrame) this.getTopLevelAncestor()).currentEventType,
317                        x + 5, y + 10);
318            }
319        }
320    }
321}
Note: See TracBrowser for help on using the repository browser.