1 package org.opentrafficsim.swing.gui;
2
3 import java.awt.BorderLayout;
4 import java.awt.Component;
5 import java.awt.Container;
6 import java.awt.Dimension;
7 import java.awt.Graphics;
8 import java.awt.event.ActionEvent;
9 import java.awt.event.ActionListener;
10 import java.awt.event.ContainerEvent;
11 import java.awt.event.ContainerListener;
12 import java.awt.event.MouseAdapter;
13 import java.awt.event.MouseEvent;
14 import java.awt.event.MouseListener;
15 import java.awt.event.MouseWheelEvent;
16 import java.awt.event.MouseWheelListener;
17 import java.awt.event.WindowEvent;
18 import java.awt.event.WindowListener;
19 import java.awt.geom.Point2D;
20 import java.awt.geom.Rectangle2D;
21 import java.rmi.RemoteException;
22 import java.text.NumberFormat;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27
28 import javax.swing.BoxLayout;
29 import javax.swing.Icon;
30 import javax.swing.JButton;
31 import javax.swing.JCheckBox;
32 import javax.swing.JFrame;
33 import javax.swing.JLabel;
34 import javax.swing.JPanel;
35 import javax.swing.JTextField;
36 import javax.swing.JToggleButton;
37 import javax.swing.border.EmptyBorder;
38
39 import org.opentrafficsim.core.animation.gtu.colorer.GTUColorer;
40 import org.opentrafficsim.core.dsol.OTSAnimator;
41 import org.opentrafficsim.core.dsol.OTSModelInterface;
42 import org.opentrafficsim.core.gtu.GTU;
43 import org.opentrafficsim.core.network.Network;
44 import org.opentrafficsim.core.network.OTSNetwork;
45
46 import nl.javel.gisbeans.map.MapInterface;
47 import nl.tudelft.simulation.dsol.animation.Locatable;
48 import nl.tudelft.simulation.dsol.animation.D2.GisRenderable2D;
49 import nl.tudelft.simulation.dsol.animation.D2.Renderable2DInterface;
50 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
51 import nl.tudelft.simulation.dsol.swing.animation.D2.AnimationPanel;
52 import nl.tudelft.simulation.dsol.swing.animation.D2.GridPanel;
53 import nl.tudelft.simulation.dsol.swing.animation.D2.mouse.InputListener;
54 import nl.tudelft.simulation.event.Event;
55 import nl.tudelft.simulation.event.EventInterface;
56 import nl.tudelft.simulation.event.EventListenerInterface;
57 import nl.tudelft.simulation.language.d3.DirectedPoint;
58
59
60
61
62
63
64
65
66
67
68
69
70 public class OTSAnimationPanel extends OTSSimulationPanel implements ActionListener, WindowListener, EventListenerInterface
71 {
72
73 private static final long serialVersionUID = 20150617L;
74
75
76 private final AutoAnimationPanel animationPanel;
77
78
79 private final JPanel borderPanel;
80
81
82 private final JPanel togglePanel;
83
84
85 private JPanel demoPanel = null;
86
87
88 private Map<String, Class<? extends Locatable>> toggleLocatableMap = new HashMap<>();
89
90
91 private Map<Class<? extends Locatable>, JToggleButton> toggleButtons = new HashMap<>();
92
93
94 private Map<String, MapInterface> toggleGISMap = new HashMap<>();
95
96
97 private Map<String, JToggleButton> toggleGISButtons = new HashMap<>();
98
99
100 private GTUColorer gtuColorer = null;
101
102
103 private ColorControlPanel colorControlPanel = null;
104
105
106 private final JLabel coordinateField;
107
108
109 private final JLabel gtuCountField;
110
111
112 private int gtuCount = 0;
113
114
115 private final ArrayList<JButton> buttons = new ArrayList<>();
116
117
118 private static final NumberFormat FORMATTER = NumberFormat.getInstance();
119
120
121 @SuppressWarnings("checkstyle:visibilitymodifier")
122 protected boolean closeHandlerRegistered = false;
123
124
125 @SuppressWarnings("checkstyle:visibilitymodifier")
126 protected boolean windowExited = false;
127
128
129 private boolean autoPan = false;
130
131
132 private final JCheckBox autoPanToggle;
133
134
135 private final JTextField autoPanField;
136
137
138 static
139 {
140 FORMATTER.setMaximumFractionDigits(3);
141 }
142
143
144
145
146
147
148
149
150
151
152
153 public OTSAnimationPanel(final Rectangle2D extent, final Dimension size, final OTSAnimator simulator,
154 final OTSModelInterface otsModel, final GTUColorer gtuColorer, final OTSNetwork network) throws RemoteException
155 {
156 super(simulator, otsModel);
157
158
159
160 this.animationPanel = new AutoAnimationPanel(extent, size, simulator, network);
161 this.animationPanel.showGrid(false);
162 this.borderPanel = new JPanel(new BorderLayout());
163 this.borderPanel.add(this.animationPanel, BorderLayout.CENTER);
164 getTabbedPane().addTab(0, "animation", this.borderPanel);
165 getTabbedPane().setSelectedIndex(0);
166
167
168 this.gtuColorer = gtuColorer;
169 this.colorControlPanel = new ColorControlPanel(this.gtuColorer);
170 JPanel buttonPanel = new JPanel();
171 buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
172 this.borderPanel.add(buttonPanel, BorderLayout.NORTH);
173 buttonPanel.add(this.colorControlPanel);
174
175
176 this.togglePanel = new JPanel();
177 this.togglePanel.setLayout(new BoxLayout(this.togglePanel, BoxLayout.Y_AXIS));
178 this.borderPanel.add(this.togglePanel, BorderLayout.WEST);
179
180
181 buttonPanel.add(new JLabel(" "));
182 buttonPanel.add(makeButton("allButton", "/Expand.png", "ZoomAll", "Zoom whole network", true));
183 buttonPanel.add(makeButton("homeButton", "/Home.png", "Home", "Zoom to original extent", true));
184 buttonPanel.add(makeButton("gridButton", "/Grid.png", "Grid", "Toggle grid on/off", true));
185 buttonPanel.add(new JLabel(" "));
186
187
188 JPanel infoTextPanel = new JPanel();
189 buttonPanel.add(infoTextPanel);
190 infoTextPanel.setMinimumSize(new Dimension(250, 20));
191 infoTextPanel.setPreferredSize(new Dimension(250, 20));
192 infoTextPanel.setLayout(new BoxLayout(infoTextPanel, BoxLayout.Y_AXIS));
193 this.coordinateField = new JLabel("Mouse: ");
194 this.coordinateField.setMinimumSize(new Dimension(250, 10));
195 this.coordinateField.setPreferredSize(new Dimension(250, 10));
196 infoTextPanel.add(this.coordinateField);
197
198 JPanel gtuPanel = new JPanel();
199 gtuPanel.setAlignmentX(0.0f);
200 gtuPanel.setLayout(new BoxLayout(gtuPanel, BoxLayout.X_AXIS));
201 gtuPanel.setMinimumSize(new Dimension(250, 10));
202 gtuPanel.setPreferredSize(new Dimension(250, 10));
203 infoTextPanel.add(gtuPanel);
204 if (null != network)
205 {
206 network.addListener(this, Network.GTU_ADD_EVENT);
207 network.addListener(this, Network.GTU_REMOVE_EVENT);
208 }
209
210
211 class AppearanceTextField extends JTextField implements AppearanceControl
212 {
213 private static final long serialVersionUID = 20180430L;
214
215
216 @Override
217 public String toString()
218 {
219 return "AppearanceTextField []";
220 }
221 }
222 this.autoPanField = new AppearanceTextField();
223 this.autoPanField.setMaximumSize(new Dimension(100, 20));
224 this.autoPanField.setVisible(false);
225 this.autoPanField.addActionListener(new ActionListener()
226 {
227 @SuppressWarnings("synthetic-access")
228 @Override
229 public void actionPerformed(final ActionEvent e)
230 {
231 OTSAnimationPanel.this.animationPanel.repaint();
232 }
233 });
234 this.autoPanToggle = new JCheckBox();
235 this.autoPanToggle.setToolTipText("Pan to GTU");
236 this.autoPanToggle.addActionListener(new ActionListener()
237 {
238 @SuppressWarnings("synthetic-access")
239 @Override
240 public void actionPerformed(final ActionEvent e)
241 {
242 OTSAnimationPanel.this.autoPan = !OTSAnimationPanel.this.autoPanField.isVisible();
243 OTSAnimationPanel.this.autoPanField.setVisible(OTSAnimationPanel.this.autoPan);
244 if (OTSAnimationPanel.this.autoPan)
245 {
246 OTSAnimationPanel.this.autoPanField.requestFocusInWindow();
247 OTSAnimationPanel.this.autoPanField.selectAll();
248 }
249 gtuPanel.revalidate();
250 }
251 });
252 gtuPanel.add(this.autoPanToggle);
253 gtuPanel.add(this.autoPanField);
254
255 this.gtuCountField = new JLabel("0 GTU's");
256 this.gtuCount = null == network ? 0 : network.getGTUs().size();
257 gtuPanel.add(this.gtuCountField);
258 setGtuCountText();
259
260
261 this.animationPanel.notify(new Event(SimulatorInterface.START_REPLICATION_EVENT, simulator, null));
262
263
264 this.animationPanel.setShowToolTip(false);
265
266
267 new UpdateTimer().start();
268
269
270 installWindowCloseHandler();
271
272 }
273
274
275
276
277
278
279
280
281
282
283 private JButton makeButton(final String name, final String iconPath, final String actionCommand, final String toolTipText,
284 final boolean enabled)
285 {
286
287 JButton result = new JButton(OTSControlPanel.loadIcon(iconPath));
288 result.setPreferredSize(new Dimension(34, 32));
289 result.setName(name);
290 result.setEnabled(enabled);
291 result.setActionCommand(actionCommand);
292 result.setToolTipText(toolTipText);
293 result.addActionListener(this);
294 this.buttons.add(result);
295 return result;
296 }
297
298
299
300
301
302
303
304
305
306
307
308
309 public final void addToggleAnimationButtonIcon(final String name, final Class<? extends Locatable> locatableClass,
310 final String iconPath, final String toolTipText, final boolean initiallyVisible, final boolean idButton)
311 {
312 JToggleButton button;
313 Icon icon = OTSControlPanel.loadIcon(iconPath);
314 Icon unIcon = OTSControlPanel.loadGrayscaleIcon(iconPath);
315 button = new JCheckBox();
316 button.setSelectedIcon(icon);
317 button.setIcon(unIcon);
318 button.setPreferredSize(new Dimension(32, 28));
319 button.setName(name);
320 button.setEnabled(true);
321 button.setSelected(initiallyVisible);
322 button.setActionCommand(name);
323 button.setToolTipText(toolTipText);
324 button.addActionListener(this);
325
326
327 if (idButton && this.togglePanel.getComponentCount() > 0)
328 {
329 JPanel lastToggleBox = (JPanel) this.togglePanel.getComponent(this.togglePanel.getComponentCount() - 1);
330 lastToggleBox.add(button);
331 }
332 else
333 {
334 JPanel toggleBox = new JPanel();
335 toggleBox.setLayout(new BoxLayout(toggleBox, BoxLayout.X_AXIS));
336 toggleBox.add(button);
337 this.togglePanel.add(toggleBox);
338 toggleBox.setAlignmentX(Component.LEFT_ALIGNMENT);
339 }
340
341 if (initiallyVisible)
342 {
343 this.animationPanel.showClass(locatableClass);
344 }
345 else
346 {
347 this.animationPanel.hideClass(locatableClass);
348 }
349 this.toggleLocatableMap.put(name, locatableClass);
350 this.toggleButtons.put(locatableClass, button);
351 }
352
353
354
355
356
357
358
359
360 public final void addToggleAnimationButtonText(final String name, final Class<? extends Locatable> locatableClass,
361 final String toolTipText, final boolean initiallyVisible)
362 {
363 JToggleButton button;
364 button = new JCheckBox(name);
365 button.setName(name);
366 button.setEnabled(true);
367 button.setSelected(initiallyVisible);
368 button.setActionCommand(name);
369 button.setToolTipText(toolTipText);
370 button.addActionListener(this);
371
372 JPanel toggleBox = new JPanel();
373 toggleBox.setLayout(new BoxLayout(toggleBox, BoxLayout.X_AXIS));
374 toggleBox.add(button);
375 this.togglePanel.add(toggleBox);
376 toggleBox.setAlignmentX(Component.LEFT_ALIGNMENT);
377
378 if (initiallyVisible)
379 {
380 this.animationPanel.showClass(locatableClass);
381 }
382 else
383 {
384 this.animationPanel.hideClass(locatableClass);
385 }
386 this.toggleLocatableMap.put(name, locatableClass);
387 this.toggleButtons.put(locatableClass, button);
388 }
389
390
391
392
393
394 public final void addToggleText(final String text)
395 {
396 JPanel textBox = new JPanel();
397 textBox.setLayout(new BoxLayout(textBox, BoxLayout.X_AXIS));
398 textBox.add(new JLabel(text));
399 this.togglePanel.add(textBox);
400 textBox.setAlignmentX(Component.LEFT_ALIGNMENT);
401 }
402
403
404
405
406
407
408
409 public final void addAllToggleGISButtonText(final String header, final GisRenderable2D gisMap, final String toolTipText)
410 {
411 addToggleText(" ");
412 addToggleText(header);
413 try
414 {
415 for (String layerName : gisMap.getMap().getLayerMap().keySet())
416 {
417 addToggleGISButtonText(layerName, layerName, gisMap, toolTipText);
418 }
419 }
420 catch (RemoteException exception)
421 {
422 exception.printStackTrace();
423 }
424 }
425
426
427
428
429
430
431
432
433 public final void addToggleGISButtonText(final String layerName, final String displayName, final GisRenderable2D gisMap,
434 final String toolTipText)
435 {
436 JToggleButton button;
437 button = new JCheckBox(displayName);
438 button.setName(layerName);
439 button.setEnabled(true);
440 button.setSelected(true);
441 button.setActionCommand(layerName);
442 button.setToolTipText(toolTipText);
443 button.addActionListener(this);
444
445 JPanel toggleBox = new JPanel();
446 toggleBox.setLayout(new BoxLayout(toggleBox, BoxLayout.X_AXIS));
447 toggleBox.add(button);
448 this.togglePanel.add(toggleBox);
449 toggleBox.setAlignmentX(Component.LEFT_ALIGNMENT);
450
451 this.toggleGISMap.put(layerName, gisMap.getMap());
452 this.toggleGISButtons.put(layerName, button);
453 }
454
455
456
457
458
459 public final void showGISLayer(final String layerName)
460 {
461 MapInterface gisMap = this.toggleGISMap.get(layerName);
462 if (gisMap != null)
463 {
464 try
465 {
466 gisMap.showLayer(layerName);
467 this.toggleGISButtons.get(layerName).setSelected(true);
468 this.animationPanel.repaint();
469 }
470 catch (RemoteException exception)
471 {
472 exception.printStackTrace();
473 }
474 }
475 }
476
477
478
479
480
481 public final void hideGISLayer(final String layerName)
482 {
483 MapInterface gisMap = this.toggleGISMap.get(layerName);
484 if (gisMap != null)
485 {
486 try
487 {
488 gisMap.hideLayer(layerName);
489 this.toggleGISButtons.get(layerName).setSelected(false);
490 this.animationPanel.repaint();
491 }
492 catch (RemoteException exception)
493 {
494 exception.printStackTrace();
495 }
496 }
497 }
498
499
500
501
502
503 public final void toggleGISLayer(final String layerName)
504 {
505 MapInterface gisMap = this.toggleGISMap.get(layerName);
506 if (gisMap != null)
507 {
508 try
509 {
510 if (gisMap.getVisibleLayers().contains(gisMap.getLayerMap().get(layerName)))
511 {
512 gisMap.hideLayer(layerName);
513 this.toggleGISButtons.get(layerName).setSelected(false);
514 }
515 else
516 {
517 gisMap.showLayer(layerName);
518 this.toggleGISButtons.get(layerName).setSelected(true);
519 }
520 this.animationPanel.repaint();
521 }
522 catch (RemoteException exception)
523 {
524 exception.printStackTrace();
525 }
526 }
527 }
528
529
530 @Override
531 public final void actionPerformed(final ActionEvent actionEvent)
532 {
533 String actionCommand = actionEvent.getActionCommand();
534
535 try
536 {
537 if (actionCommand.equals("Home"))
538 {
539 this.animationPanel.home();
540 }
541 if (actionCommand.equals("ZoomAll"))
542 {
543 this.animationPanel.zoomAll();
544 }
545 if (actionCommand.equals("Grid"))
546 {
547 this.animationPanel.showGrid(!this.animationPanel.isShowGrid());
548 }
549
550 if (this.toggleLocatableMap.containsKey(actionCommand))
551 {
552 Class<? extends Locatable> locatableClass = this.toggleLocatableMap.get(actionCommand);
553 this.animationPanel.toggleClass(locatableClass);
554 this.togglePanel.repaint();
555 }
556
557 if (this.toggleGISMap.containsKey(actionCommand))
558 {
559 this.toggleGISLayer(actionCommand);
560 this.togglePanel.repaint();
561 }
562 }
563 catch (Exception exception)
564 {
565 exception.printStackTrace();
566 }
567 }
568
569
570
571
572
573 public final AnimationPanel getAnimationPanel()
574 {
575 return this.animationPanel;
576 }
577
578
579
580
581
582 public JPanel getDemoPanel()
583 {
584 if (this.demoPanel == null)
585 {
586 this.demoPanel = new JPanel();
587 this.demoPanel.setLayout(new BoxLayout(this.demoPanel, BoxLayout.Y_AXIS));
588 this.demoPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
589 this.demoPanel.setPreferredSize(new Dimension(300, 300));
590 getAnimationPanel().getParent().add(this.demoPanel, BorderLayout.EAST);
591 this.demoPanel.addContainerListener(new ContainerListener()
592 {
593 @Override
594 public void componentAdded(final ContainerEvent e)
595 {
596 try
597 {
598
599 }
600 catch (NullPointerException exception)
601 {
602
603 }
604 }
605
606 @Override
607 public void componentRemoved(final ContainerEvent e)
608 {
609
610 }
611 });
612 }
613 return this.demoPanel;
614 }
615
616
617
618
619
620 public final void updateAnimationClassCheckBox(final Class<? extends Locatable> locatableClass)
621 {
622 JToggleButton button = this.toggleButtons.get(locatableClass);
623 if (button == null)
624 {
625 return;
626 }
627 button.setSelected(getAnimationPanel().isShowClass(locatableClass));
628 }
629
630
631
632
633 protected final void updateWorldCoordinate()
634 {
635 String worldPoint = "(x=" + FORMATTER.format(this.animationPanel.getWorldCoordinate().getX()) + " ; y="
636 + FORMATTER.format(this.animationPanel.getWorldCoordinate().getY()) + ")";
637 this.coordinateField.setText("Mouse: " + worldPoint);
638 int requiredWidth = this.coordinateField.getGraphics().getFontMetrics().stringWidth(this.coordinateField.getText());
639 if (this.coordinateField.getPreferredSize().width < requiredWidth)
640 {
641 Dimension requiredSize = new Dimension(requiredWidth, this.coordinateField.getPreferredSize().height);
642 this.coordinateField.setPreferredSize(requiredSize);
643 this.coordinateField.setMinimumSize(requiredSize);
644 Container parent = this.coordinateField.getParent();
645 parent.setPreferredSize(requiredSize);
646 parent.setMinimumSize(requiredSize);
647
648 parent.revalidate();
649 }
650 this.coordinateField.repaint();
651 }
652
653
654
655
656
657
658 public final GTUColorer getGTUColorer()
659 {
660 return this.gtuColorer;
661 }
662
663
664
665
666
667
668 public final ColorControlPanel getColorControlPanel()
669 {
670 return this.colorControlPanel;
671 }
672
673
674
675
676 public final void installWindowCloseHandler()
677 {
678 if (this.closeHandlerRegistered)
679 {
680 return;
681 }
682
683
684 new DisposeOnCloseThread(this).start();
685 }
686
687
688 protected class DisposeOnCloseThread extends Thread
689 {
690
691 private OTSAnimationPanel panel;
692
693
694
695
696 public DisposeOnCloseThread(final OTSAnimationPanel panel)
697 {
698 super();
699 this.panel = panel;
700 }
701
702
703 @Override
704 public final void run()
705 {
706 Container root = this.panel;
707 while (!(root instanceof JFrame))
708 {
709 try
710 {
711 Thread.sleep(10);
712 }
713 catch (InterruptedException exception)
714 {
715
716 }
717
718
719 root = this.panel;
720 while (null != root.getParent() && !(root instanceof JFrame))
721 {
722 root = root.getParent();
723 }
724 }
725 JFrame frame = (JFrame) root;
726 frame.addWindowListener(this.panel);
727 this.panel.closeHandlerRegistered = true;
728 }
729
730
731 @Override
732 public final String toString()
733 {
734 return "DisposeOnCloseThread of OTSAnimationPanel [panel=" + this.panel + "]";
735 }
736 }
737
738
739 @Override
740 public void windowOpened(final WindowEvent e)
741 {
742
743 }
744
745
746 @Override
747 public final void windowClosing(final WindowEvent e)
748 {
749
750 }
751
752
753 @Override
754 public final void windowClosed(final WindowEvent e)
755 {
756 this.windowExited = true;
757 }
758
759
760 @Override
761 public final void windowIconified(final WindowEvent e)
762 {
763
764 }
765
766
767 @Override
768 public final void windowDeiconified(final WindowEvent e)
769 {
770
771 }
772
773
774 @Override
775 public final void windowActivated(final WindowEvent e)
776 {
777
778 }
779
780
781 @Override
782 public final void windowDeactivated(final WindowEvent e)
783 {
784
785 }
786
787
788 @Override
789 public void notify(final EventInterface event) throws RemoteException
790 {
791 if (event.getType().equals(Network.GTU_ADD_EVENT))
792 {
793 this.gtuCount++;
794 setGtuCountText();
795 }
796 else if (event.getType().equals(Network.GTU_REMOVE_EVENT))
797 {
798 this.gtuCount--;
799 setGtuCountText();
800 }
801 }
802
803
804
805
806 private void setGtuCountText()
807 {
808 this.gtuCountField.setText(this.gtuCount + " GTU's");
809 }
810
811
812
813
814 protected class UpdateTimer extends Thread
815 {
816
817 @Override
818 public final void run()
819 {
820 while (!OTSAnimationPanel.this.windowExited)
821 {
822 if (OTSAnimationPanel.this.isShowing())
823 {
824 OTSAnimationPanel.this.updateWorldCoordinate();
825 }
826 try
827 {
828 Thread.sleep(50);
829 }
830 catch (InterruptedException exception)
831 {
832
833 }
834 }
835 }
836
837
838 @Override
839 public final String toString()
840 {
841 return "UpdateTimer thread for OTSAnimationPanel";
842 }
843
844 }
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859 private class AutoAnimationPanel extends AnimationPanel
860 {
861
862
863 private static final long serialVersionUID = 20180430L;
864
865
866 private final OTSNetwork network;
867
868
869 private GTU lastGtu;
870
871
872
873
874
875
876
877
878
879 AutoAnimationPanel(final Rectangle2D extent, final Dimension size, final SimulatorInterface<?, ?, ?> simulator,
880 final OTSNetwork network) throws RemoteException
881 {
882 super(extent, size, simulator);
883 this.network = network;
884 MouseListener[] listeners = getMouseListeners();
885 for (MouseListener listener : listeners)
886 {
887 removeMouseListener(listener);
888 }
889 this.addMouseListener(new MouseAdapter()
890 {
891
892 @SuppressWarnings("synthetic-access")
893 @Override
894 public void mouseClicked(final MouseEvent e)
895 {
896 if (e.isControlDown())
897 {
898 GTU gtu = getSelectedGTU(e.getPoint());
899 if (gtu != null)
900 {
901 OTSAnimationPanel.this.autoPanField.setText(gtu.getId());
902 OTSAnimationPanel.this.autoPanField.setVisible(true);
903 OTSAnimationPanel.this.autoPanToggle.setSelected(true);
904 OTSAnimationPanel.this.autoPanToggle.getParent().validate();
905 OTSAnimationPanel.this.autoPan = true;
906 e.consume();
907 }
908 }
909 e.consume();
910 }
911 });
912 for (MouseListener listener : listeners)
913 {
914 addMouseListener(listener);
915 }
916
917 MouseWheelListener[] wheelListeners = getMouseWheelListeners();
918 for (MouseWheelListener wheelListener : wheelListeners)
919 {
920 removeMouseWheelListener(wheelListener);
921 }
922 this.addMouseWheelListener(new InputListener(this)
923 {
924
925 @Override
926 public void mouseWheelMoved(final MouseWheelEvent e)
927 {
928 if (e.isShiftDown())
929 {
930 int amount = e.getUnitsToScroll();
931 if (amount > 0)
932 {
933 zoomVertical(GridPanel.ZOOMFACTOR, e.getX(), e.getY());
934 }
935 else
936 {
937 zoomVertical(1.0 / GridPanel.ZOOMFACTOR, e.getX(), e.getY());
938 }
939 }
940 else if (e.isAltDown())
941 {
942 int amount = e.getUnitsToScroll();
943 if (amount > 0)
944 {
945 zoomHorizontal(GridPanel.ZOOMFACTOR, e.getX(), e.getY());
946 }
947 else
948 {
949 zoomHorizontal(1.0 / GridPanel.ZOOMFACTOR, e.getX(), e.getY());
950 }
951 }
952 else
953 {
954 super.mouseWheelMoved(e);
955 }
956 }
957 });
958 }
959
960
961
962
963
964
965
966 final synchronized void zoomVertical(final double factor, final int mouseX, final int mouseY)
967 {
968
969 this.zoom(factor, mouseX, mouseY);
970
971
972
973
974
975
976
977
978
979 }
980
981
982
983
984
985
986
987 final synchronized void zoomHorizontal(final double factor, final int mouseX, final int mouseY)
988 {
989 this.zoom(factor, mouseX, mouseY);
990
991
992
993
994
995
996
997
998
999 }
1000
1001
1002
1003
1004
1005
1006 @SuppressWarnings("synthetic-access")
1007 protected GTU getSelectedGTU(final Point2D mousePoint)
1008 {
1009 List<GTU> targets = new ArrayList<>();
1010 Point2D point = Renderable2DInterface.Util.getWorldCoordinates(mousePoint,
1011 OTSAnimationPanel.this.animationPanel.getExtent(), OTSAnimationPanel.this.animationPanel.getSize());
1012 for (Renderable2DInterface<?> renderable : OTSAnimationPanel.this.animationPanel.getElements())
1013 {
1014 if (OTSAnimationPanel.this.animationPanel.isShowElement(renderable) && renderable.contains(point,
1015 OTSAnimationPanel.this.animationPanel.getExtent(), OTSAnimationPanel.this.animationPanel.getSize()))
1016 {
1017 if (renderable.getSource() instanceof GTU)
1018 {
1019 targets.add((GTU) renderable.getSource());
1020 }
1021 }
1022 }
1023 if (targets.size() == 1)
1024 {
1025 return targets.get(0);
1026 }
1027 return null;
1028 }
1029
1030
1031 @SuppressWarnings("synthetic-access")
1032 @Override
1033 public void paintComponent(final Graphics g)
1034 {
1035 if (OTSAnimationPanel.this.autoPan)
1036 {
1037 String id = OTSAnimationPanel.this.autoPanField.getText();
1038 if (this.lastGtu == null || !this.lastGtu.getId().equals(id) || this.lastGtu.isDestroyed())
1039 {
1040 this.lastGtu = this.network.getGTU(id);
1041 }
1042 DirectedPoint point;
1043 try
1044 {
1045 point = this.lastGtu != null ? this.lastGtu.getLocation() : null;
1046 }
1047 catch (RemoteException exception)
1048 {
1049 System.err.println("Could not pan to GTU location.");
1050 return;
1051 }
1052 if (point != null)
1053 {
1054 double w = this.extent.getWidth();
1055 double h = this.extent.getHeight();
1056 this.extent = new Rectangle2D.Double(point.getX() - w / 2, point.getY() - h / 2, w, h);
1057 }
1058 }
1059 super.paintComponent(g);
1060 }
1061
1062
1063 @Override
1064 public String toString()
1065 {
1066 return "AutoAnimationPanel [network=" + this.network + ", lastGtu=" + this.lastGtu + "]";
1067 }
1068 }
1069
1070 }