001 package com.croftsoft.apps.cyborg; 002 003 import java.awt.*; 004 import java.awt.event.*; 005 import java.awt.image.*; 006 import javax.swing.*; 007 import javax.swing.border.*; 008 import javax.swing.event.*; 009 010 import com.croftsoft.core.gui.LogPanel; 011 import com.croftsoft.core.lang.NullArgumentException; 012 import com.croftsoft.core.lang.lifecycle.Initializable; 013 import com.croftsoft.core.lang.lifecycle.Updatable; 014 015 /********************************************************************* 016 * JFrame subclass. 017 * 018 * @version 019 * $Date: 2008/04/19 21:30:59 $ 020 * @since 021 * 2005-08-12 022 * @author 023 * <a href="https://www.croftsoft.com/">David Wallace Croft</a> 024 *********************************************************************/ 025 026 public final class CyborgFrame 027 extends JFrame 028 implements ChangeListener, Initializable, Updatable 029 ////////////////////////////////////////////////////////////////////// 030 ////////////////////////////////////////////////////////////////////// 031 { 032 033 private static final long serialVersionUID = 0L; 034 035 // 036 037 private final CyborgModel cyborgModel; 038 039 private final CyborgController cyborgController; 040 041 // 042 043 private final CyborgAnimator cyborgAnimator; 044 045 private final CyborgComponent cyborgComponent; 046 047 // 048 049 private final SpinnerNumberModel maxSpinnerNumberModel; 050 051 private final LogPanel logPanel; 052 053 private final JCheckBox 054 animateCheckBox, 055 forceLengthCheckBox, 056 realTimeCheckBox; 057 058 private final JSlider 059 gainSlider, 060 offsetSlider; 061 062 // 063 064 private BufferedImage bufferedImage; 065 066 ////////////////////////////////////////////////////////////////////// 067 ////////////////////////////////////////////////////////////////////// 068 069 public CyborgFrame ( 070 CyborgModel cyborgModel, 071 CyborgController cyborgController ) 072 ////////////////////////////////////////////////////////////////////// 073 { 074 super ( CyborgConfig.FRAME_TITLE ); 075 076 NullArgumentException.check ( this.cyborgModel = cyborgModel ); 077 078 NullArgumentException.check ( 079 this.cyborgController = cyborgController ); 080 081 cyborgModel.addChangeListener ( this ); 082 /* 083 JMenuBar jMenuBar = new JMenuBar ( ); 084 085 setJMenuBar ( jMenuBar ); 086 087 jMenuBar.add ( new JMenu ( "Test" ) ); 088 */ 089 gainSlider = new JSlider ( ); 090 091 offsetSlider = new JSlider ( ); 092 093 Container container = getContentPane ( ); 094 095 container.setLayout ( new BorderLayout ( ) ); 096 097 cyborgComponent = new CyborgComponent ( ); 098 099 cyborgAnimator 100 = new CyborgAnimator ( cyborgModel, cyborgComponent ); 101 102 cyborgComponent.setComponentAnimator ( cyborgAnimator ); 103 104 cyborgComponent.addMouseMotionListener ( cyborgController ); 105 106 JPanel westPanel = new JPanel ( new BorderLayout ( ) ); 107 108 container.add ( westPanel, BorderLayout.WEST ); 109 110 JPanel controlPanel = new JPanel ( new BorderLayout ( ) ); 111 112 westPanel.add ( controlPanel, BorderLayout.CENTER ); 113 114 maxSpinnerNumberModel = new SpinnerNumberModel ( 115 ( int ) cyborgModel.getMax ( ), 0, CyborgConfig.FRAME_RATE, 1 ); 116 117 maxSpinnerNumberModel.addChangeListener ( this ); 118 119 controlPanel.setLayout ( 120 new BoxLayout ( controlPanel, BoxLayout.Y_AXIS ) ); 121 122 realTimeCheckBox 123 = new JCheckBox ( CyborgConfig.ACTION_COMMAND_REALTIME ); 124 125 animateCheckBox 126 = new JCheckBox ( CyborgConfig.ACTION_COMMAND_ANIMATE ); 127 128 forceLengthCheckBox 129 = new JCheckBox ( CyborgConfig.ACTION_COMMAND_FORCE_LENGTH ); 130 131 controlPanel.add ( createOptionsPanel ( ) ); 132 133 controlPanel.add ( createJoystickPanel ( ) ); 134 135 controlPanel.add ( createButtonsPanel ( ) ); 136 137 controlPanel.add ( new Box.Filler ( 138 new Dimension ( 0, 0 ), 139 new Dimension ( 0, Integer.MAX_VALUE ), 140 new Dimension ( 0, Integer.MAX_VALUE ) ) ); 141 142 westPanel.add( cyborgComponent, BorderLayout.EAST ); 143 144 JPanel centerPanel = new JPanel ( new BorderLayout ( ) ); 145 146 container.add ( centerPanel, BorderLayout.CENTER ); 147 148 logPanel = new LogPanel ( ); 149 150 centerPanel.add ( createLogPanel ( ), BorderLayout.CENTER ); 151 152 updateView ( ); 153 } 154 155 ////////////////////////////////////////////////////////////////////// 156 ////////////////////////////////////////////////////////////////////// 157 158 public void init ( ) 159 ////////////////////////////////////////////////////////////////////// 160 { 161 cyborgAnimator.init ( ); 162 } 163 164 public void update ( ) 165 ////////////////////////////////////////////////////////////////////// 166 { 167 cyborgComponent.update ( ); 168 } 169 170 public void stateChanged ( ChangeEvent changeEvent ) 171 ////////////////////////////////////////////////////////////////////// 172 { 173 Object source = changeEvent.getSource ( ); 174 175 if ( source == maxSpinnerNumberModel ) 176 { 177 Object value = maxSpinnerNumberModel.getValue ( ); 178 179 cyborgController.changeMax ( ( Integer ) value ); 180 } 181 else if ( source instanceof CyborgModel ) 182 { 183 updateView ( ); 184 } 185 } 186 187 ////////////////////////////////////////////////////////////////////// 188 ////////////////////////////////////////////////////////////////////// 189 190 private JPanel createButtonsPanel ( ) 191 ////////////////////////////////////////////////////////////////////// 192 { 193 JPanel buttonsPanel = new JPanel ( new GridLayout ( 3, 1 ) ); 194 195 final JButton pauseButton 196 = new JButton ( CyborgConfig.ACTION_COMMAND_PAUSE ); 197 198 pauseButton.setActionCommand ( CyborgConfig.ACTION_COMMAND_PAUSE ); 199 200 pauseButton.addActionListener ( cyborgController ); 201 202 pauseButton.addActionListener ( 203 new ActionListener ( ) 204 { 205 public void actionPerformed ( ActionEvent actionEvent ) 206 { 207 String actionCommand = actionEvent.getActionCommand ( ); 208 209 if ( actionCommand.equals ( 210 CyborgConfig.ACTION_COMMAND_PAUSE ) ) 211 { 212 pauseButton.setActionCommand ( 213 CyborgConfig.ACTION_COMMAND_RESUME ); 214 215 pauseButton.setText ( 216 CyborgConfig.ACTION_COMMAND_RESUME ); 217 } 218 else 219 { 220 pauseButton.setActionCommand ( 221 CyborgConfig.ACTION_COMMAND_PAUSE ); 222 223 pauseButton.setText ( 224 CyborgConfig.ACTION_COMMAND_PAUSE ); 225 } 226 } 227 } ); 228 229 buttonsPanel.add ( pauseButton ); 230 231 JButton resetButton 232 = new JButton ( CyborgConfig.ACTION_COMMAND_RESET ); 233 234 resetButton.addActionListener ( 235 new ActionListener ( ) 236 { 237 public void actionPerformed ( ActionEvent actionEvent ) 238 { 239 cyborgModel.reset ( ); 240 } 241 } ); 242 243 buttonsPanel.add ( resetButton ); 244 245 JButton clearButton = new JButton ( "Clear" ); 246 247 clearButton.addActionListener ( 248 new ActionListener ( ) 249 { 250 public void actionPerformed ( ActionEvent actionEvent ) 251 { 252 logPanel.clear ( ); 253 } 254 } ); 255 256 buttonsPanel.add ( clearButton ); 257 258 buttonsPanel.setBorder ( 259 BorderFactory.createEtchedBorder ( EtchedBorder.RAISED ) ); 260 261 return buttonsPanel; 262 } 263 264 private JPanel createJoystickPanel ( ) 265 ////////////////////////////////////////////////////////////////////// 266 { 267 JPanel joystickPanel = new JPanel ( new BorderLayout ( ) ); 268 269 joystickPanel.setPreferredSize ( 270 new Dimension ( 271 CyborgConfig.PLOT_SIZE + 2, 272 0 ) ); 273 274 JPanel joystickPanel1 = new JPanel ( new GridLayout ( 4, 1 ) ); 275 276 joystickPanel.add ( joystickPanel1, BorderLayout.NORTH ); 277 278 final JComboBox jComboBox 279 = new JComboBox ( CyborgConfig.JOYSTICK_TRANSFORM_OPTIONS ); 280 281 jComboBox.addActionListener ( 282 new ActionListener ( ) 283 { 284 public void actionPerformed ( ActionEvent actionEvent ) 285 { 286 cyborgController.changeTransform ( 287 ( String ) jComboBox.getSelectedItem ( ) ); 288 } 289 } ); 290 291 String transform = cyborgModel.getTransform ( ); 292 293 jComboBox.setSelectedItem ( transform ); 294 295 joystickPanel1.add ( jComboBox ); 296 297 JPanel maxPanel = new JPanel ( ); 298 299 maxPanel.add ( new JLabel ( "Max" ) ); 300 301 JSpinner maxSpinner = new JSpinner ( maxSpinnerNumberModel ); 302 303 maxPanel.add ( maxSpinner ); 304 305 joystickPanel1.add ( maxPanel ); 306 307 bufferedImage = new BufferedImage ( 308 CyborgConfig.PLOT_SIZE, 309 CyborgConfig.PLOT_SIZE, 310 BufferedImage.TYPE_INT_RGB ); 311 312 Icon icon = new ImageIcon ( bufferedImage ); 313 314 JButton imageButton = new JButton ( icon ); 315 316 imageButton.setMargin ( new Insets ( 0, 0, 0, 0 ) ); 317 318 imageButton.setEnabled ( false ); 319 320 imageButton.setDisabledIcon ( icon ); 321 322 imageButton.setBorder ( null ); 323 324 joystickPanel.add ( imageButton, BorderLayout.CENTER ); 325 326 JPanel gainPanel = new JPanel ( new BorderLayout ( ) ); 327 328 gainPanel.add ( 329 new JLabel ( "Gain", JLabel.CENTER ), 330 BorderLayout.NORTH ); 331 332 gainPanel.add ( gainSlider, BorderLayout.CENTER ); 333 334 gainPanel.setBorder ( 335 BorderFactory.createEtchedBorder ( EtchedBorder.RAISED ) ); 336 337 joystickPanel1.add ( gainPanel ); 338 339 gainSlider.addChangeListener ( 340 new ChangeListener ( ) 341 { 342 public void stateChanged ( ChangeEvent changeEvent ) 343 { 344 JSlider jSlider = ( JSlider ) changeEvent.getSource ( ); 345 346 if ( !jSlider.getValueIsAdjusting ( ) ) 347 { 348 cyborgController.setAlpha ( new Double ( 349 jSlider.getValue ( ) / CyborgConfig.GAIN_SCALE ) ); 350 } 351 } 352 } ); 353 354 JPanel offsetPanel = new JPanel ( new BorderLayout ( ) ); 355 356 offsetPanel.add ( 357 new JLabel ( "Offset", JLabel.CENTER ), BorderLayout.NORTH ); 358 359 offsetPanel.add ( offsetSlider, BorderLayout.SOUTH ); 360 361 offsetPanel.setBorder ( 362 BorderFactory.createEtchedBorder ( EtchedBorder.RAISED ) ); 363 364 joystickPanel1.add ( offsetPanel ); 365 366 offsetSlider.addChangeListener ( 367 new ChangeListener ( ) 368 { 369 public void stateChanged ( ChangeEvent changeEvent ) 370 { 371 JSlider jSlider = ( JSlider ) changeEvent.getSource ( ); 372 373 if ( !jSlider.getValueIsAdjusting ( ) ) 374 { 375 cyborgController.setOffset ( new Double ( 376 jSlider.getValue ( ) / CyborgConfig.OFFSET_SCALE ) ); 377 } 378 } 379 } ); 380 381 joystickPanel.setBorder ( 382 BorderFactory.createEtchedBorder ( EtchedBorder.RAISED ) ); 383 384 return joystickPanel; 385 } 386 387 private JPanel createOptionsPanel ( ) 388 ////////////////////////////////////////////////////////////////////// 389 { 390 JPanel jPanel = new JPanel ( new GridLayout ( 5, 1 ) ); 391 392 JRadioButton autoRadioButton 393 = new JRadioButton ( CyborgConfig.ACTION_COMMAND_AUTOMATIC ); 394 395 autoRadioButton.setActionCommand ( 396 CyborgConfig.ACTION_COMMAND_AUTOMATIC ); 397 398 autoRadioButton.addActionListener ( cyborgController ); 399 400 JRadioButton manuRadioButton 401 = new JRadioButton ( CyborgConfig.ACTION_COMMAND_MANUAL ); 402 403 manuRadioButton.setActionCommand ( 404 CyborgConfig.ACTION_COMMAND_MANUAL ); 405 406 manuRadioButton.addActionListener ( cyborgController ); 407 408 ButtonGroup buttonGroup = new ButtonGroup ( ); 409 410 buttonGroup.add ( autoRadioButton ); 411 412 buttonGroup.add ( manuRadioButton ); 413 414 jPanel.add ( autoRadioButton ); 415 416 jPanel.add ( manuRadioButton ); 417 418 realTimeCheckBox.setActionCommand ( 419 CyborgConfig.ACTION_COMMAND_REALTIME ); 420 421 realTimeCheckBox.addActionListener ( cyborgController ); 422 423 jPanel.add ( realTimeCheckBox ); 424 425 animateCheckBox.setActionCommand ( 426 CyborgConfig.ACTION_COMMAND_ANIMATE ); 427 428 animateCheckBox.addActionListener ( cyborgController ); 429 430 jPanel.add ( animateCheckBox ); 431 432 forceLengthCheckBox.setActionCommand ( 433 CyborgConfig.ACTION_COMMAND_FORCE_LENGTH ); 434 435 forceLengthCheckBox.addActionListener ( cyborgController ); 436 437 jPanel.add ( forceLengthCheckBox ); 438 439 jPanel.setBorder ( 440 BorderFactory.createEtchedBorder ( EtchedBorder.RAISED ) ); 441 442 autoRadioButton.setSelected ( true ); 443 444 return jPanel; 445 } 446 447 private JScrollPane createLogPanel ( ) 448 ////////////////////////////////////////////////////////////////////// 449 { 450 CyborgConfig.INSTANCE.setLog ( logPanel ); 451 452 logPanel.record ( CyborgConfig.INFO ); 453 454 JScrollPane jScrollPane = new JScrollPane ( logPanel ); 455 456 jScrollPane.setBorder ( 457 BorderFactory.createEtchedBorder ( EtchedBorder.RAISED ) ); 458 459 return jScrollPane; 460 } 461 462 ////////////////////////////////////////////////////////////////////// 463 ////////////////////////////////////////////////////////////////////// 464 465 private void updateView ( ) 466 ////////////////////////////////////////////////////////////////////// 467 { 468 animateCheckBox.setSelected ( cyborgModel.getAnimate ( ) ); 469 470 gainSlider.setValue ( ( int ) Math.round ( 471 CyborgConfig.GAIN_SCALE * cyborgModel.getAlpha ( ) ) ); 472 473 offsetSlider.setValue ( ( int ) Math.round ( 474 CyborgConfig.OFFSET_SCALE * cyborgModel.getOffset ( ) ) ); 475 476 realTimeCheckBox.setSelected ( cyborgModel.getRealTime ( ) ); 477 478 forceLengthCheckBox.setSelected ( cyborgModel.getForceLength ( ) ); 479 480 updateImageButton ( ); 481 } 482 483 private void updateImageButton ( ) 484 ////////////////////////////////////////////////////////////////////// 485 { 486 if ( bufferedImage == null ) 487 { 488 return; 489 } 490 491 for ( int x = 0; x < CyborgConfig.PLOT_SIZE; x++ ) 492 { 493 for ( int y = 0; y < CyborgConfig.PLOT_SIZE; y++ ) 494 { 495 bufferedImage.setRGB ( x, y, 0 ); 496 } 497 } 498 499 for ( int x = 0; x < CyborgConfig.PLOT_SIZE; x++ ) 500 { 501 double control 502 = ( 2.0 * x / ( CyborgConfig.PLOT_SIZE - 1.0 ) ) - 1.0; 503 504 double percent = cyborgModel.transform ( control ); 505 506 int y = ( CyborgConfig.PLOT_SIZE - 1 ) - ( int ) 507 ( Math.round ( ( CyborgConfig.PLOT_SIZE - 1 ) * percent ) ); 508 509 // System.out.println ( percent + " " + x + " " + y ); 510 511 if ( ( y > -1 ) && ( y < CyborgConfig.PLOT_SIZE ) ) 512 { 513 bufferedImage.setRGB ( x, y, 0xFFFF00 ); 514 } 515 } 516 517 repaint ( ); 518 } 519 520 ////////////////////////////////////////////////////////////////////// 521 ////////////////////////////////////////////////////////////////////// 522 }