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         }