Made the following changes: (1) renamed DuffPane's copySelection, pasteSelection, etc. to copy, paste and so forth, which override JTextComponent's methods by those names: Andres, please change the translation tool accordingly to use these new methods if that it necessary; (2) in order to allow for easier integration of Jskad with other tools such as QuillDriver, I changed DuffPane to rely on a Keymap instead of a KeyListener for its default key intercepts; this addresses the comments to bug 617156. Note that I have been working on Mac OS X and have not extensively tested my changes on a PC yet.

This commit is contained in:
eg3p 2003-04-02 20:37:14 +00:00
parent e95e41aef0
commit 7a495bc720
2 changed files with 104 additions and 174 deletions

View file

@ -43,7 +43,7 @@ import org.thdl.util.StatusBar;
* @author Edward Garrett, Tibetan and Himalayan Digital Library
* @version 1.0
*/
public class DuffPane extends TibetanPane implements KeyListener, FocusListener {
public class DuffPane extends TibetanPane implements FocusListener, KeyListener {
/**
* The status bar to update with messages about the current input mode.
* Are we expecting a vowel? a subscript? et cetera.
@ -192,6 +192,9 @@ public class DuffPane extends TibetanPane implements KeyListener, FocusListener
private MutableAttributeSet romanAttributeSet;
private Clipboard rtfBoard;
private Hashtable actions;
/** Initializes this object. All constructors should call
this. */
@ -293,8 +296,71 @@ public class DuffPane extends TibetanPane implements KeyListener, FocusListener
addKeyListener(this);
addFocusListener(this);
setupKeymap();
}
/**
* This method sets up the keymap used by DuffPane editors.
* The keymap defines a default behavior for key presses
* in both Tibetan and Roman mode.
*/
private void setupKeymap() {
Action defaultAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
if (!DuffPane.this.isEditable()) return;
if ( ((e.getModifiers() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK) ||
((e.getModifiers() & ActionEvent.ALT_MASK) == ActionEvent.ALT_MASK) ||
((e.getModifiers() & ActionEvent.META_MASK) == ActionEvent.META_MASK)) {
DuffPane.this.initKeyboard();
return;
}
if (e.getActionCommand() != null) {
String key = e.getActionCommand();
if (DuffPane.this.getSelectionStart() < DuffPane.this.getSelectionEnd())
DuffPane.this.replaceSelection("");
if (key != null) {
if (isTibetan) processTibetanChar(key.charAt(0), true);
else {
MutableAttributeSet inputAtts = DuffPane.this.getInputAttributes();
inputAtts.addAttributes(romanAttributeSet);
processRomanChar(key, inputAtts);
}
}
}
}
};
createActionTable(this);
Keymap keymap = addKeymap("DuffBindings", getKeymap());
keymap.setDefaultAction(defaultAction);
setKeymap(keymap);
}
private void createActionTable(JTextComponent textComponent) {
actions = new Hashtable();
Action[] actionsArray = textComponent.getActions();
for (int i = 0; i < actionsArray.length; i++) {
Action a = actionsArray[i];
actions.put(a.getValue(Action.NAME), a);
//System.out.println(a.getValue(Action.NAME));
}
}
private Action getActionByName(String name) {
return (Action)(actions.get(name));
}
/**
* This method sets up the Tibetan keyboard. Initially it is called
* by the constructor, but it is also called internally whenever
@ -885,13 +951,13 @@ class RTFSelection implements ClipboardOwner, Transferable {
/** Copies the current selection to the system clipboard, unless
cut-and-paste operations are disabled. */
public void copyCurrentSelection() {
public void copy() {
copy(getSelectionStart(), getSelectionEnd(), false);
}
/** If this.isEditable(), then this copies the current selection
to the system clipboard and then deletes it. */
public void cutCurrentSelection() {
public void cut() {
copy(getSelectionStart(), getSelectionEnd(), true);
}
@ -951,6 +1017,10 @@ class RTFSelection implements ClipboardOwner, Transferable {
}
}
public void paste() {
paste(getSelectionStart());
}
/**
* Pastes the contents of the system clipboard into this object's
* document, at the specified position. The only kind of
@ -1063,197 +1133,63 @@ public void paste(int offset) {
public void disableCutAndPaste() {
isCutAndPasteEnabled = false;
}
/**
* This method is required as part of the
* implementation of the KeyListener
* interface.
*
* Basically this method only handles action keys -
* Escape, Ctrl-c, Ctrl-x, etc, and TAB and ENTER.
* Other keystrokes are handled by keyTyped.
* Required by contract with the KeyListener interface,
* this method initializes the keyboard
* when an action key is pressed. It leaves the
* behavior up to the Keymap of this DuffPane.
*/
public void keyPressed(KeyEvent e) {
// FIXME: exceptions thrown here do not cause the program to fail, even in development mode.
if (e.isActionKey())
initKeyboard();
switch (e.getKeyCode()) {
case KeyEvent.VK_ESCAPE:
e.consume();
initKeyboard();
break;
case KeyEvent.VK_A:
if (e.isControlDown() && isCutAndPasteEnabled) {
e.consume();
setSelectionStart(0);
setSelectionEnd(getTibDoc().getLength());
}
break;
case KeyEvent.VK_C:
if (e.isControlDown() && isCutAndPasteEnabled) {
e.consume();
copy(getSelectionStart(), getSelectionEnd(), false);
}
break;
case KeyEvent.VK_X:
if (e.isControlDown() && isCutAndPasteEnabled) {
e.consume();
copy(getSelectionStart(), getSelectionEnd(), true);
}
break;
case KeyEvent.VK_V:
if (e.isControlDown() && isCutAndPasteEnabled) {
e.consume();
// since paste is substituting selected text, first delete
deleteCurrentSelection();
paste(caret.getDot());
}
break;
case KeyEvent.VK_TAB:
e.consume();
if (this.isEditable()) {
initKeyboard();
if (isTibetan)
getTibDoc().appendDuff(caret.getDot(),"\t",TibetanMachineWeb.getAttributeSet(1));
else
append("\t", romanAttributeSet);
}
break;
case KeyEvent.VK_ENTER:
e.consume();
if (this.isEditable()) {
initKeyboard();
if (isTibetan)
getTibDoc().appendDuff(caret.getDot(),"\n",TibetanMachineWeb.getAttributeSet(1)); // FIXME does this work on all platforms?
else
append("\n", romanAttributeSet); // FIXME does this work on all platforms?
}
break;
}
}
/**
* Required of implementations of the Key Listener interface,
* this method does (almost) nothing.
* Required by contract with the KeyListener interface,
* this method does nothing.
*
* @param e a KeyEvent
*/
public void keyTyped(KeyEvent e) { }
/**
* Required by contract with the Key Listener interface,
* this method initializes the keyboard if the user presses
* backspace.
*
* @param e the KeyEvent
*/
public void keyReleased(KeyEvent e) {
// FIXME: exceptions thrown here do not cause the program to fail, even in development mode.
/*
* Apparently it works best to check for backspace
* and init the keyboard here in key released
* though i don't really know why...
*/
if (e.getKeyCode() == KeyEvent.VK_BACK_SPACE)
initKeyboard();
}
/**
* Required of implementations of the KeyListener interface,
* this method handles the pressing of non-control and non-action keys. If the user
* is in Tibetan typing mode, then the KeyEvent
* e is consumed, and passed on to {@link #processTibetan(KeyEvent e)}, which
* contains the meat of the keyboard logic. If the user is in English mode, then
* {@link #append(String s, MutableAttributeSet attr) append} is called.
*
* @param e a KeyEvent
*/
public void keyTyped(KeyEvent e) {
// FIXME: exceptions thrown here do not cause the program to fail, even in development mode.
e.consume();
// Respect setEditable(boolean):
if (!this.isEditable())
return;
if (isTibetan)
processTibetan(e);
else {
if (e.isControlDown() || e.isAltDown())
return;
char c = e.getKeyChar();
switch (c) {
case KeyEvent.VK_TAB:
case KeyEvent.VK_ENTER:
case KeyEvent.VK_ESCAPE:
break;
case KeyEvent.VK_BACK_SPACE:
backSpace(1);
break;
default:
append(String.valueOf(c), romanAttributeSet);
}
private void processRomanChar(String key, MutableAttributeSet attSet) {
switch (key.charAt(0)) {
case KeyEvent.VK_BACK_SPACE:
break;
default:
append(key, attSet);
}
}
/**
* Interprets a key typed during Tibetan input mode.
* This method keeps track of which characters the user has and is typing,
* and also of whether or not the user is in stacking
* mode. Most of the keyboard logic can be found here.
*
* If there is a nonnull status bar to be updated (passed to the
* constructor), let's explain to the user which mode we're in, why
* their keypress has changed nothing, etc. At present, this is really
* for developers to understand what's going on. For example, if you
* type s-g-r, you see a single glyph, a three-letter stack, but if you
* type s-d-r, you see two glyphs. If you examine the status bar,
* you'll see that the thing determining that is
* TibTextUtils.getGlyphs, which in turn relies on 'tibwn.ini'.
*
* @param e a KeyEvent */
public void processTibetan(KeyEvent kev) {
/* DLC FIXME: in the extended wylie keyboard, there's a
* potential problem: typing ai gets you what aai gets you,
* not what i gets you. Typing ae gets you what e gets
* you. */
boolean shouldIBackSpace = true;
// We don't handle just any old keypress. We handle only the
// ones that enter text.
if (kev.isControlDown() || kev.isAltDown())
return;
{
int start = getSelectionStart();
int end = getSelectionEnd();
if (start != end) {
if (kev.getKeyCode() != KeyEvent.VK_ESCAPE) {
try {
initKeyboard();
getTibDoc().remove(start, end-start);
shouldIBackSpace = false;
}
catch (BadLocationException ble) {
}
}
}
}
processTibetanChar(kev.getKeyChar(), shouldIBackSpace);
}
/** Utility method used by processTibetan(keyEvent).
/** Utility method called by DuffPane's Keymap as the
default behavior when the user is in Tibetan typing mode.
@param c the character the user entered in whatever keyboard
is in use
@param shouldIBackSpace false iff a press of the backspace key
should not backspace, such as when you've selected some text
and then pressed backspace
@see #processTibetan(KeyEvent) */
and then pressed backspace ACTUALLY I DONT KNOW IF THIS IS
NECESSARY ANYMORE SINCE BACKSPACE IS NOW HANDLED BY THE
DEFAULT KEYMAP FOR JTEXTCOMPONENT */
private void processTibetanChar(char c, boolean shouldIBackSpace) {
// Have we modified the status bar?
@ -1364,12 +1300,6 @@ public void paste(int offset) {
appendStatus(" (because you typed enter, tab, or escape)");
break;
case KeyEvent.VK_BACK_SPACE:
if (shouldIBackSpace) {
backSpace(1);
break;
}
default:
String val = String.valueOf(c);

View file

@ -809,11 +809,11 @@ public class Jskad extends JPanel implements DocumentListener {
}
private void cutSelection() {
dp.cutCurrentSelection();
dp.cut();
}
private void copySelection() {
dp.copyCurrentSelection();
dp.copy();
}
private void pasteSelection() {