You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

668 lines
16 KiB

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<ObjClass extends Object> 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<JComponent> 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<Object> optionDialog = new LeafOptionDialog<Object>( getParentWindow(), (Map) object, null );
return optionDialog.getOption();
}
}
else if( object instanceof OrderedMap )
{
if(((OrderedMap) object).rows() > 0)
{
LeafOptionDialog<Object> optionDialog = new LeafOptionDialog<Object>( getParentWindow(), (OrderedMap<Object>) 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<Object> values = ((OrderedMap) object).getValues( selectedOption );
theeze = new ArrayList<JComponent>();
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<JComponent>();
OrderedMap<Object> map = (OrderedMap<Object>) 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<Object> 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<Object> leaf;
if( value instanceof LeafInputField )
{
leaf = (LeafInputField<Object>) value;
}
else
{
leaf = new LeafInputField<Object>();
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() );
}
}