package leaf; import info.clearthought.layout.TableLayout; import info.clearthought.layout.TableLayoutConstraints; import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.text.DateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Map; import javax.swing.BorderFactory; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSeparator; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SwingUtilities; public class LeafInputField extends JPanel implements FocusListener, MouseListener, PropertyChangeListener { public static final String PROPERTY_CHANGED_CONSTANT = "LEAF_INPUT_PROPERTY_CHANGED"; public static final String PROPERTY_CHANGED_CLICK = "LEAF_PROPERTY_CHANGED_CLICK"; private static final long serialVersionUID = 1L; private static final DateFormat sdf = DateFormat.getDateInstance( DateFormat.SHORT, new Locale( "pt", "PT" ) ); private static final int defaultColorDec = 20; private int colorDec = defaultColorDec; public Dimension size = null; private Color hot = null; private Color cold = null; private Color background = null; private Color startColor = null; private Color endColor = null; private Color highLightColor = new Color( 180, 255, 180 ); private Object selectedOption = null; private boolean isError = false; private boolean isEditable = false; private boolean isClickable = false; private boolean highLighted = false; private boolean collapseOptions = true; private ObjClass object = null; private GradientPaint outerContour = null; private GradientPaint outerReversedContour = null; private GradientPaint innerContour = null; private GradientPaint innerReversedContour = null; private GradientPaint gradient = null; private TableLayout layout = null; private JComponent thiz = null; private List theeze = null; public LeafInputField() { super(); setOpaque( false ); setBorder( BorderFactory.createEmptyBorder( 3, 10, 3, 10 ) ); setBackground( Color.WHITE ); hot = getBackground(); cold = new Color( hot.getRed() > colorDec ? hot.getRed() - colorDec : 0, hot.getGreen() > colorDec ? hot.getGreen() - colorDec : 0, hot.getBlue() > colorDec ? hot.getBlue() - colorDec : 0, hot.getAlpha() ); background = cold; setObject( null ); } public boolean isCollapseOptions() { return collapseOptions; } public void setCollapseOptions( boolean collapse ) { collapseOptions = collapse; } public void setText( String text ) { try { setObject( (ObjClass) text ); } catch( ClassCastException ex ) { ex.printStackTrace(); } } private String getStringFromUser() { LeafTextDialog textDialog = new LeafTextDialog( getParentWindow(), this, (String) object, true ); return textDialog.getText(); } private Object getOptionFromUser() { if( object instanceof Map ) { if(((Map) object).size() > 0) { LeafOptionDialog optionDialog = new LeafOptionDialog( getParentWindow(), (Map) object, null ); return optionDialog.getOption(); } } else if( object instanceof OrderedMap ) { if(((OrderedMap) object).rows() > 0) { LeafOptionDialog optionDialog = new LeafOptionDialog( getParentWindow(), (OrderedMap) object, null, null, null, null ); return optionDialog.getOption(); } } return null; } private Date getDateFromUser() { LeafCalendarDialog calendarDialog = new LeafCalendarDialog( getParentWindow(), this ); return calendarDialog.getDate(); } private LeafWindow getParentWindow() { LeafWindow result = null; for( Container parent = this.getParent(); parent != null; parent = parent.getParent() ) { if( parent instanceof LeafWindow ) { result = (LeafWindow) parent; } } return result; } protected void paintComponent( Graphics g ) { Graphics2D g2d = (Graphics2D) g; int width = getWidth(); int height = getHeight(); setColors( width, height ); g2d.setPaint( outerReversedContour ); g2d.fillRect( 15, 0, width / 4, height ); g2d.setPaint( outerContour ); g2d.fillRect( width / 4, 0, width, height ); g2d.setPaint( innerReversedContour ); g2d.fillRect( 15, 0, width / 4, height - 1 ); g2d.setPaint( innerContour ); g2d.fillRect( width / 4, 0, width, height - 1 ); g2d.setPaint( gradient ); g2d.fillRoundRect( 0, 2, width, height - 5, 15, 15 ); super.paintComponent( g ); } private void setColors( int width, int height ) { startColor = getGradientStartColor(); endColor = getGradientEndColor( startColor ); outerContour = new GradientPaint( width / 4, 0, Color.GRAY, width, 0, this.getParent().getBackground() ); outerReversedContour = new GradientPaint( 15, 0, this.getParent().getBackground(), width / 4, 0, Color.GRAY ); innerContour = new GradientPaint( width / 4, 0, Color.LIGHT_GRAY, width, 0, this.getParent().getBackground() ); innerReversedContour = new GradientPaint( 15, 0, this.getParent().getBackground(), width / 4, 0, Color.LIGHT_GRAY ); gradient = new GradientPaint( 0, 0, startColor, width, height, endColor ); } private Color getGradientStartColor() { Color result = background; /* * int red = result.getRed(), green = result.getGreen(), blue = * result.getBlue(), alpha = result.getAlpha(); if( isError() ) { result = * new Color( red, green > colorDec ? (green - colorDec) : 0, (blue > * colorDec) ? (blue - colorDec) : 0, alpha ); } else if( isEditable() ) { * result = new Color( red > colorDec ? (red - colorDec) : 0, green, * blue > colorDec ? (blue - colorDec) : 0, alpha ); } */ return result; } private Color getGradientEndColor( Color startColor ) { return getParent() != null ? getParent().getBackground() : startColor; } /** * Sets the component to an error state appearance * * @param error */ public void setError( boolean error ) { isError = error; repaint(); } public boolean isError() { return isError; } public boolean getSelected() { return highLighted; } public void setSelected( boolean selected ) { highLighted = selected; background = selected ? highLightColor : cold; repaint(); } public void setEditable( boolean editable ) { isEditable = editable; if( !editable ) { setMouseOver( false ); } repaint(); } public boolean isEditable() { return isEditable; } public void setClickable( boolean clickable ) { isClickable = clickable; if( !clickable ) { setMouseOver( false ); } repaint(); } public boolean isClickable() { return isClickable; } private void setupCollapsedPanel() { List values = ((OrderedMap) object).getValues( selectedOption ); theeze = new ArrayList(); if( values != null ) { double[] rows = new double[] { TableLayout.MINIMUM }; double[] cols = new double[values.size() > 0 ? (values.size() * 2 - 1) : 0]; for( int i = 0; i < cols.length; ++i ) { cols[i] = (i % 2 == 0) ? TableLayout.FILL : TableLayout.MINIMUM; } TableLayout layout = new TableLayout( cols, rows ); layout.setHGap( 5 ); thiz.setLayout( layout ); for( int i = 0, a = 0; i < cols.length; ++i ) { JComponent comp = null; if( i % 2 == 0 ) { Object value = values.get( a++ ); comp = new JLabel( value == null ? " " : value.toString() ); theeze.add( comp ); } else { comp = new JSeparator( JSeparator.VERTICAL ); } thiz.add( comp, new TableLayoutConstraints( i, 0 ) ); } } } private void setupUncollapsedPanel() { theeze = new ArrayList(); OrderedMap map = (OrderedMap) object; double[] rows = new double[map.rows() > 0 ? (map.rows() * 2 - 1) : 0]; double[] cols = new double[map.columns() > 0 ? (map.columns() * 2 - 1) : 0]; for( int i = 0; i < rows.length; ++i ) { rows[i] = (i % 2 == 0) ? TableLayout.MINIMUM : TableLayout.MINIMUM; } for( int i = 0; i < cols.length; ++i ) { cols[i] = (i % 2 == 0) ? TableLayout.FILL : TableLayout.MINIMUM; } TableLayout layout = new TableLayout( cols, rows ); layout.setHGap( 5 ); thiz.setLayout( layout ); for( int i = 0, a = 0; i < rows.length; ++i ) { if( i % 2 == 0 ) { List values = map.getRow( a++ ); for( int j = 0, b = 0; j < cols.length; ++j ) { JComponent comp = null; if( j % 2 == 0 ) { Object value = values.get( b++ ); LeafInputField leaf; if( value instanceof LeafInputField ) { leaf = (LeafInputField) value; } else { leaf = new LeafInputField(); leaf.setObject( value ); if( j > 1 ) { leaf.setEditable( isEditable ); } } comp = leaf; theeze.add( comp ); } else { JSeparator sep = new JSeparator( JSeparator.VERTICAL ); sep.setForeground( cold ); comp = sep; } thiz.add( comp, new TableLayoutConstraints( j, i ) ); } } else { JSeparator sep = new JSeparator(); sep.setForeground( cold ); thiz.add( sep, new TableLayoutConstraints( 0, i, cols.length - 1, i ) ); } } } private void setSelectedObject( Object key ) { selectedOption = key; if( object != null && thiz != null /*&& selectedOption != null */) { if( object instanceof Map ) { Object value = null; value = ((Map) object).get( selectedOption ); if( thiz instanceof JTextArea ) { ((JTextArea) thiz).setText( value == null ? " " : value.toString() ); } else if( thiz instanceof JTextField ) { ((JTextField) thiz).setText( value == null ? " " : value.toString() ); } else if( thiz instanceof JLabel ) { ((JLabel) thiz).setText( value == null ? " " : value.toString() ); } } else if( object instanceof OrderedMap ) { if( thiz instanceof JPanel && collapseOptions ) { setupCollapsedPanel(); } else if( thiz instanceof JPanel && !collapseOptions ) { setupUncollapsedPanel(); } } } } public Object getSelectedObject() { return selectedOption; } public void setObject( ObjClass object, Object selected ) { this.selectedOption = selected; setObject( object ); } public void setObject( ObjClass object ) { this.object = object; if( object != null ) { if( object instanceof Date ) { thiz = new JLabel( sdf.format( object ) ); } else if( object instanceof Map ) { thiz = new JLabel( " " ); setSelectedObject( selectedOption ); } else if( object instanceof OrderedMap && collapseOptions ) { thiz = new JPanel(); setSelectedObject( selectedOption ); } else if( object instanceof OrderedMap && !collapseOptions ) { thiz = new JPanel(); setSelectedObject( selectedOption ); } else if( object instanceof LeafInputField ) { setObject( (ObjClass) ((LeafInputField) object).getObject(), ((LeafInputField) object).getSelectedObject() ); } else if( object instanceof String ) { JTextArea textArea = new JTextArea(); textArea.setEditable( false ); textArea.setText( object == null ? "" : object.toString() ); thiz = textArea; } else { String toString = object.toString(); if( "".equals( toString ) ) { toString = " "; } thiz = new JLabel( toString ); } } else { thiz = new JLabel( " " ); } reListen(); reLayout(); } public ObjClass getObject() { return this.object; } private void reListen() { removeListeners(); if( theeze != null && !collapseOptions && !theeze.isEmpty() ) { for( JComponent current : theeze ) { if( current instanceof LeafInputField ) { current.addFocusListener( (LeafInputField) current ); current.addMouseListener( (LeafInputField) current ); current.addPropertyChangeListener( PROPERTY_CHANGED_CONSTANT, this ); } } } else { thiz.addFocusListener( this ); thiz.addMouseListener( this ); } } private void removeListeners() { removeListerensFrom( thiz ); if( theeze != null ) { for( JComponent comp : theeze ) { removeListerensFrom( comp ); } } } private void removeListerensFrom( JComponent comp ) { if( comp != null ) { FocusListener[] allFocus = thiz.getFocusListeners(); if( allFocus != null ) { for( FocusListener focusListener : allFocus ) { comp.removeFocusListener( focusListener ); } } MouseListener[] allMouse = thiz.getMouseListeners(); if( allMouse != null ) { for( MouseListener mouseListener : allMouse ) { comp.removeMouseListener( mouseListener ); } } } } private void reLayout() { if( thiz != null ) { SwingUtilities.invokeLater( new Runnable() { @Override public void run() { if( layout == null ) { layout = new TableLayout( new double[] { TableLayout.FILL }, new double[] { TableLayout.FILL } ); LeafInputField.this.setLayout( layout ); } else { removeAll(); } LeafInputField.this.add( thiz, new TableLayoutConstraints( 0, 0 ) ); revalidate(); repaint(); } } ); size = thiz.getPreferredSize(); thiz.setOpaque( false ); } } @Override public void focusLost( FocusEvent e ) { repaint(); } @Override public void focusGained( FocusEvent e ) { repaint(); } @Override public void mouseReleased( MouseEvent e ) { } @Override public void mousePressed( MouseEvent e ) { Object old = null; if( object != null && isEditable ) { if( object instanceof Date ) { old = object; ObjClass newDate = (ObjClass) getDateFromUser(); if( newDate != null ) { setObject( newDate ); firePropertyChange( PROPERTY_CHANGED_CONSTANT, old, object ); } } else if( object instanceof Map && collapseOptions ) { old = selectedOption; ObjClass out = (ObjClass) getOptionFromUser(); setObject( object, out ); firePropertyChange( PROPERTY_CHANGED_CONSTANT, old, selectedOption ); } else if( object instanceof OrderedMap && collapseOptions ) { old = selectedOption; ObjClass out = (ObjClass) getOptionFromUser(); setObject( object, out ); firePropertyChange( PROPERTY_CHANGED_CONSTANT, old, object ); } else if( object instanceof OrderedMap && !collapseOptions ) { // old = selectedOption; // ObjClass out = (ObjClass) getOptionFromUser(); // setObject( object, out ); // firePropertyChange( PROPERTY_CHANGED_CONSTANT, old, object ); } else if( object instanceof String ) { old = object; setObject( (ObjClass) getStringFromUser() ); firePropertyChange( PROPERTY_CHANGED_CONSTANT, old, object ); } } if( isClickable ) { firePropertyChange( PROPERTY_CHANGED_CLICK, false, true ); } // setObject( object, selectedOption ); } @Override public void mouseExited( MouseEvent e ) { setMouseOver( false ); repaint(); } @Override public void mouseEntered( MouseEvent e ) { setMouseOver( true ); repaint(); } @Override public void mouseClicked( MouseEvent e ) { } private void setMouseOver( boolean mouseOver ) { if( mouseOver ) { background = (!highLighted && (isEditable || isClickable)) ? hot : background; } else { background = (!highLighted && (isEditable || isClickable)) ? cold : background; } } @Override public void propertyChange( PropertyChangeEvent evt ) { firePropertyChange( PROPERTY_CHANGED_CONSTANT, evt.getOldValue(), evt.getNewValue() ); } }