Package org.openquark.gems.client

Source Code of org.openquark.gems.client.RecordFieldSelectionGemFieldNameEditor$TextListener

/*
* Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*     * Redistributions of source code must retain the above copyright notice,
*       this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of Business Objects nor the names of its contributors
*       may be used to endorse or promote products derived from this software
*       without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/


/*
* RecordFieldSelectionGemFieldNameEditor.java
* Creation date: Dec 13, 2006.
* By: Neil Corkum
*/
package org.openquark.gems.client;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.swing.ComboBoxEditor;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;

import org.openquark.cal.compiler.FieldName;
import org.openquark.cal.compiler.LanguageInfo;
import org.openquark.cal.compiler.RecordType;
import org.openquark.cal.compiler.TypeExpr;
import org.openquark.gems.client.Gem.PartInput;
import org.openquark.gems.client.utilities.ExtendedUndoManager;

/**
* This class is responsible for determining the correct field name editor to
* display for a given Record Field Selection Gem. The editor provided will depend on the
* types connected to the Record Field Selection Gem, if any.
* @author Neil Corkum
*/
public class RecordFieldSelectionGemFieldNameEditor {

    /**
     * The RecordFieldSelection Gem this editor will be acting on.
     */
    private final RecordFieldSelectionGem recordFieldSelectionGem;

    /** this is used to record the fixed state before any modifications are made
     * so that the gem can be restored to it's original state if the user aborts the
     * edit.
     */
    private final boolean oldFixedState;
   
    /** this is used to record the select field name before any modifications are made
     * so that the gem can be restored to it's original state if the user aborts the
     * edit.
     */
    private final String oldFieldName;
   
    /**
     * TableTop reference.
     */
    private final TableTop tableTop;
   
    /**
     * This interface is used so the combo box editor can listen for special text events -
     * when the text is updated so that the combo box can be resized, and when
     * the editor is finished so that the combo box can close.
     */
    private interface TextListener {

        /**
         * This is called when the text is edited and the editor has resized
         * @param dimension
         */
        void resize(Dimension dimension);
       
        /**
         * This is called when the enter or escape is pressed and the editor is closing.
         */
        void closing();
    }
   
    /**
     * An editable text field that accepts valid CAL identifiers for field names
     * @author Neil Corkum
     */
    private class RecordFieldSelectionTextEditor extends EditableIdentifierNameField {
       
        //a set containing field names that are disallowed - i.e. in the lacks constraints
        final private Set<FieldName> disallowedFields;
       
        //listener to receive test editor messages - resize and select
        public TextListener textListener = null;

        private static final long serialVersionUID = -3629150370610668038L;

        /** Keeps track of whether this component has been removed from the tableTop */ // is there a better way??
        private boolean removed = false;

        /** The undo manager for this text field. */
        private final ExtendedUndoManager undoManager;
       
        /**
         * Constructor for a new EditableGemNameField.
         */
        public RecordFieldSelectionTextEditor(Set<FieldName> disallowedFields) {
            super();
          
            this.disallowedFields = disallowedFields;
           
            String initialText = oldFieldName;
           
            // set the initial text
            setInitialText(initialText);
            setText(initialText);
           
           
            // set the font of the text
            setFont(GemCutterPaintHelper.getTitleFont());
           
            // update the size of the text area to reflect the size of the text
            updateSize();
           
            // starts out with all text selected
            selectAll();
           
            // set up the undo manager
            undoManager = new ExtendedUndoManager();
            getDocument().addUndoableEditListener(undoManager);
           
            // moving focus away commits the text entered and closes this component
            addFocusListener(new FocusAdapter(){
                @Override
                public void focusLost(FocusEvent e) {
                    commitText();
                }
            });
           
            // intercept some key events           
            addKeyListener(new KeyAdapter(){
                @Override
                public void keyPressed(KeyEvent e) {
                    int keyCode = e.getKeyCode();
                   
                    // pressing "ESC" cancels text entry and closes this component
                    if (keyCode == KeyEvent.VK_ESCAPE) {
                        cancelEntry();
                    }
                   
                    KeyStroke keyStroke = KeyStroke.getKeyStrokeForEvent(e);
                   
                    // handle undo and redo
                    if (keyStroke.equals(GemCutterActionKeys.ACCELERATOR_UNDO)) {
                        if (undoManager.canUndo()) {
                            undoManager.undo();
                            textChanged();
                        }
                        e.consume();
                       
                    } else if (keyStroke.equals(GemCutterActionKeys.ACCELERATOR_REDO)) {
                        if (undoManager.canRedo()) {
                            undoManager.redo();
                            textChanged();
                        }
                        e.consume();
                       
                    } else if (keyStroke.equals(GemCutterActionKeys.ACCELERATOR_ARRANGE_GRAPH) ||
                            keyStroke.equals(GemCutterActionKeys.ACCELERATOR_FIT_TABLETOP) ||
                            keyStroke.equals(GemCutterActionKeys.ACCELERATOR_NEW)) {
                       
                        // We have to intercept accelerators for these so that the GemCutter
                        // doesn't get screwed up when the text field doesn't match the action result.
                        e.consume();
                    }
                }
            });
           
            // ensure the cursor is visible when it moves
            addCaretListener(new CaretListener(){
                public void caretUpdate(CaretEvent e){
                    // just ensure the caret is visible
                    scrollCaretToVisible();
                }
            });
        }

        /**
         * Returns whether a name is a valid name for this field
         * @param name String the name to check for validity
         */
        @Override
        protected boolean isValidName(String name){
            return !disallowedFields.contains(FieldName.make(name)) && LanguageInfo.isValidFieldName(name);
        }
       
        /**
         * Creates the default implementation of the model to be used at construction if one isn't explicitly given.
         * Overridden to return a LetterNumberUnderscorePoundDocument.
         * Creation date: (10/29/01 6:50:22 PM)
         * @return Document the default model implementation.
         */
        @Override
        protected Document createDefaultModel() {
            return new LetterNumberUnderscorePoundDocument();
        }
       
        /**
         * Cancel text entry (press "ESC" ..)
         */
        @Override
        protected void cancelEntry(){
            // Revert to the last valid name
            setText(getInitialText());
           
            // What to do, what to do..
            textCommittedInvalid();
        }
       
        /**
         * If this has been placed in the tabletop, make sure the caret is visible
         */
        void scrollCaretToVisible(){
            if (tableTop.getTableTopPanel().isAncestorOf(this)) {
                int dotPos = getCaret().getDot();
                try {
                    Rectangle caretRect = modelToView(dotPos);
                   
                    if (caretRect != null) {
                        caretRect.width += 1;
                        Rectangle convertedRect =
                            SwingUtilities.convertRectangle(this, caretRect, tableTop.getTableTopPanel());
                        tableTop.getTableTopPanel().scrollRectToVisible(convertedRect);
                    }
                } catch (BadLocationException e) {
                    // Nowhere to scroll.  Oh well.
                }
            }
        }

        /**
         * Close this window (if not already gone..)
         */
        synchronized void closeField(){
            // check if we've removed this already
            if (!removed) {
                removed = true;
                tableTop.getTableTopPanel().remove(this);
                tableTop.getTableTopPanel().repaint(RecordFieldSelectionTextEditor.this.getBounds());

                // we have to do this or else you can just keep typing (..!)
                setEnabled(false);
               
                // Update the tabletop for the new gem graph state.
                //  Among other things, this will ensure arg name disambiguation with respect to the new collector name.
                tableTop.updateForGemGraph();
               
                if (textListener != null) {
                    textListener.closing();
                }
            }
            // trigger a focusLost() on this component if it had focus
            tableTop.getTableTopPanel().requestFocus();
        }
       
        /**
         * Notify that the text of this text field has changed.  Called upon insertUpdate() and remove() completion.
         * Eg. If the current result is not valid, maybe do something about it (like warn the user somehow..)
         */
        @Override
        protected void textChanged(){
            super.textChanged();
           
            tableTop.resizeForGems();

            // ensure the caret is visible
            scrollCaretToVisible();
           
        }

        /**
         * Take appropriate action if the result of the text change is invalid.
         */
        @Override
        protected void textChangeInvalid(){
            // Signal the user.
            setForeground(Color.lightGray);

            // update the gem field name to display the new text (despite being invalid)
            updateGemFieldName(getText());

            // set a tooltip saying that the text is invalid
            String text = GemCutter.getResourceString("ToolTip_InvalidFieldName");
            String[] lines = ToolTipHelpers.splitTextIntoLines(text, 300, getFont(), ((Graphics2D)tableTop.getTableTopPanel().getGraphics()).getFontRenderContext());
            text = "<html>" + lines [0];
            for (int i = 1; i < lines.length; i++) {
                text += "<br>" + lines[i];
            }
            setToolTipText(text + "</html>");

            // update the text field to reflect the new size of the text
            updateSize();
        }

        /**
         * Take appropriate action if the result of the text change is valid.
         */
        @Override
        protected void textChangeValid(){
            // do validation checking - paint text colors differently depending on the result
            setForeground(Color.black);

            // update the gem name to display the new text
            updateGemFieldName(getText());

            // clear any tooltip saying that the text is invalid
            setToolTipText(null);
           
            // update the text field to reflect the new size of the text
            updateSize();
        }

        /**
         * Take appropriate action if the text committed is valid.
         */
        @Override
        protected void textCommittedInvalid(){
            revertEdit();
           
            // close this component
            closeField();
        }

        /**
         * Take appropriate action if the text committed is valid.
         */
        @Override
        protected void textCommittedValid(){
            commitEdit(getText());

            // close this component
            closeField();
        }
       
        /**
         * Update the size of this field.
         */
        private void updateSize(){
            Insets insets = getInsets();

            // The X dimension is based on the size of the text for the name (plus some margins)
            FontMetrics fm = getFontMetrics(getFont());

            // Calculate width and height
            int newWidth = fm.stringWidth(getText()) + insets.right + insets.left + 1;
            int newHeight = fm.getHeight();

            setSize(new Dimension(newWidth, newHeight));
           
            if (textListener != null) {
                textListener.resize(new Dimension(newWidth, newHeight));
            }
        }
       
        /**
         * Update the name of the gem represented by this text field.
         * @param newName String the new name for the let gem
         */
        private void updateGemFieldName(String newName){
            recordFieldSelectionGem.setFieldName(newName);
        }
    }
   
    /**
     * A combo box for editing the field name to select from records of which
     * we have some knowledge of the fields contained in the record. It
     * provides an option to enter a field of the user's choice, if the record
     * is polymorphic.
     * @author Neil Corkum
     */
    private class RecordFieldSelectionComboEditor extends JComboBox {

        private static final long serialVersionUID = -1520958490445008579L;
       
        /** this is set when the combo box is closed - it is used to prevent the
         * combo box for duplicating actions when it is closing and committing
         * a value. This can happen when multiple events calling for the control
         * to close are fired. The combo box cannot be reused once it has been closed.*/
        private boolean closed = false;
       
        /**
         * This class implements a custom editor for the combo box that is based on a supplied
         * RecordFieldSelectionTextEditor. This ensures the combo text editing is
         * identical to plain record field text editor.
         */
        private class ComboEditor implements  ComboBoxEditor, DocumentListener {
           
            /** the actual text editor used by this component*/
            private final RecordFieldSelectionTextEditor text;

            /**
             * Constructs the combo box editor with a specific editor
             * @param textEditor the editor to use
             */
            public ComboEditor(RecordFieldSelectionTextEditor textEditor) {
                text = textEditor;
            }

            /**
             * {@inheritDoc}
             */
            public Component getEditorComponent() {
                return text;
            }

            /**
             * {@inheritDoc}
             */
            public void setItem(Object item) {
                text.setText(item.toString());
            }

            /**
             * {@inheritDoc}
             */
            public Object getItem() {
                return text.getText();
            }

            /**
             * {@inheritDoc}
             */
            public void selectAll() { text.selectAll(); }

            /**
             * {@inheritDoc}
             */
            public void addActionListener(ActionListener l) {
                text.addActionListener(l);
            }

            /**
             * {@inheritDoc}
             */
            public void removeActionListener(ActionListener l) {
                text.removeActionListener(l);
            }

            /**
             * {@inheritDoc}
             */
            public void insertUpdate(DocumentEvent e) {  }
           
            /**
             * {@inheritDoc}
             */
            public void removeUpdate(DocumentEvent e) {  }
           
            /**
             * {@inheritDoc}
             */
            public void changedUpdate(DocumentEvent e) { }

        }
       
        /**
         * Constructor for a RecordFieldSelectionComboEditor.
         * @param obj objects to put in combo box list. Can include RecordFieldName
         * and String (String only used for the "other field" item).
         */
        private RecordFieldSelectionComboEditor(Object obj[], RecordFieldSelectionTextEditor textEditor) {
            super(obj);
           
            setFont(GemCutterPaintHelper.getTitleFont());
           
            setSelectedItem(oldFieldName);
           
            //if a text editor is supplied, the field is editable
            if (textEditor != null) {
                setEditable(true);
                setEditor(new ComboEditor(textEditor));
            }
           
            // popup menu listener to determine when to close editor and commit value
            addPopupMenuListener(new PopupMenuListener() {
               
                ///** marks whether popup has been canceled.
                boolean cancelled = false; // is there a better way to do this?
               
                public void popupMenuCanceled(PopupMenuEvent e) {
                    // selection canceled; revert to previous value
                    cancelFieldSelection();
                    cancelled = true;
                }
               
                synchronized public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
                    // popup menu closing; get rid of editor and commit value if editor not canceled
                    if (!isClosed()){
                        setClosed();
                        tableTop.getTableTopPanel().remove(RecordFieldSelectionComboEditor.this);
                        if (!cancelled) {
                            commitFieldSelection();
                        }
                    }
                }
               
                public void popupMenuWillBecomeVisible(PopupMenuEvent e) {         
                }
            });

            //listen for when the value is set
            addActionListener(new ActionListener() {
                synchronized public void actionPerformed(ActionEvent a) {
                    if (isClosed()) {
                        setClosed();
                        tableTop.getTableTopPanel().remove(RecordFieldSelectionComboEditor.this);
                        commitFieldSelection();
                    }
                }          
            });
           
             
        }
       
        /**
         * @return true if the combo box has been marked as closed
         */
        public boolean isClosed() {
            return closed;
        }
       
        /**
         * mark the combo box as closed
         */
        public void setClosed() {
            closed = true;
        }
       
        /**
         * Saves change to the selected field to select.
         */
        void commitFieldSelection() {
            if (getSelectedIndex() >= 0) {
                commitEdit(getSelectedItem().toString());
            }

        }
       
        /**
         * Cancels any changes made to the selected field, and reverts to the
         * field name present before creating the editor.
         */
        void cancelFieldSelection() {
            revertEdit();
        }
       

       
        /**
         * Override to ensure that popup to control the visibility of the drop down options for non-polymorphic records
         */
        @Override
        public void requestFocus() {
            if (!isEditable()) {
              // always show the popup while the combo box is showing for non polymorphic records.
              setPopupVisible(true);
            }
            super.requestFocus();           
        }

    }

    /**
     * Constructor for an RecordFieldSelectionGemFieldNameEditor. To make an editor, use the static
     * method makeEditor().
     * @param recordFieldSelectionGem The RecordFieldSelection Gem this editor is associated with
     * @param tableTop A reference to the table top on which the RecordFieldSelection Gem is present
     */
    private RecordFieldSelectionGemFieldNameEditor(RecordFieldSelectionGem recordFieldSelectionGem, TableTop tableTop) {
        this.recordFieldSelectionGem = recordFieldSelectionGem;
        this.tableTop = tableTop;
        this.oldFieldName = recordFieldSelectionGem.getFieldNameString();
        this.oldFixedState = recordFieldSelectionGem.isFieldFixed();

        //update the gem to fixed so the rendering is in fixed mode
        this.recordFieldSelectionGem.setFieldFixed(true);

        //force the gem to be redrawn
        this.recordFieldSelectionGem.setFieldName("");
        this.recordFieldSelectionGem.setFieldName(oldFieldName);
       
    }
   
    /**
     * Creates an editor for the field name to be selected. This method
     * selects the appropriate type of editor - edit box or combo box,
     * or nothing if the field may not be edited due to type constraints
     * @param recordFieldSelectionGem The RecordFieldSelection Gem this editor is associated with
     * @param tableTop A reference to the table top on which the RecordFieldSelection Gem is present
     * @return the component for editing the field to be selected, or null if the field cannot be edited.
     */
    public static JComponent makeEditor(RecordFieldSelectionGem recordFieldSelectionGem, TableTop tableTop) {
        // field editor to return
        final JComponent fieldEditor;
        final PartInput inputPart = recordFieldSelectionGem.getInputPart();
       
        final TypeExpr inputTypeExpr;
        TypeExpr outputTypeExpr = TypeExpr.makeParametricType();
       
        //determine the input type
        if (inputPart.isConnected() ) {
            inputTypeExpr = inputPart.inferType(tableTop.getTypeCheckInfo()) ;
            if (recordFieldSelectionGem.getOutputPart().getConnection() != null) {
                outputTypeExpr = recordFieldSelectionGem.getOutputPart().inferType(tableTop.getTypeCheckInfo());
            }
        } else if (inputPart.isBurnt() && recordFieldSelectionGem.getOutputPart().getConnection() != null) {  
            TypeExpr outputType = recordFieldSelectionGem.getOutputPart().inferType(tableTop.getTypeCheckInfo());
           
            if (outputType.getArity() > 0) {
                TypeExpr[] typePieces = outputType.getTypePieces(1);
                inputTypeExpr = typePieces[0];
                outputTypeExpr = typePieces[1];
            } else {
                inputTypeExpr = null;
            }
        } else {
            inputTypeExpr = null;
        }

        RecordFieldSelectionGemFieldNameEditor editor = new RecordFieldSelectionGemFieldNameEditor(recordFieldSelectionGem, tableTop);
       
        //create the appropriate editor type
        if (inputTypeExpr instanceof RecordType) {
            RecordType inputType = (RecordType)inputTypeExpr;
           
            Set<FieldName> disallowedFields = new HashSet<FieldName>(inputType.getLacksFieldsSet());
            disallowedFields.removeAll(inputType.getHasFieldNames());
           
            List<FieldName> possibleFields = RecordFieldSelectionGem.possibleFieldNames(inputType, outputTypeExpr, tableTop.getCurrentModuleTypeInfo());
                 
            if (inputType.isRecordPolymorphic()) {
                if (possibleFields.isEmpty()) {
                    fieldEditor = editor.createTextFieldEditor(disallowedFields);
                } else {
                    fieldEditor = editor.createComboFieldEditor(possibleFields, editor.createTextFieldEditor(disallowedFields));
                }
            } else {
                if (possibleFields.size() == 1) {
                    //there is only one option - no reason to edit
                    fieldEditor = null;
                } else {
                    fieldEditor = editor.createComboFieldEditor(possibleFields, null)
                }
            }
        } else {
            // input generic/not connected; use text editor
            fieldEditor = editor.createTextFieldEditor(Collections.<FieldName>emptySet());
        }
       
        return fieldEditor;
    }
   
    /**
     * Commits an edit and creates an undo action.
     */
    private void commitEdit(String newFieldName) {
        recordFieldSelectionGem.setFieldFixed(true);
        recordFieldSelectionGem.setFieldName(newFieldName);
        tableTop.getUndoableEditSupport().postEdit(new UndoableChangeFieldSelectionEdit(tableTop, recordFieldSelectionGem, oldFieldName, oldFixedState));
        tableTop.updateForGemGraph();
    }
   
    /**
     * Reverts any changes to the record field selection gem
     */
    private void revertEdit() {
        recordFieldSelectionGem.setFieldFixed(oldFixedState);
        recordFieldSelectionGem.setFieldName(oldFieldName);
    }
   
    /**
     * Creates a text field-style editor. This is used when it is appropriate
     * to allow the user to input any valid field name for extraction.
     */
    private RecordFieldSelectionTextEditor createTextFieldEditor(Set<FieldName> disallowedFields) {
        // not connected to record input; display text field for editing field name
        RecordFieldSelectionTextEditor fieldEditor = new RecordFieldSelectionTextEditor(disallowedFields);
       
        fieldEditor.setFont(GemCutterPaintHelper.getTitleFont());

        // ensure the cursor is visible
        fieldEditor.scrollCaretToVisible();
       
        return fieldEditor;
    }
   
    /**
     * Creates a combo box-style editor. This is used when some or all of the
     * fields available in a record to be extracted from are known.
     * @param validFieldNames a list of possible field names to display in the combo box
     * @param textEditor if the record type is polymorphic this is the editor used to enter new field names, if the record is non polymorphic this should be null.
     */
    private JComponent createComboFieldEditor(final List<FieldName> validFieldNames, final RecordFieldSelectionTextEditor textEditor) {
       
        final RecordFieldSelectionComboEditor fieldComboEditor = new RecordFieldSelectionComboEditor(validFieldNames.toArray(), textEditor);

        //set the selection to the existing value of it is in the list of values
        fieldComboEditor.setSelectedItem(oldFieldName);       
        final int currentIndex = validFieldNames.indexOf(FieldName.make(oldFieldName));
        if (currentIndex >=0 ) {
            fieldComboEditor.setSelectedIndex(currentIndex);
        }
           
        fieldComboEditor.setSize(fieldComboEditor.getPreferredSize());
       
        //if the text editor is supplied we must catch size changes and closes
        if (textEditor != null) {
            textEditor.selectAll();
           
            final int sizeDiff = fieldComboEditor.getPreferredSize().width - textEditor.getPreferredSize().width;
           
            //listen for text update and closing events
            textEditor.textListener =
                new TextListener() {
                    public void resize(Dimension d) {
                        fieldComboEditor.setSize(d.width + sizeDiff,fieldComboEditor.getHeight() );
                    }
                    public void closing() {
                        if (!fieldComboEditor.isClosed()){
                            fieldComboEditor.setClosed();
                            tableTop.getTableTopPanel().remove(fieldComboEditor);
                        }
                    }
                };

            //listen for when the text value is set value is set
            textEditor.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent a) {
                    if (!fieldComboEditor.isClosed()){
                        fieldComboEditor.setClosed();
                        tableTop.getTableTopPanel().remove(fieldComboEditor);
                       
                        if (!textEditor.isValidName(textEditor.getText())) {
                            textEditor.cancelEntry();
                        }

                        fieldComboEditor.commitFieldSelection();
                    }
                }          
            });
        } else {
            //if there is no text field we must watch for focus lost events
            //which would would otherwise be taken care of by the text field
            fieldComboEditor.addFocusListener(new FocusListener() {
                public void focusGained(FocusEvent e) {}
                public void focusLost(FocusEvent e) {
                    if (!fieldComboEditor.isClosed()){
                        fieldComboEditor.setClosed();
                        tableTop.getTableTopPanel().remove(fieldComboEditor);
                        fieldComboEditor.cancelFieldSelection();                   
                    }
                }
               
            });
            //catch the escape key
            fieldComboEditor.addKeyListener(new KeyListener() {
                public void keyPressed(KeyEvent e) {}
                public void keyReleased(KeyEvent e)  {}
                public void keyTyped(KeyEvent e)  {
                    int keyCode = e.getKeyCode();
                   
                    // pressing "ESC" cancels entry and closes this component
                    if (keyCode == KeyEvent.VK_ESCAPE) {
                        if (!fieldComboEditor.isClosed()){
                            fieldComboEditor.setClosed();
                            tableTop.getTableTopPanel().remove(fieldComboEditor);
                            fieldComboEditor.cancelFieldSelection();                           
                        }
                    }
                   
                }
            });          
        }
        return fieldComboEditor;
    }
   
}
TOP

Related Classes of org.openquark.gems.client.RecordFieldSelectionGemFieldNameEditor$TextListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.