⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keysequencetext.java

📁 jfa2ce 源码帮助开发人员更好的理解运用
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************* * Copyright (c) 2004, 2006 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 *******************************************************************************/package org.eclipse.jface.bindings.keys;import java.util.ArrayList;import java.util.Collection;import java.util.Collections;import java.util.Iterator;import java.util.List;import java.util.TreeSet;import org.eclipse.jface.util.IPropertyChangeListener;import org.eclipse.jface.util.PropertyChangeEvent;import org.eclipse.swt.SWT;import org.eclipse.swt.events.DisposeEvent;import org.eclipse.swt.events.DisposeListener;import org.eclipse.swt.events.FocusEvent;import org.eclipse.swt.events.FocusListener;import org.eclipse.swt.events.ModifyEvent;import org.eclipse.swt.events.ModifyListener;import org.eclipse.swt.graphics.Font;import org.eclipse.swt.graphics.Point;import org.eclipse.swt.widgets.Display;import org.eclipse.swt.widgets.Event;import org.eclipse.swt.widgets.Listener;import org.eclipse.swt.widgets.Text;/** * <p> * A wrapper around the SWT text widget that traps literal key presses and * converts them into key sequences for display. There are two types of key * strokes that are displayed: complete and incomplete. A complete key stroke is * one with a natural key, while an incomplete one has no natural key. * Incomplete key strokes are only displayed until they are made complete or * their component key presses are released. * </p> *  * @since 3.1 */public final class KeySequenceText {	/**	 * A key listener that traps incoming events and displays them in the	 * wrapped text field. It has no effect on traversal operations.	 */	private class KeyTrapListener implements Listener {		/**		 * The index at which insertion should occur. This is used if there is a		 * replacement occurring in the middle of the stroke, and the first key		 * stroke was incomplete.		 */		private int insertionIndex = -1;		/**		 * Resets the insertion index to point nowhere. In other words, it is		 * set to <code>-1</code>.		 */		void clearInsertionIndex() {			insertionIndex = -1;		}		/**		 * Deletes the current selection. If there is no selection, then it		 * deletes the last key stroke.		 * 		 * @param keyStrokes		 *            The key strokes from which to delete. This list must not		 *            be <code>null</code>, and must represent a valid key		 *            sequence.		 */		private final KeyStroke[] deleteKeyStroke(final KeyStroke[] keyStrokes) {			clearInsertionIndex();			if (hasSelection()) {				/*				 * Delete the current selection -- disallowing incomplete				 * strokes in the middle of the sequence.				 */				final KeyStroke[][] deletedKeyStrokes = new KeyStroke[1][];				deleteSelection(keyStrokes, false, deletedKeyStrokes);				return deletedKeyStrokes[0];			}			// Remove the last key stroke.			if (keyStrokes.length > 0) {				final int newKeyStrokesLength = keyStrokes.length - 1;				final KeyStroke[] newKeyStrokes = new KeyStroke[newKeyStrokesLength];				System.arraycopy(keyStrokes, 0, newKeyStrokes, 0,						newKeyStrokesLength);				return newKeyStrokes;			}			return keyStrokes;		}		/**		 * Handles the key pressed and released events on the wrapped text		 * widget. This makes sure to either add the pressed key to the		 * temporary key stroke, or complete the current temporary key stroke		 * and prompt for the next. In the case of a key release, this makes		 * sure that the temporary stroke is correctly displayed --		 * corresponding with modifier keys that may have been released.		 * 		 * @param event		 *            The triggering event; must not be <code>null</code>.		 */		public void handleEvent(Event event) {			KeyStroke[] keyStrokes = getKeySequence().getKeyStrokes();			// Dispatch the event to the correct handler.			if (event.type == SWT.KeyDown) {				keyStrokes = handleKeyDown(event, keyStrokes);			} else if (event.type == SWT.KeyUp) {				keyStrokes = handleKeyUp(event, keyStrokes);			}			// Update the underlying widget.			setKeySequence(KeySequence.getInstance(keyStrokes));			// Prevent the event from reaching the widget.			event.doit = false;		}		/**		 * Handles the case where the key event is an <code>SWT.KeyDown</code>		 * event. This either causes a deletion (if it is an unmodified		 * backspace key stroke), or an insertion (if it is any other key).		 * 		 * @param event		 *            The trigger key down event; must not be <code>null</code>.		 * @param keyStrokes		 *            The current list of key strokes. This valud must not be		 *            <code>null</code>, and it must represent a valid key		 *            sequence.		 */		private KeyStroke[] handleKeyDown(Event event, KeyStroke[] keyStrokes) {			// Is it an unmodified backspace character?			if ((event.character == SWT.BS) && (event.stateMask == 0)) {				return deleteKeyStroke(keyStrokes);			}			return insertKeyStroke(event, keyStrokes);		}		/**		 * Handles the case where the key event is an <code>SWT.KeyUp</code>		 * event. This resets the insertion index. If there is an incomplete		 * stroke, then that incomplete stroke is modified to match the keys		 * that are still held. If no keys are held, then the incomplete stroke		 * is removed.		 * 		 * @param event		 *            The triggering event; must not be <code>null</code>		 * @param keyStrokes		 *            The key strokes that are part of the current key sequence;		 *            these key strokes are guaranteed to represent a valid key		 *            sequence. This value must not be <code>null</code>.		 */		private final KeyStroke[] handleKeyUp(final Event event,				final KeyStroke[] keyStrokes) {			if (hasIncompleteStroke()) {				/*				 * Figure out the SWT integer representation of the remaining				 * values.				 */				Event mockEvent = new Event();				if ((event.keyCode & SWT.MODIFIER_MASK) != 0) {					// This key up is a modifier key being released.					mockEvent.stateMask = event.stateMask - event.keyCode;				} else {					/*					 * This key up is the other end of a key down that was					 * trapped by the operating system or window manager.					 */					mockEvent.stateMask = event.stateMask;				}				/*				 * Get a reasonable facsimile of the stroke that is still				 * pressed.				 */				int key = SWTKeySupport						.convertEventToUnmodifiedAccelerator(mockEvent);				KeyStroke remainingStroke = SWTKeySupport						.convertAcceleratorToKeyStroke(key);				final int keyStrokesLength = keyStrokes.length;				final KeyStroke[] newKeyStrokes;				if ((keyStrokesLength > 0)						&& (remainingStroke.getModifierKeys() != 0)) {					newKeyStrokes = new KeyStroke[keyStrokesLength];					System.arraycopy(keyStrokes, 0, newKeyStrokes, 0,							keyStrokesLength - 1);					newKeyStrokes[keyStrokesLength - 1] = remainingStroke;				} else if (keyStrokesLength > 0) {					newKeyStrokes = new KeyStroke[keyStrokesLength - 1];					System.arraycopy(keyStrokes, 0, newKeyStrokes, 0,							keyStrokesLength - 1);				} else if (remainingStroke.getModifierKeys() != 0) {					newKeyStrokes = new KeyStroke[keyStrokesLength + 1];					System.arraycopy(keyStrokes, 0, newKeyStrokes, 0,							keyStrokesLength);					newKeyStrokes[keyStrokesLength] = remainingStroke;				} else {					newKeyStrokes = keyStrokes;				}				return newKeyStrokes;			}			return keyStrokes;		}		/**		 * <p>		 * Handles the case where a key down event is leading to a key stroke		 * being inserted. The current selection is deleted, and an invalid		 * remanents of the stroke are also removed. The insertion is carried		 * out at the cursor position.		 * </p>		 * <p>		 * If only a natural key is selected (as part of a larger key stroke),		 * then it is possible for the user to press a natural key to replace		 * the old natural key. In this situation, pressing any modifier keys		 * will replace the whole thing.		 * </p>		 * <p>		 * If the insertion point is not at the end of the sequence, then		 * incomplete strokes will not be immediately inserted. Only when the		 * sequence is completed is the stroke inserted. This is a requirement		 * as the widget must always represent a valid key sequence. The		 * insertion point is tracked using <code>insertionIndex</code>,		 * which is an index into the key stroke array.		 * </p>		 * 		 * @param event		 *            The triggering key down event; must not be		 *            <code>null</code>.		 * @param keyStrokes		 *            The key strokes into which the current stroke should be		 *            inserted. This value must not be <code>null</code>, and		 *            must represent a valid key sequence.		 */		private final KeyStroke[] insertKeyStroke(final Event event,				KeyStroke[] keyStrokes) {			// Compute the key stroke to insert.			int key = SWTKeySupport.convertEventToUnmodifiedAccelerator(event);			KeyStroke stroke = SWTKeySupport.convertAcceleratorToKeyStroke(key);			/*			 * Only insert the stroke if it is *not ScrollLock. Let's not get			 * silly			 */			if ((SWT.NUM_LOCK == stroke.getNaturalKey())					|| (SWT.CAPS_LOCK == stroke.getNaturalKey())					|| (SWT.SCROLL_LOCK == stroke.getNaturalKey())) {				return keyStrokes;			}			if (insertionIndex != -1) {				// There is a previous replacement still going on.				if (stroke.isComplete()) {					keyStrokes = insertStrokeAt(keyStrokes, stroke,							insertionIndex);					clearInsertionIndex();				}			} else if (hasSelection()) {				// There is a selection that needs to be replaced.				final KeyStroke[][] deletedKeyStrokes = new KeyStroke[1][];				insertionIndex = deleteSelection(keyStrokes, stroke						.isComplete(), deletedKeyStrokes);				keyStrokes = deletedKeyStrokes[0];				if ((stroke.isComplete())						|| (insertionIndex >= keyStrokes.length)) {					keyStrokes = insertStrokeAt(keyStrokes, stroke,							insertionIndex);					clearInsertionIndex();				}			} else {				// No selection, so remove the incomplete stroke, if any				if ((hasIncompleteStroke()) && (keyStrokes.length > 0)) {					final KeyStroke[] newKeyStrokes = new KeyStroke[keyStrokes.length - 1];					System.arraycopy(keyStrokes, 0, newKeyStrokes, 0,							keyStrokes.length - 1);					keyStrokes = newKeyStrokes;				}				// And then add the new stroke.				if ((keyStrokes.length == 0)						|| (insertionIndex >= keyStrokes.length)						|| (isCursorInLastPosition())) {					keyStrokes = insertStrokeAt(keyStrokes, stroke,							keyStrokes.length);					clearInsertionIndex();				} else {					/*					 * I'm just getting the insertionIndex here. No actual					 * deletion should occur.					 */					final KeyStroke[][] deletedKeyStrokes = new KeyStroke[1][];					insertionIndex = deleteSelection(keyStrokes, stroke							.isComplete(), deletedKeyStrokes);					keyStrokes = deletedKeyStrokes[0];					if (stroke.isComplete()) {						keyStrokes = insertStrokeAt(keyStrokes, stroke,								insertionIndex);						clearInsertionIndex();					}				}			}			return keyStrokes;		}	}	/**	 * A traversal listener that blocks all traversal except for tabs and arrow	 * keys.	 */	private class TraversalFilter implements Listener {		/**		 * Handles the traverse event on the text field wrapped by this class.		 * It swallows all traverse events example for tab and arrow key		 * navigation. The other forms of navigation can be reached by tabbing		 * off of the control.		 * 		 * @param event		 *            The trigger event; must not be <code>null</code>.		 */		public void handleEvent(Event event) {			switch (event.detail) {			case SWT.TRAVERSE_ESCAPE:			case SWT.TRAVERSE_MNEMONIC:			case SWT.TRAVERSE_NONE:			case SWT.TRAVERSE_PAGE_NEXT:			case SWT.TRAVERSE_PAGE_PREVIOUS:			case SWT.TRAVERSE_RETURN:				event.type = SWT.None;				event.doit = false;				break;			case SWT.TRAVERSE_TAB_NEXT:			case SWT.TRAVERSE_TAB_PREVIOUS:				// Check if modifiers other than just 'Shift' were				// down.				if ((event.stateMask & (SWT.MODIFIER_MASK ^ SWT.SHIFT)) != 0) {					// Modifiers other than shift were down.					event.type = SWT.None;					event.doit = false;					break;				}				// fall through -- either no modifiers, or just shift.			case SWT.TRAVERSE_ARROW_NEXT:			case SWT.TRAVERSE_ARROW_PREVIOUS:			default:				// Let the traversal happen, but clear the incomplete				// stroke				if (hasIncompleteStroke()) {					final KeyStroke[] oldKeyStrokes = getKeySequence()							.getKeyStrokes();					final int newKeyStrokesLength = oldKeyStrokes.length - 1;					if (newKeyStrokesLength >= 1) {						final KeyStroke[] newKeyStrokes = new KeyStroke[newKeyStrokesLength];						System.arraycopy(oldKeyStrokes, 0, newKeyStrokes, 0,								newKeyStrokesLength);						setKeySequence(KeySequence.getInstance(newKeyStrokes));					} else {						setKeySequence(KeySequence.getInstance());					}				}			}		}	}	/**	 * The manager resposible for installing and removing the traversal filter	 * when the key sequence entry widget gains and loses focus.	 */	private class TraversalFilterManager implements FocusListener {		/** The managed filter. We only need one instance. */		private TraversalFilter filter = new TraversalFilter();		/**		 * Attaches the global traversal filter.		 * 		 * @param event		 *            Ignored.		 */		public void focusGained(FocusEvent event) {			Display.getCurrent().addFilter(SWT.Traverse, filter);		}		/**		 * Detaches the global traversal filter.		 * 		 * @param event		 *            Ignored.		 */		public void focusLost(FocusEvent event) {			Display.getCurrent().removeFilter(SWT.Traverse, filter);		}	}	/**	 * A modification listener that makes sure that external events to this	 * class (i.e., direct modification of the underlying text) do not break	 * this class' view of the world.	 */	private class UpdateSequenceListener implements ModifyListener {		/**		 * Handles the modify event on the underlying text widget.		 * 		 * @param event		 *            The triggering event; ignored.		 */		public void modifyText(ModifyEvent event) {			try {				// The original sequence.				KeySequence originalSequence = getKeySequence();				// The new sequence drawn from the text.				String contents = getText();				KeySequence newSequence = KeySequence.getInstance(contents);				// Check to see if they're the same.				if (!originalSequence.equals(newSequence)) {					setKeySequence(newSequence);				}			} catch (ParseException e) {				// Abort any cut/paste-driven modifications				setKeySequence(getKeySequence());			}		}	}	static {		TreeSet trappedKeys = new TreeSet();		trappedKeys.add(SWTKeySupport.convertAcceleratorToKeyStroke(SWT.TAB));		trappedKeys.add(SWTKeySupport.convertAcceleratorToKeyStroke(SWT.TAB				| SWT.SHIFT));		trappedKeys.add(SWTKeySupport.convertAcceleratorToKeyStroke(SWT.BS));		List trappedKeyList = new ArrayList(trappedKeys);		TRAPPED_KEYS = Collections.unmodifiableList(trappedKeyList);	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -