source: tmcsimulator-scriptbuilder/trunk/src/scriptbuilder/gui/panels/ScriptBuilderTimelinePanel.java @ 61

Revision 61, 12.7 KB checked in by bmcguffin, 9 years ago (diff)

Made a few cosmetic changes to the code. Added a statement in the update method of IncidentEditorFrame? which tries to set the maximum scale of the zoom slider at an appropriate level.

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