001 package com.sptci.echo2demo;
002
003 import java.beans.PropertyDescriptor;
004 import java.lang.reflect.Field;
005 import java.util.HashMap;
006 import java.util.Map;
007
008 import nextapp.echo2.app.Alignment;
009 import nextapp.echo2.app.Button;
010 import nextapp.echo2.app.CheckBox;
011 import nextapp.echo2.app.Column;
012 import nextapp.echo2.app.Component;
013 import nextapp.echo2.app.ContentPane;
014 import nextapp.echo2.app.Extent;
015 import nextapp.echo2.app.Grid;
016 import nextapp.echo2.app.Insets;
017 import nextapp.echo2.app.Label;
018 import nextapp.echo2.app.ListBox;
019 import nextapp.echo2.app.Row;
020 import nextapp.echo2.app.SelectField;
021 import nextapp.echo2.app.TextArea;
022 import nextapp.echo2.app.TextField;
023 import nextapp.echo2.app.layout.GridLayoutData;
024 import nextapp.echo2.app.list.DefaultListModel;
025 import nextapp.echo2.app.text.TextComponent;
026
027 import nextapp.echo2.app.event.ActionEvent;
028 import nextapp.echo2.app.event.ActionListener;
029
030 import org.rakeshv.utils.StringUtilities;
031 import com.sptci.echo2.JDOModelUpdater;
032 import com.sptci.echo2.JDOModelPropertyChangeListener;
033 import com.sptci.echo2.ListItem;
034 import com.sptci.echo2.ViewPropertyChangeListener;
035 import com.sptci.echo2.ViewUpdater;
036
037 /**
038 * A <code>ContentPane</code> that builds the form used to input
039 * user and job information.
040 *
041 * <p>Copyright 2006 Sans Pareil Technologies, Inc.</p>
042 * @author Rakesh Vidyadharan 2006-01-21
043 * @version $Id: InputForm.java,v 1.10 2006/02/15 16:14:57 rakesh Exp $
044 */
045 public class InputForm extends ContentPane implements ActionListener
046 {
047 /**
048 * The java bean used to store the values of the data for the
049 * UI components.
050 */
051 private InputFormModel model;
052
053 /**
054 * The property change listener used to synchronise modifications
055 * applied to UI components to the {@link #model} java bean.
056 */
057 private JDOModelPropertyChangeListener jdoChangeListener;
058
059 /**
060 * The property change listener used to synchronise modifications
061 * applied to the {@link #model} java bean to the UI components.
062 */
063 private ViewPropertyChangeListener uiChangeListener;
064
065 private TextField textField;
066 private TextArea textArea;
067 private HashMap<String, CheckBox> checkBoxes;
068 private ListBox listBox;
069 private SelectField selectField;
070
071 private Button first;
072 private Button previous;
073 private Button last;
074 private Button next;
075 private Button save;
076 private Button delete;
077 private Label index;
078
079 /**
080 * Create a new instance of the form.
081 *
082 * @see #initForm
083 */
084 public InputForm()
085 {
086 this( new InputFormModel() );
087 }
088
089 /**
090 * Create a new instance of the form using the specified java bean.
091 *
092 * @see #initForm
093 * @param model The java bean to use to store the values of the
094 * UI components.
095 */
096 public InputForm( InputFormModel model )
097 {
098 this.model = model;
099 /*
100 try
101 {
102 jdoChangeListener = new JDOModelPropertyChangeListener( model );
103 }
104 catch ( java.beans.IntrospectionException iex )
105 {
106 throw new RuntimeException( iex.getMessage(), iex );
107 }
108 */
109
110 initForm();
111
112 //uiChangeListener = new ViewPropertyChangeListener( this );
113 //this.model.addPropertyChangeListener( uiChangeListener );
114 }
115
116 /**
117 * Initialise the UI components for the form.
118 *
119 * @see #createTextField
120 * @see #createTextArea
121 * @see #createCheckBoxes
122 * @see #createSelectField
123 * @see #createListBox
124 * @see #createButton
125 */
126 private void initForm()
127 {
128 setStyleName( "InputForm.ContentPane" );
129 Grid grid = new Grid( 3 );
130 grid.setInsets( new Insets( 2, 2 ) );
131
132 grid.add( createTextField( "textField" ) );
133 grid.add( createTextArea( "textArea" ) );
134
135 grid.add( createCheckBoxes() );
136 grid.add( createSelectField() );
137 grid.add( createListBox() );
138
139 Row row1 = new Row();
140 row1.add( createButton( "first" ) );
141 row1.add( createButton( "previous" ) );
142
143 Row row3 = new Row();
144 row3.add( createButton( "next" ) );
145 row3.add( createButton( "last" ) );
146
147 Row row2 = new Row();
148 row2.add( createButton( "save" ) );
149 index = new Label();
150 index.setToolTipText( "Record number" );
151 row2.add( index );
152 row2.add( createButton( "delete" ) );
153 setIndexValue( InputFormModelFactory.getInstance().lastIndex() + 1 );
154
155 grid.add( row1 );
156 grid.add( row2 );
157 grid.add( row3 );
158
159 add( grid );
160 }
161
162 /**
163 * Create the label and text field necessary to display the UI
164 * components.
165 *
166 * @see #createLabel
167 * @see #setText
168 * @param name The name used to identify the text field to create.
169 * The name must match the name of the appropriate field
170 * without the Field suffix (eg. userName, salary, ...). The
171 * same name must be configured in the configuration file for
172 * the properties and resources.
173 * @return Component The new component that contains the newly
174 * created UI components.
175 */
176 private Component createTextField( String name )
177 {
178 Column column = new Column();
179 column.setStyleName( "InputForm.LabelFieldColumn" );
180
181 createLabel( name, column );
182
183 TextField textField = new TextField();
184 textField.setActionCommand( name );
185 textField.setWidth( new Extent(
186 Configuration.getInt( "InputForm." + name + ".width" ) ) );
187 textField.setToolTipText(
188 Configuration.getString( "InputForm." + name + ".tooltip" ) );
189 textField.setStyleName( "InputForm.TextComponent" );
190 //textField.addPropertyChangeListener( jdoChangeListener );
191 //setText( textField );
192
193 try
194 {
195 Field field = getClass().getDeclaredField( name );
196 field.set( this, textField );
197 }
198 catch ( Throwable t )
199 {
200 throw new RuntimeException( t.getMessage(), t );
201 }
202
203 column.add( textField );
204 return column;
205 }
206
207 /**
208 * Create a label using the specified name property and add it to the
209 * specified component.
210 *
211 * @param name The name used to identify the label to create. The
212 * same name must be configured in the configuration file for
213 * the properties and resources.
214 */
215 private Label createLabel( String name, Component component )
216 {
217 Label label = new Label(
218 Configuration.getString( "InputForm." + name + ".label" ) );
219 label.setToolTipText(
220 Configuration.getString( "InputForm." + name + ".tooltip" ) );
221 label.setStyleName( "InputForm.Label" );
222 component.add( label );
223
224 return label;
225 }
226
227 /**
228 * Set the text for the specified <code>TextComponent</code> from
229 * the value in the {@link #model} data bean through {@link
230 * #jdoChangeListener}.
231 *
232 * <p><b>Note:</b> It is mandatory that the <code>ActionCommand</code>
233 * for the <code>TextComponent</code> be set prior to invoking this
234 * method.</p>
235 *
236 * @param text The text component whose text is to be set.
237 */
238 private void setText( TextComponent text )
239 {
240 PropertyDescriptor descriptor =
241 jdoChangeListener.getProperties().get( text.getActionCommand() );
242 if ( descriptor != null )
243 {
244 try
245 {
246 Object object = descriptor.getReadMethod().invoke( model );
247 if ( object != null )
248 {
249 text.setText( object.toString() );
250 }
251 }
252 catch ( Throwable t )
253 {
254 throw new RuntimeException( t.getMessage(), t );
255 }
256 }
257 }
258
259 /**
260 * Create the label and text area necessary to display the UI
261 * components.
262 *
263 * @see #createLabel
264 * @see #setText
265 * @param name The name used to identify the text area to create.
266 * The name must match the name of the appropriate area
267 * without the Area suffix (eg. userName, salary, ...). The
268 * same name must be configured in the configuration file for
269 * the properties and resources.
270 * @return Component The new component that contains the newly
271 * created UI components.
272 */
273 private Component createTextArea( String name )
274 {
275 Column column = new Column();
276 GridLayoutData layout = new GridLayoutData();
277 layout.setColumnSpan( 2 );
278 column.setLayoutData( layout );
279 createLabel( name, column );
280
281 TextArea textArea = new TextArea();
282 textArea.setActionCommand( name );
283 textArea.setHeight( new Extent( Configuration.getInt(
284 "InputForm." + name + ".height" ), Extent.EM ) );
285 textArea.setWidth( new Extent(
286 Configuration.getInt( "InputForm." + name + ".width" ) ) );
287 textArea.setToolTipText(
288 Configuration.getString( "InputForm." + name + ".tooltip" ) );
289 textArea.setStyleName( "InputForm.TextComponent" );
290 //textArea.addPropertyChangeListener( jdoChangeListener );
291 //setText( textArea );
292
293 try
294 {
295 Field field = getClass().getDeclaredField( name );
296 field.set( this, textArea );
297 }
298 catch ( Throwable t )
299 {
300 throw new RuntimeException( t.getMessage(), t );
301 }
302
303 column.add( textArea );
304 return column;
305 }
306
307 /**
308 * Create the column necessary to display the check boxes and also
309 * create the required check boxes.
310 */
311 private Component createCheckBoxes()
312 {
313 checkBoxes = new HashMap<String, CheckBox>();
314 Column column = new Column();
315
316 for ( Map.Entry<String, Boolean> entry : model.getCheckBoxes().entrySet() )
317 {
318 CheckBox checkBox = new CheckBox( entry.getKey() );
319 checkBox.setActionCommand( "checkBoxes>" + entry.getKey() );
320 checkBox.setStyleName( "InputForm.TextComponent" );
321 checkBox.setSelected( entry.getValue() );
322 //checkBox.addPropertyChangeListener( jdoChangeListener );
323 column.add( checkBox );
324
325 checkBoxes.put( checkBox.getActionCommand(), checkBox );
326 }
327
328 return column;
329 }
330
331 /**
332 * Create the select field component.
333 */
334 private Component createSelectField()
335 {
336 selectField = new SelectField();
337
338 DefaultListModel listModel = new DefaultListModel();
339 int count = 0;
340 for ( ListItem item : model.getSelectField() )
341 {
342 listModel.add( count++, item.getValue() );
343 if ( item.isSelected() )
344 {
345 selectField.setSelectedIndex( count );
346 }
347 }
348 selectField.setModel( listModel );
349 selectField.setSelectedIndex( 0 );
350
351 selectField.setActionCommand( "selectField" );
352 //selectField.addPropertyChangeListener( jdoChangeListener );
353 return selectField;
354 }
355
356 /**
357 * Create the list box component.
358 */
359 private Component createListBox()
360 {
361 listBox = new ListBox();
362
363 DefaultListModel listModel = new DefaultListModel();
364 int count = 0;
365 for ( ListItem item : model.getListBox() )
366 {
367 listModel.add( count++, item.getValue() );
368 }
369 listBox.setModel( listModel );
370
371 listBox.setActionCommand( "listBox" );
372 //listBox.addPropertyChangeListener( jdoChangeListener );
373 return listBox;
374 }
375
376 /**
377 * Create the button identified by the specified name.
378 *
379 * @param name The name used to identify the button to create.
380 * The name must match the name of the appropriate button. The
381 * same name must be configured in the configuration file for
382 * the properties and resources.
383 * @return Component The new component that contains the newly
384 * created UI components.
385 */
386 private Button createButton( String name )
387 {
388 Button button = new Button( Configuration.getString(
389 "InputForm." + name + ".text" ) );
390 button.setStyleName( "InputForm.Button" );
391 button.setToolTipText( Configuration.getString(
392 "InputForm." + name + ".tooltip" ) );
393 button.setActionCommand( name );
394 button.addActionListener( this );
395
396 try
397 {
398 Field field = getClass().getDeclaredField( name );
399 field.set( this, button );
400 }
401 catch ( Throwable t )
402 {
403 throw new RuntimeException( t.getMessage(), t );
404 }
405
406 return button;
407 }
408
409 /**
410 * Set the text of the {@link #index} label. Enable or disable
411 * the navigation buttons depending upon the values.
412 *
413 * @param index The index value to set.
414 */
415 private void setIndexValue( int index )
416 {
417 first.setEnabled( true );
418 previous.setEnabled( true );
419 next.setEnabled( true );
420 last.setEnabled( true );
421 delete.setEnabled( true );
422
423 if ( index == 0 )
424 {
425 first.setEnabled( false );
426 previous.setEnabled( false );
427 }
428 if ( index >= InputFormModelFactory.getInstance().lastIndex() )
429 {
430 last.setEnabled( false );
431 }
432 if ( index > InputFormModelFactory.getInstance().lastIndex() )
433 {
434 next.setEnabled( false );
435 delete.setEnabled( false );
436 }
437
438 this.index.setText( String.valueOf( index ) );
439 }
440
441 /**
442 * Returns {@link #model}.
443 *
444 * @return InputFormModel The value/reference of/to model.
445 */
446 public final InputFormModel getFormData()
447 {
448 return model;
449 }
450
451 /**
452 * Set {@link #model}.
453 *
454 * @param model The value to set.
455 */
456 final void setModel( InputFormModel model )
457 {
458 //this.model.removePropertyChangeListener( uiChangeListener );
459 this.model = model;
460 //this.model.addPropertyChangeListener( uiChangeListener );
461 /*
462 try
463 {
464 jdoChangeListener.setBean( model );
465 }
466 catch ( Throwable t )
467 {
468 throw new RuntimeException( t.getMessage(), t );
469 }
470 */
471
472 ( new ViewUpdater( this, model ) ).update();
473 }
474
475 /**
476 * Returns {@link #jdoChangeListener}.
477 *
478 * @return JDOModelPropertyChangeListener The value/reference of/to
479 * jdoChangeListener.
480 */
481 public final JDOModelPropertyChangeListener getDataChangeListener()
482 {
483 return jdoChangeListener;
484 }
485
486 /**
487 * ActionListener implementation. Actions are triggered when a
488 * button is pressed.
489 *
490 * @param event The event that contains the information
491 * pertaining to the action.
492 */
493 public void actionPerformed( ActionEvent event )
494 {
495 if ( event.getActionCommand().equals( "save" ) )
496 {
497 doSave();
498 }
499 else if ( event.getActionCommand().equals( "delete" ) )
500 {
501 doDelete();
502 }
503 else if ( event.getActionCommand().equals( "first" ) )
504 {
505 doNavigate( 0 );
506 }
507 else if ( event.getActionCommand().equals( "previous" ) )
508 {
509 doNavigate( Integer.parseInt( index.getText() ) - 1 );
510 }
511 else if ( event.getActionCommand().equals( "next" ) )
512 {
513 doNavigate( Integer.parseInt( index.getText() ) + 1 );
514 }
515 else if ( event.getActionCommand().equals( "last" ) )
516 {
517 doNavigate( InputFormModelFactory.getInstance().lastIndex() );
518 }
519 }
520
521 /**
522 * The action for the {@link #save} button.
523 */
524 private void doSave()
525 {
526 save.setEnabled( false );
527 save.setText( Configuration.getString( "InputForm.save.working" ) );
528 InputFormModelFactory factory =
529 InputFormModelFactory.getInstance();
530
531 try
532 {
533 ( new JDOModelUpdater( this, model ) ).update();
534 factory.save( model );
535 setModel( new InputFormModel() );
536 setIndexValue( factory.lastIndex() + 1 );
537 }
538 catch ( Throwable t )
539 {
540 ErrorPane pane = new ErrorPane(
541 t.getMessage(), StringUtilities.stackTrace( t ) );
542 add( pane );
543 }
544
545 save.setEnabled( true );
546 save.setText( Configuration.getString( "InputForm.save.text" ) );
547 }
548
549 /**
550 * The action for the {@link #delete} button.
551 */
552 private void doDelete()
553 {
554 delete.setEnabled( false );
555 delete.setText( Configuration.getString( "InputForm.delete.working" ) );
556 InputFormModelFactory factory =
557 InputFormModelFactory.getInstance();
558
559 try
560 {
561 factory.delete( model );
562 setModel( new InputFormModel() );
563 setIndexValue( factory.lastIndex() + 1 );
564 }
565 catch ( Throwable t )
566 {
567 ErrorPane pane = new ErrorPane(
568 t.getMessage(), StringUtilities.stackTrace( t ) );
569 add( pane );
570 }
571
572 delete.setEnabled( true );
573 delete.setText( Configuration.getString( "InputForm.delete.text" ) );
574 }
575
576 /**
577 * The action for the navigation buttons.
578 *
579 * @param index The index in a List of {@link InputFormModel} objects at
580 * which the object is to be retrieved.
581 */
582 private void doNavigate( int index )
583 {
584 InputFormModel data =
585 InputFormModelFactory.getInstance().fetchByIndex( index );
586 if ( data == null )
587 {
588 data = new InputFormModel();
589 }
590
591 setModel( data );
592 setIndexValue( index );
593 }
594 }