diff dwtx/jface/viewers/TextCellEditor.d @ 10:b6c35faf97c8

Viewers
author Frank Benoit <benoit@tionex.de>
date Mon, 31 Mar 2008 00:47:19 +0200
parents
children ea8ff534f622
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/viewers/TextCellEditor.d	Mon Mar 31 00:47:19 2008 +0200
@@ -0,0 +1,485 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+
+module dwtx.jface.viewers.TextCellEditor;
+
+import dwtx.jface.viewers.CellEditor;
+
+import dwt.DWT;
+import dwt.events.FocusAdapter;
+import dwt.events.FocusEvent;
+import dwt.events.KeyAdapter;
+import dwt.events.KeyEvent;
+import dwt.events.ModifyEvent;
+import dwt.events.ModifyListener;
+import dwt.events.MouseAdapter;
+import dwt.events.MouseEvent;
+import dwt.events.SelectionAdapter;
+import dwt.events.SelectionEvent;
+import dwt.events.TraverseEvent;
+import dwt.events.TraverseListener;
+import dwt.widgets.Composite;
+import dwt.widgets.Control;
+import dwt.widgets.Text;
+import dwtx.core.runtime.Assert;
+
+import dwt.dwthelper.utils;
+import tango.text.convert.Format;
+
+/**
+ * A cell editor that manages a text entry field.
+ * The cell editor's value is the text string itself.
+ * <p>
+ * This class may be instantiated; it is not intended to be subclassed.
+ * </p>
+ */
+public class TextCellEditor : CellEditor {
+
+    /**
+     * The text control; initially <code>null</code>.
+     */
+    protected Text text;
+
+    private ModifyListener modifyListener;
+
+    /**
+     * State information for updating action enablement
+     */
+    private bool isSelection = false;
+
+    private bool isDeleteable = false;
+
+    private bool isSelectable = false;
+
+    /**
+     * Default TextCellEditor style
+     * specify no borders on text widget as cell outline in table already
+     * provides the look of a border.
+     */
+    private static const int defaultStyle = DWT.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.
+     *
+     * @since 2.1
+     */
+    public this() {
+        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 this(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
+     * @since 2.1
+     */
+    public this(Composite parent, int style) {
+        super(parent, style);
+    }
+
+    /**
+     * 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() {
+        bool oldIsDeleteable = isDeleteable;
+        isDeleteable = isDeleteEnabled();
+        if (oldIsDeleteable !is 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() {
+        bool oldIsSelectable = isSelectable;
+        isSelectable = isSelectAllEnabled();
+        if (oldIsSelectable !is 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() {
+        bool oldIsSelection = isSelection;
+        isSelection = text.getSelectionCount() > 0;
+        if (oldIsSelection !is isSelection) {
+            fireEnablementChanged(COPY);
+            fireEnablementChanged(CUT);
+        }
+    }
+
+    /* (non-Javadoc)
+     * Method declared on CellEditor.
+     */
+    protected Control createControl(Composite parent) {
+        text = new Text(parent, getStyle());
+        text.addSelectionListener(new class SelectionAdapter {
+            public void widgetDefaultSelected(SelectionEvent e) {
+                handleDefaultSelection(e);
+            }
+        });
+        text.addKeyListener(new class 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() is null) || getControl().isDisposed()) {
+                    return;
+                }
+                checkSelection(); // see explanation below
+                checkDeleteable();
+                checkSelectable();
+            }
+        });
+        text.addTraverseListener(new class TraverseListener {
+            public void keyTraversed(TraverseEvent e) {
+                if (e.detail is DWT.TRAVERSE_ESCAPE
+                        || e.detail is DWT.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 class MouseAdapter {
+            public void mouseUp(MouseEvent e) {
+                checkSelection();
+                checkDeleteable();
+                checkSelectable();
+            }
+        });
+        text.addFocusListener(new class FocusAdapter {
+            public void focusLost(FocusEvent e) {
+                this.outer.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() {
+        return new ArrayWrapperString(text.getText());
+    }
+
+    /* (non-Javadoc)
+     * Method declared on CellEditor.
+     */
+    protected void doSetFocus() {
+        if (text !is 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 text string (type <code>String</code>)
+     */
+    protected void doSetValue(Object value) {
+        Assert.isTrue(text !is null && ( cast(ArrayWrapperString)value ));
+        text.removeModifyListener(getModifyListener());
+        text.setText((cast(ArrayWrapperString)value).array);
+        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 DWT modify event
+     */
+    protected void editOccured(ModifyEvent e) {
+        String value = text.getText();
+        if (value is null) {
+            value = "";//$NON-NLS-1$
+        }
+        Object typedValue = new ArrayWrapperString(value);
+        bool oldValidState = isValueValid();
+        bool newValidState = isCorrect(typedValue);
+        if (typedValue is 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(Format(getErrorMessage(), 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 is null) {
+            modifyListener = new class 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
+     *
+     * @since 3.0
+     */
+    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 bool isCopyEnabled() {
+        if (text is 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 bool isCutEnabled() {
+        if (text is 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 bool isDeleteEnabled() {
+        if (text is 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 bool isPasteEnabled() {
+        if (text is null || text.isDisposed()) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Check if save all is enabled
+     * @return true if it is
+     */
+    public bool isSaveAllEnabled() {
+        if (text is 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 bool isSelectAllEnabled() {
+        if (text is 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 is '\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 !is null && !text.isDisposed()
+                    && (text.getStyle() & DWT.MULTI) !is 0) {
+                if ((keyEvent.stateMask & DWT.CTRL) !is 0) {
+                    super.keyReleaseOccured(keyEvent);
+                }
+            }
+            return;
+        }
+        super.keyReleaseOccured(keyEvent);
+    }
+
+    /**
+     * 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();
+    }
+
+    bool dependsOnExternalFocusListener() {
+        return this.classinfo !is TextCellEditor.classinfo;
+    }
+}