Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/flexstor/common/awt/field/ComboField.java


1   /*
2    * ComboField.java
3    *
4    * Copyright $Date: 2003/08/19 04:06:47 $ FLEXSTOR.net Inc.
5    *
6    * This work is licensed for use and distribution under license terms found at
7    * http://www.flexstor.org/license.html
8    *
9    */
10  
11  package com.flexstor.common.awt.field;
12  
13  import java.awt.Color;
14  import java.awt.Component;
15  import java.awt.Dimension;
16  import java.awt.Frame;
17  import java.awt.Graphics;
18  import java.awt.Panel;
19  import java.awt.event.ActionEvent;
20  import java.awt.event.ActionListener;
21  import java.awt.event.MouseEvent;
22  import java.awt.event.MouseListener;
23  import java.util.ArrayList;
24  import java.util.Vector;
25  
26  //TODO:3PG fix or remove import jclass.bwt.JCActionEvent;
27  //TODO:3PG fix or remove import jclass.bwt.JCActionListener;
28  
29  import com.flexstor.common.awt.ArrowButton;
30  import com.flexstor.common.awt.event.FlexTextEvent;
31  import com.flexstor.common.awt.event.FlexTextListener;
32  import com.flexstor.common.constants.FieldConstantsI;
33  import com.flexstor.common.disguise.LookupListItem;
34  import com.flexstor.common.parsers.ValidatorI;
35  import com.flexstor.common.settings.Settings;
36  
37  /**
38   * ComboField is a self configuring TextField/Choice that provides full data
39   * validation and case conversion.  All edit events are sent as FlexTextEvent events, so that three
40   * different events (ItemEvent, ActionEvent, and TextEvent/KeyEvent) do not need to be caught.
41   * @author Dan Schroeder
42   * @version 2.1
43   */
44  public class ComboField
45         extends Panel
46         implements FlexTextListener, MouseListener, FieldConstantsI,
47                 ActionListener //TODO:3PG fix or remove JCActionListener
48  {
49     /** The current mode, either ENTRY_TYPE_UNDEFINED, ENTRY_TYPE_TEXT_FIELD, or ENTRY_TYPE_CHOICE. */
50     protected int nMode = ENTRY_TYPE_UNDEFINED;
51  
52     /** Reference to the field object. */
53     protected ComponentI field = null;
54  
55     /** The name associated with this field. */
56     protected String sName = "";
57  
58     /** Flag for choice padding. */
59     protected boolean bPadChoice = false;
60  
61     protected boolean bAllowRepaint = true;
62  
63     private boolean bVisualRequired = false;
64  
65     protected boolean bExtendedEdit = false;
66  
67     protected boolean bShowExtEdit = false;
68     
69     protected ArrowButton arrow;
70     
71     private boolean bEnabled = true;
72  
73     /** Text Listeners -- used for filtering of text events. */
74     private Vector textListeners = null;
75     
76     private String sTextAreaText;
77     
78     private int nCase;
79     
80     private static int nPopupThreshold = -1;
81  
82     private int nForcedLength = 0;
83     
84  
85     /**
86      * Creates a new ComboField with the specified name.
87      * @parma sName the name of this field.
88      */
89     public ComboField ( String sName, boolean bPadChoice )
90     {
91        setLayout ( null );
92        this.sName = sName;
93        this.bPadChoice = bPadChoice;
94        textListeners = new Vector ( 1, 1 );
95     }
96  
97  
98     /**
99      * Creates a new ComboField with the specified name.
100     * @parma sName the name of this field.
101     */
102    public ComboField ( String sName, boolean bPadChoice, boolean bVisualRequired, boolean bExtendedEdit )
103    {
104       this ( sName, bPadChoice );
105       arrow = new ArrowButton ( ArrowButton.RIGHT );
106     arrow.addActionListener ( this );
107       
108       this.bVisualRequired = bVisualRequired;
109       this.bExtendedEdit = bExtendedEdit;
110 
111       if ( nPopupThreshold == -1 )
112          nPopupThreshold = Settings.getInt ( Settings.FIELD_POPUP_THRESHOLD );
113    }
114 
115    public void cleanup()
116    {
117       cleanUp();
118       
119       field.cleanup();
120       field = null;
121    
122       if ( arrow != null )
123       {
124     arrow.removeActionListener( this );
125          arrow = null;
126       }
127       
128       textListeners.removeAllElements();
129       textListeners = null;
130    }
131 
132    /**
133     * Returns the name of this field.
134     * @return the name of this field.
135     */
136    public String getName ( )
137    {
138       return sName;
139 
140    }
141 
142    /**
143     * Conditionally enables/disables this field.
144     * @param bEdit enabled if true.
145     */
146    public void setEnabled ( boolean bEdit )
147    {
148       if ( bShowExtEdit )
149          field.setEnabled ( false );
150       else
151          field.setEnabled ( bEdit );
152       
153       bEnabled = bEdit;
154       repaint();
155    }
156    
157 
158    public boolean getEnabled ( )
159    {
160       return bEnabled;
161    }
162 
163    /**
164     * Configures this field.
165     * @param nDataType the data type.
166     * @param nEntryType the entry type.
167     * @param nLength the maximum entry lenght.
168     * @param nCase the case of strings.
169     * @param bRequired the user is required to enter data in this field.
170     * @param bEditable the field is editable if true.
171     * @param sLabel the name that is used in error messages for vaildation.
172     */
173    public void configure ( int nDataType, int nEntryType, int nLength, int nCase, boolean bRequired, boolean bEditable, String sLabel )
174    {
175       configure( nDataType, nEntryType, nLength, nCase, bRequired, bEditable, sLabel, new ArrayList() );
176    }
177 
178    /**
179     * Configures this field.
180     * @param nDataType the data type.
181     * @param nEntryType the entry type.
182     * @param nLength the maximum entry lenght.
183     * @param nCase the case of strings.
184     * @param bRequired the user is required to enter data in this field.
185     * @param bEditable the field is editable if true.
186     * @param sLabel the name that is used in error messages for vaildation.
187     * @param saLookup the list of lookup values for choices. Values id will be set to -1.
188     */
189    public void configure ( int nDataType, int nEntryType, int nLength, int nCase, boolean bRequired, boolean bEditable,
190                            String sLabel, String[] saLookup )
191    {
192       ArrayList alLookup = new ArrayList();
193       if ( saLookup != null )
194       {
195          for ( int i = 0; i < saLookup.length; i++ )
196             alLookup.add( new LookupListItem( saLookup[i], -1 ) );
197       }
198       
199       configure( nDataType, nEntryType, nLength, nCase, bRequired, bEditable, sLabel, alLookup );         
200    }
201    
202    /**
203     * Configures this field.
204     * @param nDataType the data type.
205     * @param nEntryType the entry type.
206     * @param nLength the maximum entry lenght.
207     * @param nCase the case of strings.
208     * @param bRequired the user is required to enter data in this field.
209     * @param bEditable the field is editable if true.
210     * @param sLabel the name that is used in error messages for vaildation.
211     * @param alLookup the list of lookup items including values and ids for choices.
212     */
213    public void configure ( int nDataType, int nEntryType, int nLength, int nCase, boolean bRequired, boolean bEditable,
214                            String sLabel, ArrayList alLookup )
215    {
216       bShowExtEdit = false;
217       this.nCase = nCase;
218 
219       switch ( nEntryType )
220       {
221          case ENTRY_TYPE_UNDEFINED:
222          {
223             cleanUp();
224             field = null;
225             break;
226          }
227 
228          case ENTRY_TYPE_CHOICE:
229          {
230             if ( nMode != ENTRY_TYPE_CHOICE )
231             {
232                cleanUp();
233                field = new FlexChoice( bPadChoice );
234                ((FlexChoice)field).addTextListener ( this );
235                ((FlexChoice)field).addMouseListener ( this );
236                ((FlexChoice)field).configure ( bEditable, bRequired, sLabel, alLookup );
237                add ( (FlexChoice)field );
238             }
239             else
240                ((FlexChoice)field).configure ( bEditable, bRequired, sLabel, alLookup );
241 
242             break;
243          }
244 
245          case ENTRY_TYPE_TEXT_FIELD:
246          {
247             if ( nMode != ENTRY_TYPE_TEXT_FIELD )
248             {
249                cleanUp();
250                field = new FlexTextField ( );
251                ((FlexTextField)field).addTextListener ( this );
252                ((FlexTextField)field).addMouseListener ( this );
253                ((FlexTextField)field).configure ( nDataType, nLength, nCase, bEditable, bRequired, sLabel );
254                add ( ((FlexTextField)field) );
255             }
256             else
257                ((FlexTextField)field).configure ( nDataType, nLength, nCase, bEditable, bRequired, sLabel );
258 
259             if ( bExtendedEdit && nLength >= nPopupThreshold )
260             {
261                bShowExtEdit = true;
262                add ( arrow );
263             }
264 
265             break;
266          }
267       }
268 
269       setEnabled ( bEditable );
270 
271       nMode = nEntryType;
272    }
273 
274    public void setItems( ArrayList alItems )
275    {
276       if ( field instanceof FlexChoice )
277          ( (FlexChoice)field ).setItems( alItems );
278    }
279 
280    public void setPreferredWidth ( int nWidth )
281    {
282       nForcedLength = nWidth;
283    }
284 
285 
286    public Dimension getMinimumSize()
287    {
288       int nWidth;
289       if ( nForcedLength > 0 )
290          nWidth = nForcedLength;
291       else
292          nWidth = field.getMinimumSize().width;
293 
294       return new Dimension ( nWidth, ComponentI.COMBO_FIELD_HEIGHT );
295    }
296 
297    public Dimension getPreferredSize()
298    {
299       int nWidth;
300       if ( nForcedLength > 0 )
301          nWidth = nForcedLength;
302       else
303          nWidth = field.getPreferredSize().width;
304 
305       return new Dimension ( nWidth, ComponentI.COMBO_FIELD_HEIGHT );
306    }
307 
308    // for 1.0 compatibility
309    public Dimension minimumSize()   {return getMinimumSize();}
310    public Dimension preferredSize() {return getPreferredSize();}
311 
312    /**
313     *
314     */
315    public void setText( String sText )
316    {
317       if ( bShowExtEdit )
318       {
319          sTextAreaText = sText;
320          field.setText ( fixupLabel(sText) );
321       }
322       else
323          field.setText ( sText );
324    }
325 
326    /**
327     *
328     */
329    public String getText()
330    {
331       if ( bShowExtEdit )
332          return sTextAreaText;
333       else
334          return field.getText();
335    }
336 
337    /**
338     *
339     */
340    public void setId( long nId )
341    {
342       field.setId( nId );
343    }
344 
345    /**
346     *
347     */
348    public long getId()
349    {
350       return field.getId();
351    }
352 
353    /**
354     *
355     */
356    public int getSelectedIndex()
357    {
358       return (nMode == ENTRY_TYPE_CHOICE) ? ((FlexChoice)field).getSelectedIndex() : 0;
359    }
360 
361    /**
362     *
363     */
364    public void setRequired ( boolean bRequired )
365    {
366       field.setRequired ( bRequired );
367    }
368 
369    public boolean isRequired ( )
370    {
371       return field.isRequired();
372    }
373 
374    /**
375     * This method will select the first item in the Choice box or clear out the text field.
376     * @param bNotify Sends an edit ActionEvent to all listeners if true.
377     */
378    public void clear ( boolean bNotify )
379    {
380       field.clear ( bNotify );
381    }
382 
383    /**
384     * Checks if the field is required.
385     */
386    public boolean verify ( boolean bCheckRequired )
387    {
388       return field.verify ( bCheckRequired );
389    }
390 
391    public boolean quietVerify()
392    {
393       return field.quietVerify();
394    }
395 
396    public void formatCase()
397    {
398       field.formatCase();
399    }
400 
401    public void setCustomValidator ( ValidatorI validator )
402    {
403       field.setCustomValidator ( validator );
404    }
405 
406    public void requestFocus ( )
407    {
408       field.requestFocus();
409    }
410    
411    public void enableRepaints ( boolean bPaint )
412    {
413       bAllowRepaint = bPaint;
414    }
415 
416    public void paint ( Graphics g )
417    {
418       if ( bAllowRepaint )
419       {
420          super.paint ( g );
421 
422          Dimension d = getSize();
423 
424          // Setup color for required fields.
425          if ( bVisualRequired && isRequired() && bEnabled )
426             g.setColor ( Settings.getColor ( Settings.FIELD_REQUIRED_COLOR ) );
427          else
428             g.setColor ( super.getBackground() );
429 
430 
431          if ( bShowExtEdit )
432          {
433             g.drawRect ( 0, 0, d.width-1, d.height-1 );
434             field.setBounds ( 1, 1, d.width-14, d.height-2 );
435 
436             if ( bEnabled )
437                arrow.setBackground ( Color.white );
438             else
439                arrow.setBackground ( Color.lightGray );
440 
441             arrow.setBounds ( d.width-13, 2, 12, d.height-3 );
442          }
443          else
444          {
445             g.drawRect ( 0, 0, d.width-1, d.height-1 );
446             field.setBounds ( 1, 1, d.width-2, d.height-2 );
447          }
448       }
449    }
450 
451    public void setOptimumSize ( int nMaxFieldWidth )
452    {
453       Dimension size = field.getMinimumSize();
454       
455       size.width  = (nMaxFieldWidth < size.width) ? nMaxFieldWidth : size.width;
456       size.height = ComponentI.COMBO_FIELD_HEIGHT;
457 
458       setSize ( size );
459    }
460 
461 
462    public void textValueChangeBegin ( FlexTextEvent e )
463    {
464       synchronized ( textListeners )
465       {
466          FlexTextEvent ne = new FlexTextEvent( this, 0, 0, e.getText() );
467          
468          for ( int i = 0; i < textListeners.size(); i++ )
469             ((FlexTextListener)textListeners.elementAt(i)).textValueChangeBegin ( ne );
470             
471          e.setAllowChange ( ne.getAllowChange() );
472       }
473    }
474    
475    
476    public void textValueChangeEnd ( FlexTextEvent e )
477    {
478       synchronized ( textListeners )
479       {
480          FlexTextEvent ne = new FlexTextEvent( this, 0, 0, e.getText() );
481          
482          for ( int i = 0; i < textListeners.size(); i++ )
483             ((FlexTextListener)textListeners.elementAt(i)).textValueChangeEnd ( ne );
484       }
485    }
486 
487    public synchronized void addTextListener ( FlexTextListener l )
488    {
489       textListeners.addElement ( l );
490    }
491 
492 
493    public synchronized void removeTextListener ( FlexTextListener l )
494    {
495       if ( textListeners.contains ( l ) )
496          textListeners.removeElement ( l );
497    }
498 
499 
500    public void actionPerformed ( ActionEvent e )
501    {
502       if ( e.getSource() instanceof ArrowButton )
503          popupExtDialog();
504    }
505    
506 
507    private void popupExtDialog ( )
508    {
509       ExtendedFieldDialog extDlg;
510 
511       extDlg = new ExtendedFieldDialog ( getParentFrame(), ((FlexTextField)field).getName(), getText(), bEnabled, nCase,
512                                           100); //TODO:3PG fix or remove  ((FlexTextField)field).getMaximumLength()  );
513 
514       String s = extDlg.getChanges();
515       if ( s != null )
516       {
517          FlexTextEvent e = new FlexTextEvent ( this, 0, 0, s );
518 
519          textValueChangeBegin ( e );
520          if ( e.getAllowChange() )
521          {
522             setText ( s );
523             textValueChangeEnd ( e );
524          }
525       }
526    }
527 
528 
529    public void mousePressed ( MouseEvent e )
530    {
531       if ( e.getComponent() != this )
532          this.processMouseEvent ( new MouseEvent ( this, e.getID(), e.getWhen(), e.getModifiers(), e.getX(), e.getY(),
533                                                    e.getClickCount(), e.isPopupTrigger()) );
534    }
535 
536    public void mouseClicked ( MouseEvent e ) { }
537    public void mouseEntered ( MouseEvent e ) { }
538    public void mouseExited ( MouseEvent e ) { }
539    public void mouseReleased ( MouseEvent e ) { }
540 
541    private void cleanUp ( )
542    {
543       removeAll();
544 
545       switch ( nMode )
546       {
547          case ENTRY_TYPE_CHOICE:
548          {
549             ((FlexChoice)field).removeTextListener ( this );
550             ((FlexChoice)field).removeMouseListener ( this );
551             break;
552          }
553 
554          case ENTRY_TYPE_TEXT_FIELD:
555          {
556             ((FlexTextField)field).removeTextListener ( this );
557             ((FlexTextField)field).removeMouseListener ( this );
558             break;
559          }
560       }
561    }
562 
563    public int getMode ( )
564    {
565       return nMode;
566    }
567 
568    public boolean isBlank()
569    {
570       return field.isBlank();
571    }
572 
573    
574    private Frame getParentFrame ( )
575    {
576       Component c = this;
577 
578       do
579       {
580          c = c.getParent();
581       }
582       while ( c != null && !(c instanceof Frame) );
583 
584       return (Frame)c;
585    }
586    
587    
588    public boolean isShowing ( )
589    {
590       return super.isShowing() && getLocation().x >= 0 && getLocation().y >= 0;
591    }
592 
593 
594    /**
595     * Removes invalid characters from the label.
596     * @param sLabel the orginal label.
597     * @return the "fixed" label.
598     */
599    private String fixupLabel ( String sLabel )
600    {
601       int nOrginal = sLabel.length() - 1;
602       int nLast    = nOrginal;
603       int nTemp;
604 
605       // Detect Newlines.
606       nTemp = sLabel.indexOf ( '\n' );
607       if ( nTemp > -1 )
608          nLast = nTemp;
609 
610       // Detect Tabs.
611 //      nTemp = sLabel.indexOf ( '\t' );
612 //      if ( (nTemp > -1) && (nTemp < nLast) )
613 //         nLast = nTemp;
614 
615       if ( nLast < nOrginal )
616          sLabel = sLabel.substring ( 0, nLast ) + "...";
617 
618       return sLabel;
619    }
620 
621 
622 }