TimePanel.java 14 KB

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