Issue Details (XML | Word | Printable)

Key: UBA-878
Type: Bug Bug
Status: Open Open
Priority: Major Major
Assignee: Unassigned
Reporter: Andreas Henle
Votes: 1
Watchers: 3
Operations

If you were logged in you would be able to see more operations.
ULCBase

How to find out ULCTextField is empty

Created: 10/Dec/04 12:00 AM   Updated: 17/Jul/08 11:26 AM
Component/s: core
Affects Version/s: None
Fix Version/s: None

Issue Links:
Reference
 


 Description  « Hide
If a ULCTextField is combined with a ULCDataType it is not possible to find out by calling getValue if a returned null value is the result of a unvalid input or an empty text field.

 All   Comments   Change History      Sort Order: Ascending order - Click to sort in descending order
Daniel Grob added a comment - 13/May/08 12:22 PM
As a workaround you can use the following extension.
import com.ulcjava.base.application.ULCFrame;
import com.ulcjava.base.application.ULCTextField;
import com.ulcjava.base.application.datatype.ULCDateDataType;
import com.ulcjava.base.application.event.ActionEvent;
import com.ulcjava.base.application.event.IActionListener;
import com.ulcjava.base.client.IDirtyDataOwner;
import com.ulcjava.base.client.UITextField;
import com.ulcjava.testframework.development.AbstractSimpleDevelopmentTestCase;
import com.ulcjava.testframework.operator.ULCFrameOperator;
import com.ulcjava.testframework.operator.ULCTextFieldOperator;

public class PR878 extends AbstractSimpleDevelopmentTestCase {
    public void start() {
        final ULCSnippetTextField field = new ULCSnippetTextField();
        field.setDataType(new ULCDateDataType("MM.dd.yyyy"));
        field.addActionListener(new IActionListener() {
            public void actionPerformed(ActionEvent event) {
                System.out.println("Field value:      " + field.getValue());
                System.out.println("Field last input: " + field.getLastInput());
            }
        });
        
        ULCFrame frame = new ULCFrame("Snippet");
        frame.setDefaultCloseOperation(ULCFrame.TERMINATE_ON_CLOSE);
        frame.getContentPane().add(field);
        frame.pack();
        frame.setVisible(true);
    }
    
    public void testIllegalDate() {
        ULCFrameOperator frame = new ULCFrameOperator();
        ULCTextFieldOperator field = new ULCTextFieldOperator(frame);
        ULCSnippetTextField serverField = (ULCSnippetTextField)field.getULCTextField();
        
        assertNull(serverField.getValue());
        assertNull(serverField.getLastInput());
        
        field.enterText("11.25.1970");
        assertNotNull(serverField.getValue());
        assertEquals("11.25.1970", serverField.getLastInput());
        
        field.enterText("11.25.1970a");
        assertNull(serverField.getValue());
        assertEquals("11.25.1970a", serverField.getLastInput());
    }
    
    public static class ULCSnippetTextField extends ULCTextField {
        private String fLastInput;
        
        public void updateLastInput(String lastInput) {
            fLastInput = lastInput;
        }
        
        public String getLastInput() {
            return fLastInput;
        }
        
        protected String typeString() {
            return UISnippetTextField.class.getName();
        }
    }
    
    public static class UISnippetTextField extends UITextField {
        protected void updateToModel(boolean displayFormattedValue) {
            super.updateToModel(displayFormattedValue);
            
            getSession().addDirtyDataOwner(new IDirtyDataOwner() {
                public void flushDirtyData() {
                    updateStateULC("lastInput", fLastInput);
                }
            });
        }
    }
}

Daniel Grob added a comment - 14/May/08 04:47 PM
What value is displayed in case of invalid input is decided by IDataType.getDefaultValue(String newString). All data types delivered with the ULC release return null in getDefaultValue(). You can provide your own implementation of getDefaultValue() for your own behavior. See the code below.

Please note that there is a related issue (UBA-7351) that prevents you from setting invalid values from the server-side (e.g. clicking the button in the snippet below).

import com.ulcjava.base.application.ClientContext;
import com.ulcjava.base.application.DefaultCellEditor;
import com.ulcjava.base.application.ULCBorderLayoutPane;
import com.ulcjava.base.application.ULCButton;
import com.ulcjava.base.application.ULCFrame;
import com.ulcjava.base.application.ULCProxy;
import com.ulcjava.base.application.ULCScrollPane;
import com.ulcjava.base.application.ULCTable;
import com.ulcjava.base.application.ULCTextField;
import com.ulcjava.base.application.event.ActionEvent;
import com.ulcjava.base.application.event.IActionListener;
import com.ulcjava.base.application.table.AbstractTableModel;
import com.ulcjava.base.client.UIProxy;
import com.ulcjava.base.client.datatype.DataTypeConversionException;
import com.ulcjava.base.client.datatype.IDataType;
import com.ulcjava.base.shared.UlcEventConstants;
import com.ulcjava.testframework.development.AbstractSimpleDevelopmentTestCase;
import com.ulcjava.testframework.operator.ULCFrameOperator;
import com.ulcjava.testframework.operator.ULCTableOperator;
import com.ulcjava.testframework.operator.ULCTextFieldOperator;

import java.awt.Color;
import java.awt.Component;
import java.awt.KeyboardFocusManager;
import java.text.DecimalFormat;
import java.text.Format;
import java.text.ParsePosition;

import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.text.AttributeSet;

public class PR878_2 extends AbstractSimpleDevelopmentTestCase {
    public void start() {
        final ULCTextField field = new ULCTextField();
        field.setDataType(new ULCSnippetDataType());
        field.setValue("Initial Invalid Value");
        field.addActionListener(new IActionListener() {
            public void actionPerformed(ActionEvent event) {
                System.out.println("Field value: " + field.getValue());
            }
        });
        
        ULCTextField editorComponent = new ULCTextField();
        editorComponent.setDataType(new ULCSnippetDataType());
        
        ULCTable table = new ULCTable(new SnippetTableModel());
        table.setDefaultEditor(Object.class, new DefaultCellEditor(editorComponent));
        ClientContext.setModelUpdateMode(table.getModel(), UlcEventConstants.SYNCHRONOUS_MODE);
        
        ULCButton setInvalidValueButton = new ULCButton("Set Invalid Value");
        setInvalidValueButton.addActionListener(new IActionListener() {
            public void actionPerformed(ActionEvent event) {
                field.setValue("Later Invalid Value");
            }
        });
        
        ULCFrame frame = new ULCFrame("Snippet");
        frame.setDefaultCloseOperation(ULCFrame.TERMINATE_ON_CLOSE);
        frame.getContentPane().add(field, ULCBorderLayoutPane.NORTH);
        frame.getContentPane().add(new ULCScrollPane(table));
        frame.getContentPane().add(setInvalidValueButton, ULCBorderLayoutPane.SOUTH);
        frame.pack();
        frame.setVisible(true);
    }
    
    public void testIllegalInput() throws InterruptedException {
        ULCFrameOperator frame = new ULCFrameOperator();
        ULCTextFieldOperator field = new ULCTextFieldOperator(frame);
        ULCTableOperator table = new ULCTableOperator(frame);
        ULCTextField serverField = field.getULCTextField();
        SnippetTableModel serverTableModel = (SnippetTableModel)table.getULCTable().getModel();
        
        assertEquals("Initial Invalid Value", serverField.getValue());
        
        field.enterText("1234");
        assertEquals(new Long(1234), serverField.getValue());
        
        field.enterText("1234a");
        assertEquals("1234a", serverField.getValue());
        
        assertNull(serverTableModel.getLastChangedValue());
        
        table.clickForEdit(1, 2);
        ULCTextFieldOperator tableField = new ULCTextFieldOperator(table);
        tableField.enterText("1234");
        assertEquals(new Long(1234), serverTableModel.getLastChangedValue());
        
        table.clickForEdit(1, 2);
        tableField = new ULCTextFieldOperator(table);
        tableField.enterText("1234a");
        assertEquals("1234a", serverTableModel.getLastChangedValue());
    }
    
    public static class SnippetTableModel extends AbstractTableModel {
        private Object fLastChangedValue;

        
        public Object getLastChangedValue() {
            return fLastChangedValue;
        }

        public Object getValueAt(int row, int column) {
            return Integer.toString(row + column) + ":";
        }
        
        public int getRowCount() {
            return 1000;
        }
        
        public int getColumnCount() {
            return 5;
        }
        
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return true;
        }
        
        public void setValueAt(Object value, int rowIndex, int columnIndex) {
            System.out.println("SnippetTableModel.setValueAt() " + value);
            
            fLastChangedValue = value;
            
            // for simplicity => just cancel editing
            fireTableCellUpdated(rowIndex, columnIndex);
        }
    }
    
    public static class ULCSnippetDataType extends ULCProxy implements com.ulcjava.base.application.datatype.IDataType {
        protected String typeString() {
            return UISnippetDataType.class.getName();
        }
    }
    
    public static class UISnippetDataType extends UIProxy implements IDataType {
        private Format fFormat;
        
        public UISnippetDataType() {
            fFormat = new DecimalFormat("#,##0.00");
        }
        
        public Object convertToObject(String newString, Object previousValue) throws DataTypeConversionException {
            
            ParsePosition position = new ParsePosition(0);
            Object result = fFormat.parseObject(newString, position);
            Component dataTypeTarget = findDataTypeTarget();
            if (position.getErrorIndex() >= 0 || position.getIndex() < newString.length()) {
                if (dataTypeTarget != null) {
                    dataTypeTarget.setBackground(Color.RED);
                }
                
                throw new DataTypeConversionException(newString);
            } else {
                if (dataTypeTarget != null) {
                    dataTypeTarget.setBackground(Color.WHITE);
                }
                
                return result;
            }
        }
        
        public String convertToString(Object object, boolean forEditing) {
            if (object == null) {
                return null;
            } else if (object instanceof String) {
                return (String)object;
            } else {
                return fFormat.format(object);
            }
        }
        
        public String filterInput(int position, String newString, String currentText, AttributeSet attribute) {
            // no filtering
            return newString;
        }
        
        public Object getDefaultValue(String newString) {
            // invalid values will be replaced by the input string
            return newString;
        }

        private Component findDataTypeTarget() {
            if (getSession().isHandlingRequest()) {
                return null;
            }
            
            Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner();
            
            // the focus owner might be part of an table editor
            // => use the table instead of the focus owner as target
            JTable tableFocusOwner = (JTable)SwingUtilities.getAncestorOfClass(JTable.class, focusOwner);
            if (tableFocusOwner != null && tableFocusOwner.isEditing()) {
                focusOwner = tableFocusOwner;
            }
            
            return focusOwner;
        }
    }
}