TimePanel.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. package ui.view;
  2. import ui.controller.Control;
  3. import ui.controller.SingletonControl;
  4. import ui.model.Model;
  5. import javax.swing.*;
  6. import javax.swing.event.ChangeEvent;
  7. import javax.swing.event.ChangeListener;
  8. import javax.swing.plaf.basic.BasicSliderUI;
  9. import java.awt.*;
  10. import java.awt.event.*;
  11. import java.util.Hashtable;
  12. /**
  13. * This Class represents a Panel where the User can start and stop the
  14. * Simulation. He Can also reset the Simulation and click through every
  15. * Iteration.
  16. *
  17. * @author Gruppe14
  18. */
  19. public class TimePanel extends JPanel implements ActionListener{
  20. private static final long serialVersionUID = 1L;
  21. private static final int MAX_ITERATIONS=100000;
  22. /*
  23. * variable for calculating the performance
  24. */
  25. //private long performanceTime;
  26. final JButton playBtn = new JButton();
  27. final JButton timeResetBtn = new JButton();
  28. final JButton timeForwardBtn = new JButton();
  29. final JButton timeBackwardBtn = new JButton();
  30. JTextField iterationsField;
  31. final JLabel iterationsLabel=new JLabel(" Iterations ");
  32. private final JPanel btnAndSpeedPanel = new JPanel();
  33. private final JPanel speedPanel = new JPanel();
  34. private final JPanel timeBtnPanel = new JPanel();
  35. private final JPanel iterationsPanel=new JPanel();
  36. private final JPanel timePanel=new JPanel();
  37. private LabelHint iterationsLblHint;
  38. JSlider timeSlider = new JSlider() {
  39. /**
  40. *
  41. */
  42. private static final long serialVersionUID = 1L;
  43. {
  44. // Make the slider jump to mouse position on left click
  45. MouseListener[] listeners = getMouseListeners();
  46. for (MouseListener l : listeners)
  47. removeMouseListener(l); // remove UI-installed TrackListener
  48. final BasicSliderUI ui = (BasicSliderUI) getUI();
  49. BasicSliderUI.TrackListener tl = ui.new TrackListener() {
  50. // this is where we jump to absolute value of click
  51. @Override
  52. public void mouseClicked(MouseEvent e) {
  53. Point p = e.getPoint();
  54. int value = ui.valueForXPosition(p.x);
  55. setValue(value);
  56. }
  57. // disable check that will invoke scrollDueToClickInTrack
  58. @Override
  59. public boolean shouldScroll(int dir) {
  60. return false;
  61. }
  62. };
  63. addMouseListener(tl);
  64. }
  65. };
  66. //private Model model;
  67. private Control controller;
  68. private int dragResetIteration = 0;
  69. private JLabel simSpeedLabel = new JLabel("Speed:");
  70. private JSlider speedSlider = new JSlider();
  71. private Timer timer;
  72. private boolean running = false;
  73. private GUI parentGUI;
  74. /**
  75. * Constructor.
  76. *
  77. * @param mod
  78. * the Model
  79. * @param cont
  80. * the Controller
  81. */
  82. public TimePanel(GUI parent, Control cont) {
  83. super();
  84. this.controller = cont;
  85. this.parentGUI=parent;
  86. // One Iteration
  87. timer = new Timer(0, new ActionListener() {//TODO: Merge all these damned listeners.
  88. @Override
  89. public void actionPerformed(ActionEvent ae) {
  90. timeSlider.setValue(timeSlider.getValue() + 1);
  91. controller.setCurIteration(timeSlider.getValue());
  92. timer.setDelay(cont.getModel().getTimerSpeed());
  93. if (timeSlider.getValue() >= cont.getModel().getIterations() - 1) {
  94. /*/calc and print performance
  95. performanceTime = System.nanoTime()-performanceTime;
  96. System.out.println(performanceTime/1000000000 + " Sekunden "
  97. + (performanceTime%1000000000)/1000000 + " Millisekunden "
  98. + (performanceTime%1000000)/1000 + " Mikrosekunden ");
  99. //*/
  100. running = false;
  101. playBtn.setIcon(new ImageIcon(Util.loadImage(this, "/Button_Images/play.png", 30, 30, Image.SCALE_SMOOTH)));
  102. timer.stop();
  103. }
  104. }
  105. });
  106. // Time Slider. Panels and Buttons
  107. this.setLayout(new BorderLayout(0, 0));
  108. this.setBorder(null);
  109. // Slider
  110. timeSlider.setPaintTicks(true);
  111. timeSlider.setPaintLabels(true);
  112. timeSlider.setMajorTickSpacing((int)Math.ceil(((double)cont.getModel().getIterations())/20));
  113. timeSlider.setMinorTickSpacing((int)Math.ceil(((double)cont.getModel().getIterations())/100));
  114. timeSlider.setToolTipText(Languages.getLanguage()[93]);
  115. timeSlider.setMaximum(cont.getModel().getIterations() - 1);
  116. timeSlider.setValue(0);
  117. timeSlider.addChangeListener(changeEvent -> controller.setCurIteration(timeSlider.getValue()));
  118. timeSlider.addMouseListener(new MouseAdapter() {
  119. @Override
  120. public void mousePressed(MouseEvent e) {
  121. dragResetIteration = cont.getModel().getCurIteration();
  122. }
  123. });
  124. timeSlider.addMouseMotionListener(new MouseAdapter() {
  125. @Override
  126. public void mouseDragged(MouseEvent e) {
  127. if (dragResetIteration != cont.getModel().getCurIteration()) {
  128. controller.resetSimulation();
  129. if (running) {
  130. playBtn.doClick();
  131. }
  132. }
  133. }
  134. });
  135. // Panel
  136. timeBtnPanel.setBorder(null);
  137. timeBtnPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
  138. // Buttons
  139. playBtn.setToolTipText(Languages.getLanguage()[89]);
  140. playBtn.setContentAreaFilled(false);
  141. playBtn.setBorderPainted(false);
  142. playBtn.setBorder(null);
  143. playBtn.setIcon(new ImageIcon(Util.loadImage(this, "/Button_Images/play.png",30,30)));
  144. playBtn.addActionListener(new ActionListener() {
  145. @Override
  146. public void actionPerformed(ActionEvent e) {
  147. if(cont.getModel().getCurIteration()==cont.getModel().getIterations()-1)timeSlider.setValue(timeSlider.getMinimum());
  148. running = !running;
  149. controller.setIsSimRunning(running);
  150. if (running) {
  151. timer.setDelay(cont.getModel().getTimerSpeed());
  152. /*
  153. * start the Performance Test
  154. * /
  155. performanceTime = System.nanoTime();
  156. timeSlider.setValue(0);
  157. timer.setDelay(0);
  158. speedSlider.setValue(10);
  159. timeSlider.setValue(0);
  160. //*/
  161. timer.start();
  162. playBtn.setIcon(new ImageIcon(Util.loadImage(this, "/Button_Images/pause.png", 30, 30, Image.SCALE_SMOOTH)));
  163. } else {
  164. timer.stop();
  165. playBtn.setIcon(new ImageIcon(Util.loadImage(this, "/Button_Images/play.png", 30, 30, Image.SCALE_SMOOTH)));
  166. }
  167. }
  168. });
  169. timeResetBtn.setToolTipText(Languages.getLanguage()[90]);
  170. timeResetBtn.setContentAreaFilled(false);
  171. timeResetBtn.setBorder(null);
  172. timeResetBtn.setIcon(new ImageIcon(Util.loadImage(this, "/Button_Images/reset.png", 30, 30)));
  173. timeResetBtn.addActionListener(new ActionListener() {
  174. public void actionPerformed(ActionEvent ae) {
  175. timeSlider.setValue(timeSlider.getMinimum());
  176. controller.setCurIteration(timeSlider.getValue());
  177. // controller.calculateStateForCurrentTimeStep();
  178. controller.resetSimulation();
  179. if (running) {
  180. playBtn.doClick();
  181. }
  182. }
  183. });
  184. timeForwardBtn.setToolTipText(Languages.getLanguage()[91]);
  185. timeForwardBtn.setContentAreaFilled(false);
  186. timeForwardBtn.setBorder(null);
  187. timeForwardBtn.setIcon(new ImageIcon(Util.loadImage(this,"/Button_Images/forward.png",30,30)));
  188. timeForwardBtn.addActionListener(new ActionListener() {
  189. public void actionPerformed(ActionEvent ae) {
  190. if (!cont.getModel().getIsSimRunning()) {
  191. controller.setIsSimRunning(true);
  192. }
  193. timeSlider.setValue(timeSlider.getValue() + 1);
  194. controller.setCurIteration(timeSlider.getValue());
  195. }
  196. });
  197. timeBackwardBtn.setToolTipText(Languages.getLanguage()[92]);
  198. timeBackwardBtn.setBorder(null);
  199. timeBackwardBtn.setIcon(new ImageIcon(Util.loadImage(this, "/Button_Images/backward.png", 30,30)));
  200. timeBackwardBtn.addActionListener(new ActionListener() {
  201. public void actionPerformed(ActionEvent ae) {
  202. timeSlider.setValue(timeSlider.getValue() - 1);
  203. controller.setCurIteration(timeSlider.getValue());
  204. }
  205. });
  206. timeBtnPanel.add(playBtn);
  207. timeBtnPanel.add(Box.createRigidArea(new Dimension(10, 0)));
  208. timeBtnPanel.add(timeResetBtn);
  209. timeBtnPanel.add(Box.createRigidArea(new Dimension(10, 0)));
  210. timeBtnPanel.add(timeForwardBtn);
  211. // Speed Panel
  212. speedPanel.add(simSpeedLabel);
  213. speedPanel.add(speedSlider);
  214. speedSlider.setPaintTicks(true);
  215. speedSlider.setPaintLabels(true);
  216. speedSlider.setMaximum(6);
  217. speedSlider.setMinimum(0);
  218. speedSlider.setValue(1);
  219. speedSlider.setPaintLabels(true);
  220. Hashtable<Integer, JLabel> table = new Hashtable<Integer, JLabel>();
  221. table.put (0, new JLabel("1x"));
  222. table.put (1, new JLabel("2x"));
  223. table.put (2, new JLabel("4x"));
  224. table.put (3, new JLabel("8x"));
  225. table.put (4, new JLabel("16x"));
  226. table.put (5, new JLabel("32x"));
  227. table.put (6, new JLabel("64x"));
  228. speedSlider.setLabelTable(table);
  229. speedSlider.addChangeListener(new ChangeListener() {
  230. @Override
  231. public void stateChanged(ChangeEvent e) {
  232. /**
  233. * Shifting Powers of two:
  234. * e.g. 1<<0 -> 1 step per Second
  235. * 1<<3 -> 8 steps per Second
  236. * and so on,
  237. */
  238. int calculationsPerSecond = 1 << speedSlider.getValue();
  239. controller.setTimerSpeed(1024 >> speedSlider.getValue());
  240. speedSlider.setToolTipText("Speed: " + calculationsPerSecond + " Calculations per Second.");
  241. }
  242. });
  243. speedSlider.setToolTipText("Change the Number of Calculations per Secons");
  244. // Buttons and Speed Panel
  245. btnAndSpeedPanel.setLayout(new BorderLayout(0, 0));
  246. btnAndSpeedPanel.setBorder(null);
  247. btnAndSpeedPanel.add(timeBtnPanel, BorderLayout.NORTH);
  248. btnAndSpeedPanel.add(speedPanel, BorderLayout.CENTER);
  249. iterationsPanel.setLayout(new GridLayout(3,1));
  250. iterationsPanel.add(iterationsLabel, BorderLayout.NORTH);
  251. iterationsLblHint=new LabelHint(iterationsLabel);
  252. iterationsField=new JTextField(6);//Considering hundreds of thousands in an extreme case
  253. iterationsField.setText(""+cont.getModel().getIterations());
  254. iterationsField.addActionListener(this);
  255. iterationsField.addCaretListener((e)->
  256. {
  257. try{
  258. int a=Integer.parseInt(iterationsField.getText());
  259. iterationsField.setBackground(Color.WHITE);//red stings
  260. if(
  261. a!=
  262. SingletonControl
  263. .getInstance()
  264. .getControl()
  265. .getModel()
  266. .getIterations()
  267. )iterationsLblHint.go("Press ENTER");
  268. }catch(NumberFormatException n){
  269. iterationsLblHint.go("Invalid");
  270. iterationsField.setBackground(GUI.PALE_RED);//red stings
  271. }
  272. }
  273. );
  274. iterationsPanel.add(iterationsField);
  275. iterationsPanel.add(new JLabel(), BorderLayout.SOUTH);
  276. timePanel.setLayout(new BorderLayout());
  277. timePanel.add(iterationsPanel, BorderLayout.WEST);
  278. timePanel.add(timeSlider, BorderLayout.CENTER);
  279. this.add(btnAndSpeedPanel, BorderLayout.WEST);
  280. add(timePanel);
  281. //Disable Keys
  282. timeSlider.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "UP_ARROW");
  283. timeSlider.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "DOWN_ARROW");
  284. timeSlider.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0, false), "PAGE_DOWN");
  285. timeSlider.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, 0, false), "PAGE_UP");
  286. timeSlider.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_END, 0, false), "END");
  287. timeSlider.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0, false), "HOME");
  288. // Left arrow Key
  289. timeSlider.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "LEFT_ARROW");
  290. timeSlider.getActionMap().put("LEFT_ARROW", new AbstractAction() {
  291. private static final long serialVersionUID = 1L;
  292. @Override
  293. public void actionPerformed(ActionEvent e) {
  294. timeSlider.setValue(timeSlider.getValue() - 1);
  295. controller.resetSimulation();
  296. }
  297. });
  298. //Right arrow Key
  299. timeSlider.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "Right_ARROW");
  300. timeSlider.getActionMap().put("Right_ARROW", new AbstractAction() {
  301. private static final long serialVersionUID = 1L;
  302. @Override
  303. public void actionPerformed(ActionEvent e) {
  304. if (!cont.getModel().getIsSimRunning()) {
  305. controller.setIsSimRunning(true);
  306. }
  307. timeSlider.setValue(timeSlider.getValue() + 1);
  308. }
  309. });
  310. }
  311. /**
  312. * Returns the TimeSlider.
  313. *
  314. * @return the TimeSlider
  315. */
  316. public JSlider getTimeSlider() {
  317. return timeSlider;
  318. }
  319. @Override
  320. public void actionPerformed(ActionEvent arg0) {//I dislike anon classes.
  321. try{
  322. int iterations=Integer.parseInt(iterationsField.getText());
  323. iterationsLblHint.reset();
  324. boolean resetField=true;
  325. if(iterations<1)iterations=1;
  326. else if(iterations>MAX_ITERATIONS)iterations=MAX_ITERATIONS;
  327. else resetField=false;
  328. if(resetField)iterationsField.setText(""+iterations);
  329. controller.getModel().setIterations(Integer.parseInt(iterationsField.getText()));
  330. timeSlider.setMaximum(controller.getModel().getIterations()-1);
  331. timeSlider.setLabelTable(null);//Otherwise the ticks won't update
  332. timeSlider.setMajorTickSpacing((int)Math.ceil(((double)controller.getModel().getIterations())/20));
  333. timeSlider.setMinorTickSpacing((int)Math.ceil(((double)controller.getModel().getIterations())/100));//Even though the final mark can't actually be reached.
  334. parentGUI.updateIterations();//First one in the chain
  335. }catch(NumberFormatException e){}
  336. }
  337. }