Package hidb2.gui.util

Source Code of hidb2.gui.util.NumericCellEditor

/**
* This file is part of HIDB2.
*
* HIDB2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HIDB2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser Public License
* along with HIDB2.  If not, see <http://www.gnu.org/licenses/>.
*/
package hidb2.gui.util;

import hidb2.kern.AttrType;
import hidb2.kern.HIDBConst;

import java.text.MessageFormat;
import java.util.logging.Logger;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Text;

/**
* Adaptation/Specialisation of TextCellEditor for Numeric Inputs.
* Type controlled : C_TYPE_INT, C_TYPE_FLOAT, C_TYPE_DOUBLE, C_TYPE_VECTOR3D
* Default : C_TYPE_DOUBLE
*/
public class NumericCellEditor extends CellEditor implements HIDBConst
  {
  final static Logger log = Logger.getLogger("hidb2.gui.util");

  /** Characters allowed for numeric float input */
  public final static String S_NUMDBLCHARS = "0123456789.,+-eE";

  /** Characters allowed for numeric integer input */
  public final static String S_NUMINTCHARS = "0123456789";

  /** Character used to separate vector values */
  public final static String S_VECTSEP = ";";

  /** Characters allowed for numeric vector input */
  public final static String S_NUMVECTCHARS = S_NUMDBLCHARS + S_VECTSEP;

  /**
   * The text control; initially <code>null</code>.
   */
  protected Text text;

  private ModifyListener modifyListener;

  /**
   * State information for updating action enablement
   */
  private boolean isSelection = false;

  private boolean isDeleteable = false;

  private boolean isSelectable = false;

  /** Default type is Double - Type chosen at creation time */
  private AttrType _dataType = AttrType.T_Double;

  /**
   * Default TextCellEditor style
   * specify no borders on text widget as cell outline in table already
   * provides the look of a border.
   */
  private static final int defaultStyle = SWT.SINGLE;

  /**
   * Creates a new text string cell editor with no control
   * The cell editor value is the string itself, which is initially the empty
   * string. Initially, the cell editor has no cell validator.
   */
  public NumericCellEditor()
    {
    setStyle(defaultStyle);
    }

  /**
   * Creates a new text string cell editor parented under the given control.
   * The cell editor value is the string itself, which is initially the empty string.
   * Initially, the cell editor has no cell validator.
   *
   * @param parent the parent control
   */
  public NumericCellEditor(Composite parent)
    {
    this(parent, defaultStyle);
    }

  /**
   * Creates a new text string cell editor parented under the given control.
   * The cell editor value is the string itself, which is initially the empty string.
   * Initially, the cell editor has no cell validator.
   *
   * @param parent the parent control
   * @param style the style bits
   */
  public NumericCellEditor(Composite parent, int style)
    {
    super(parent, style);
    }

  /**
   * Creates a new text string cell editor parented under the given control.
   * The cell editor value is the string itself, which is initially the empty string.
   * Initially, the cell editor has no cell validator.
   *
   * @param parent the parent control
   * @param style the style bits
   * @param dataType    Type of numeric to be controlled : C_TYPE_INT, C_TYPE_FLOAT, C_TYPE_DOUBLE, C_TYPE_VECTOR3D
   */
  public NumericCellEditor(Composite parent, int style, AttrType dataType)
    {
    super(parent, style);
    _dataType = dataType;
    }

  /**
   * Checks to see if the "deletable" state (can delete/
   * nothing to delete) has changed and if so fire an
   * enablement changed notification.
   */
  private void checkDeleteable()
    {
    boolean oldIsDeleteable = isDeleteable;
    isDeleteable = isDeleteEnabled();
    if (oldIsDeleteable != isDeleteable)
      {
      fireEnablementChanged(DELETE);
      }
    }

  /**
   * Checks to see if the "selectable" state (can select)
   * has changed and if so fire an enablement changed notification.
   */
  private void checkSelectable()
    {
    boolean oldIsSelectable = isSelectable;
    isSelectable = isSelectAllEnabled();
    if (oldIsSelectable != isSelectable)
      {
      fireEnablementChanged(SELECT_ALL);
      }
    }

  /**
   * Checks to see if the selection state (selection /
   * no selection) has changed and if so fire an
   * enablement changed notification.
   */
  private void checkSelection()
    {
    boolean oldIsSelection = isSelection;
    isSelection = text.getSelectionCount() > 0;
    if (oldIsSelection != isSelection)
      {
      fireEnablementChanged(COPY);
      fireEnablementChanged(CUT);
      }
    }

  /* (non-Javadoc)
   * Method declared on CellEditor.
   */
  protected Control createControl(Composite parent)
    {
    text = new Text(parent, getStyle());
    text.addSelectionListener(new SelectionAdapter()
      {
        public void widgetDefaultSelected(SelectionEvent e)
          {
          handleDefaultSelection(e);
          }
      });
    text.addKeyListener(new KeyAdapter()
      {
        // hook key pressed - see PR 14201 
        public void keyPressed(KeyEvent e)
          {
          keyReleaseOccured(e);

          // as a result of processing the above call, clients may have
          // disposed this cell editor
          if ((getControl() == null) || getControl().isDisposed())
            {
            return;
            }
          checkSelection(); // see explanation below
          checkDeleteable();
          checkSelectable();
          }
      });
    text.addTraverseListener(new TraverseListener()
      {
        public void keyTraversed(TraverseEvent e)
          {
          if (e.detail == SWT.TRAVERSE_ESCAPE || e.detail == SWT.TRAVERSE_RETURN)
            {
            e.doit = false;
            }
          }
      });
    // We really want a selection listener but it is not supported so we
    // use a key listener and a mouse listener to know when selection changes
    // may have occurred
    text.addMouseListener(new MouseAdapter()
      {
        public void mouseUp(MouseEvent e)
          {
          checkSelection();
          checkDeleteable();
          checkSelectable();
          }
      });
    text.addFocusListener(new FocusAdapter()
      {
        public void focusLost(FocusEvent e)
          {
          NumericCellEditor.this.focusLost();
          }
      });
    text.setFont(parent.getFont());
    text.setBackground(parent.getBackground());
    text.setText("");//$NON-NLS-1$
    text.addModifyListener(getModifyListener());
    return text;
    }

  /**
   * The <code>TextCellEditor</code> implementation of
   * this <code>CellEditor</code> framework method returns
   * the text string.
   *
   * @return the text string
   */
  protected Object doGetValue()
    {
    String s = text.getText();
    Object num = null;

    try
      {
      switch (_dataType)
        {
        case T_Integer:
          num = Integer.parseInt(s);
          break;
        case T_Double:
          num = Double.parseDouble(s);
          break;
        //      case T_Float:
        //        num = Float.parseFloat(s);
        //        break;

        //      case C_TYPE_VECTOR3D:
        //        String[] ts = s.split(S_VECTSEP);
        //
        //        num = new Vector3d(Double.parseDouble(ts[0]), Double.parseDouble(ts[1]), Double.parseDouble(ts[2]));
        //        break;
        }
      }

    catch (java.lang.NumberFormatException nfex)
      {
      log.warning("Format Exception for :" + (s == null ? "null" : s));
      }

    return num;
    }

  /* (non-Javadoc)
   * Method declared on CellEditor.
   */
  protected void doSetFocus()
    {
    if (text != null)
      {
      text.selectAll();
      text.setFocus();
      checkSelection();
      checkDeleteable();
      checkSelectable();
      }
    }

  /**
   * The <code>TextCellEditor</code> implementation of
   * this <code>CellEditor</code> framework method accepts
   * a text string (type <code>String</code>).
   *
   * @param value a numeric value (type <code>Double</code> or <code>Float</code> or <code>Integer</code>)
   */
  protected void doSetValue(Object value)
    {
    Assert.isTrue(text != null && (((_dataType == AttrType.T_Double) && (value instanceof Double))
    //                || ((_dataType == C_TYPE_FLOAT) && (value instanceof Float))
        || ((_dataType == AttrType.T_Integer) && (value instanceof Integer))
        //                || ((_dataType == C_TYPE_VECTOR3D) && (value instanceof Vector3d))
        ));

    String sval = "";

    switch (_dataType)
      {
      case T_Integer:
        sval = ((Integer) value).toString();
        break;
      case T_Double:
        sval = ((Double) value).toString();
        break;
      //      case C_TYPE_FLOAT:
      //        sval = ((Float) value).toString();
      //        break;
      //      case C_TYPE_VECTOR3D:
      //        Vector3d v = (Vector3d) value;
      //        sval = Double.toString(v.x) + S_VECTSEP + Double.toString(v.y) + S_VECTSEP + Double.toString(v.z);
      //        break;
      }

    text.removeModifyListener(getModifyListener());
    text.setText(sval);
    text.addModifyListener(getModifyListener());
    }

  /**
   * Processes a modify event that occurred in this text cell editor.
   * This framework method performs validation and sets the error message
   * accordingly, and then reports a change via <code>fireEditorValueChanged</code>.
   * Subclasses should call this method at appropriate times. Subclasses
   * may extend or reimplement.
   *
   * @param e the SWT modify event
   */
  protected void editOccured(ModifyEvent e)
    {
    String value = text.getText();
    if (value == null)
      {
      value = "";//$NON-NLS-1$
      }
    Object typedValue = value;
    boolean oldValidState = isValueValid();
    boolean newValidState = isCorrect(typedValue);
    if (typedValue == null && newValidState)
      {
      Assert.isTrue(false, "Validator isn't limiting the cell editor's type range");//$NON-NLS-1$
      }
    if (!newValidState)
      {
      // try to insert the current value into the error message.
      setErrorMessage(MessageFormat.format(getErrorMessage(), new Object[]
        {
          value
        }));
      }
    valueChanged(oldValidState, newValidState);
    }

  /**
   * Since a text editor field is scrollable we don't
   * set a minimumSize.
   */
  public LayoutData getLayoutData()
    {
    return new LayoutData();
    }

  /**
   * Return the modify listener.
   */
  private ModifyListener getModifyListener()
    {
    if (modifyListener == null)
      {
      modifyListener = new ModifyListener()
        {
          public void modifyText(ModifyEvent e)
            {
            editOccured(e);
            }
        };
      }
    return modifyListener;
    }

  /**
   * Handles a default selection event from the text control by applying the editor
   * value and deactivating this cell editor.
   *
   * @param event the selection event
   */
  protected void handleDefaultSelection(SelectionEvent event)
    {
    // same with enter-key handling code in keyReleaseOccured(e);
    fireApplyEditorValue();
    deactivate();
    }

  /**
   * The <code>TextCellEditor</code>  implementation of this
   * <code>CellEditor</code> method returns <code>true</code> if
   * the current selection is not empty.
   */
  public boolean isCopyEnabled()
    {
    if (text == null || text.isDisposed())
      {
      return false;
      }
    return text.getSelectionCount() > 0;
    }

  /**
   * The <code>TextCellEditor</code>  implementation of this
   * <code>CellEditor</code> method returns <code>true</code> if
   * the current selection is not empty.
   */
  public boolean isCutEnabled()
    {
    if (text == null || text.isDisposed())
      {
      return false;
      }
    return text.getSelectionCount() > 0;
    }

  /**
   * The <code>TextCellEditor</code>  implementation of this
   * <code>CellEditor</code> method returns <code>true</code>
   * if there is a selection or if the caret is not positioned
   * at the end of the text.
   */
  public boolean isDeleteEnabled()
    {
    if (text == null || text.isDisposed())
      {
      return false;
      }
    return text.getSelectionCount() > 0 || text.getCaretPosition() < text.getCharCount();
    }

  /**
   * The <code>TextCellEditor</code>  implementation of this
   * <code>CellEditor</code> method always returns <code>true</code>.
   */
  public boolean isPasteEnabled()
    {
    if (text == null || text.isDisposed())
      {
      return false;
      }
    return true;
    }

  /**
   * Check if save all is enabled
   * @return true if it is
   */
  public boolean isSaveAllEnabled()
    {
    if (text == null || text.isDisposed())
      {
      return false;
      }
    return true;
    }

  /**
   * Returns <code>true</code> if this cell editor is
   * able to perform the select all action.
   * <p>
   * This default implementation always returns
   * <code>false</code>.
   * </p>
   * <p>
   * Subclasses may override
   * </p>
   * @return <code>true</code> if select all is possible,
   *  <code>false</code> otherwise
   */
  public boolean isSelectAllEnabled()
    {
    if (text == null || text.isDisposed())
      {
      return false;
      }
    return text.getCharCount() > 0;
    }

  /**
   * Processes a key release event that occurred in this cell editor.
   * <p>
   * The <code>TextCellEditor</code> implementation of this framework method
   * ignores when the RETURN key is pressed since this is handled in
   * <code>handleDefaultSelection</code>.
   * An exception is made for Ctrl+Enter for multi-line texts, since
   * a default selection event is not sent in this case.
   * </p>
   *
   * @param keyEvent the key event
   */
  protected void keyReleaseOccured(KeyEvent keyEvent)
    {
    if (keyEvent.character == '\r')
      { // Return key
      // Enter is handled in handleDefaultSelection.
      // Do not apply the editor value in response to an Enter key event
      // since this can be received from the IME when the intent is -not-
      // to apply the value. 
      // See bug 39074 [CellEditors] [DBCS] canna input mode fires bogus event from Text Control
      //
      // An exception is made for Ctrl+Enter for multi-line texts, since
      // a default selection event is not sent in this case.
      if (text != null && !text.isDisposed() && (text.getStyle() & SWT.MULTI) != 0)
        {
        if ((keyEvent.stateMask & SWT.CTRL) != 0)
          {
          super.keyReleaseOccured(keyEvent);
          }
        }
      return;
      }

    boolean accept = Character.isISOControl(keyEvent.character);

    switch (_dataType)
      {
      case T_Integer:
        accept |= S_NUMINTCHARS.indexOf(keyEvent.character) >= 0;
        break;

      case T_Double:
        //      case C_TYPE_FLOAT:
        accept |= S_NUMDBLCHARS.indexOf(keyEvent.character) >= 0;
        break;

      //      case C_TYPE_VECTOR3D:
      //        accept |= S_NUMVECTCHARS.indexOf(keyEvent.character) >= 0;
      //        break;
      }

    // Try to filter characters
    if (accept)
      {
      super.keyReleaseOccured(keyEvent);
      }
    else
      {
      keyEvent.doit = false;
      }
    }

  /**
   * The <code>TextCellEditor</code> implementation of this
   * <code>CellEditor</code> method copies the
   * current selection to the clipboard.
   */
  public void performCopy()
    {
    text.copy();
    }

  /**
   * The <code>TextCellEditor</code> implementation of this
   * <code>CellEditor</code> method cuts the
   * current selection to the clipboard.
   */
  public void performCut()
    {
    text.cut();
    checkSelection();
    checkDeleteable();
    checkSelectable();
    }

  /**
   * The <code>TextCellEditor</code> implementation of this
   * <code>CellEditor</code> method deletes the
   * current selection or, if there is no selection,
   * the character next character from the current position.
   */
  public void performDelete()
    {
    if (text.getSelectionCount() > 0)
      {
      // remove the contents of the current selection
      text.insert(""); //$NON-NLS-1$
      }
    else
      {
      // remove the next character
      int pos = text.getCaretPosition();
      if (pos < text.getCharCount())
        {
        text.setSelection(pos, pos + 1);
        text.insert(""); //$NON-NLS-1$
        }
      }
    checkSelection();
    checkDeleteable();
    checkSelectable();
    }

  /**
   * The <code>TextCellEditor</code> implementation of this
   * <code>CellEditor</code> method pastes the
   * the clipboard contents over the current selection.
   */
  public void performPaste()
    {
    text.paste();
    checkSelection();
    checkDeleteable();
    checkSelectable();
    }

  /**
   * The <code>TextCellEditor</code> implementation of this
   * <code>CellEditor</code> method selects all of the
   * current text.
   */
  public void performSelectAll()
    {
    text.selectAll();
    checkSelection();
    checkDeleteable();
    }

  /**
   * This implementation of
   * {@link CellEditor#dependsOnExternalFocusListener()} returns false if the
   * current instance's class is TextCellEditor, and true otherwise.
   * Subclasses that hook their own focus listener should override this method
   * and return false. See also bug 58777.
   */
  protected boolean dependsOnExternalFocusListener()
    {
    return getClass() != NumericCellEditor.class;
    }
  }
TOP

Related Classes of hidb2.gui.util.NumericCellEditor

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.