Code Search for Developers
 
 
  

AutoCompletion.java from Magellan-Client at Krugle


Show AutoCompletion.java syntax highlighted

/*
 *  Copyright (C) 2000-2004 Roger Butenuth, Andreas Gampe,
 *                          Stefan Goetz, Sebastian Pappert,
 *                          Klaas Prause, Enno Rehling,
 *                          Sebastian Tusk, Ulrich Kuester,
 *                          Ilja Pavkovic
 *
 * This file is part of the Eressea Java Code Base, see the
 * file LICENSING for the licensing information applying to
 * this file.
 *
 */

package com.eressea.completion;

import java.awt.Component;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Collections;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.Timer;
import javax.swing.border.BevelBorder;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.CaretListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
import javax.swing.text.SimpleAttributeSet;

import com.eressea.event.GameDataEvent;
import com.eressea.event.GameDataListener;
import com.eressea.event.SelectionEvent;
import com.eressea.event.SelectionListener;
import com.eressea.main.MagellanContext;
import com.eressea.swing.InternationalizedDialog;
import com.eressea.swing.completion.CompletionGUI;
import com.eressea.swing.completion.ListCompletionGUI;
import com.eressea.swing.completion.MarkedTextCompletionGUI;
import com.eressea.swing.completion.NoneCompletionGUI;
import com.eressea.swing.completion.OrderEditorList;
import com.eressea.swing.preferences.PreferencesAdapter;
import com.eressea.util.CollectionFactory;
import com.eressea.util.PropertiesHelper;
import com.eressea.util.Translations;
import com.eressea.util.logging.Logger;

/**
 * DOCUMENT ME!
 *
 * @author Andreas Gampe, Ulrich Küster
 */
public class AutoCompletion implements SelectionListener, KeyListener, ActionListener,
									   CaretListener, FocusListener, GameDataListener,
									   CompleterSettingsProvider
{
	private static final Logger log = Logger.getInstance(AutoCompletion.class);
	private OrderEditorList editors;
	private Vector completionGUIs;
	private CompletionGUI currentGUI;
	private Completer completer;
	private int lastCaretPosition = 0;

	/**
	 * Keys for cycling, completing and breaking. completerKeys[] completerKeys[][0]
	 * completerKeys[1]     cycle forward modifier key cycle backward        modifier key complete
	 * modifier key     break modifier key
	 */
	private int completerKeys[][];
	private Timer timer;
	private List completions = null;
	private int completionIndex = 0;
	private String lastStub = null;
	private boolean enableAutoCompletion = true;

	// limits the completion of the make-order to items
	// whose resources are available
	private boolean limitMakeCompletion = true;
	private boolean emptyStubMode = false;
	private String activeGUI = null;
	private int time = 150;

	// self defined completion objects (mapping a name (String) to a value (String))
	private Map selfDefinedCompletions = new Hashtable();
    private Map selfDefinedCompletions2 = new Hashtable();

	protected Properties settings;
    private Properties completionSettings;

	/**
	 * Creates new AutoCompletion
	 *
	 * @param context The magellan context holding Client-Global informations
	 */
	public AutoCompletion(MagellanContext context) {
		this.settings = context.getProperties();
		this.completionSettings = context.getCompletionProperties();
		context.getEventDispatcher().addSelectionListener(this);
		context.getEventDispatcher().addGameDataListener(this);

		editors = null;
		completionGUIs = new Vector();
		currentGUI = null;
		completer = null;

		loadSettings();
		timer = new Timer(time, this);

		addCompletionGUI(new ListCompletionGUI());
		addCompletionGUI(new MarkedTextCompletionGUI());
		addCompletionGUI(new NoneCompletionGUI());

		// let the AutoCompletion choose the current GUI
		loadComplete();
	}

	protected void loadSettings() {
		String autoCmp = settings.getProperty("AutoCompletion.Enabled");

		if(autoCmp != null) {
			enableAutoCompletion = autoCmp.equalsIgnoreCase("true");
		} else {
			autoCmp = settings.getProperty("OrderEditingPanel.useOrderCompletion");

			if(autoCmp != null) {
				enableAutoCompletion = Boolean.valueOf(autoCmp).booleanValue();
				settings.remove("OrderEditingPanel.useOrderCompletion");
				settings.setProperty("AutoCompletion.Enabled",
									 enableAutoCompletion ? "true" : "false");
			} else {
				enableAutoCompletion = true;
			}
		}

		limitMakeCompletion = settings.getProperty("AutoCompletion.limitMakeCompletion", "true")
									  .equalsIgnoreCase("true");

		String stubMode = settings.getProperty("AutoCompletion.EmptyStubMode", "true");
		emptyStubMode = stubMode.equalsIgnoreCase("true");

		activeGUI = settings.getProperty("AutoCompletion.CompletionGUI", "List");

		try {
			time = Integer.parseInt(settings.getProperty("AutoCompletion.ActivationTime", "150"));
		} catch(Exception exc) {
			time = 150;
		}

		completerKeys = new int[4][2]; // cycle forward, cycle backward, complete, break

		String cycleForward = settings.getProperty("AutoCompletion.Keys.Cycle.Forward");

		try {
			StringTokenizer st = new StringTokenizer(cycleForward, ",");
			completerKeys[0][0] = Integer.parseInt(st.nextToken());
			completerKeys[0][1] = Integer.parseInt(st.nextToken());
		} catch(Exception exc) {
			completerKeys[0][0] = KeyEvent.CTRL_MASK;
			completerKeys[0][1] = KeyEvent.VK_DOWN;
		}

		String cycleBackward = settings.getProperty("AutoCompletion.Keys.Cycle.Backward");

		try {
			StringTokenizer st = new StringTokenizer(cycleBackward, ",");
			completerKeys[1][0] = Integer.parseInt(st.nextToken());
			completerKeys[1][1] = Integer.parseInt(st.nextToken());
		} catch(Exception exc) {
			completerKeys[1][0] = KeyEvent.CTRL_MASK;
			completerKeys[1][1] = KeyEvent.VK_UP;
		}

		String complete = settings.getProperty("AutoCompletion.Keys.Complete");

		try {
			StringTokenizer st = new StringTokenizer(complete, ",");
			completerKeys[2][0] = Integer.parseInt(st.nextToken());
			completerKeys[2][1] = Integer.parseInt(st.nextToken());
		} catch(Exception exc) {
			completerKeys[2][0] = 0;
			completerKeys[2][1] = KeyEvent.VK_TAB;
		}

		String breakKey = settings.getProperty("AutoCompletion.Keys.Break");

		try {
			StringTokenizer st = new StringTokenizer(breakKey, ",");
			completerKeys[3][0] = Integer.parseInt(st.nextToken());
			completerKeys[3][1] = Integer.parseInt(st.nextToken());
		} catch(Exception exc) {
			completerKeys[3][0] = 0;
			completerKeys[3][1] = KeyEvent.VK_ESCAPE;
		}
        
		selfDefinedCompletions = getSelfDefinedCompletions(settings);
        selfDefinedCompletions2 = getSelfDefinedCompletions(completionSettings);

	}

    /**
     * read defined completions from given property file
     * @return Map containing name to      
     */
	private Map getSelfDefinedCompletions(Properties aSettings) {
	    Map result = CollectionFactory.createOrderedHashtable();

        // load selfdefined completions
        List completionNames = PropertiesHelper.getList(aSettings, "AutoCompletion.SelfDefinedCompletions.name");
        for(int i = 0, size = completionNames.size(); i < size; i++) {
            String name  = (String) completionNames.get(i);
            String value = (String) aSettings.get("AutoCompletion.SelfDefinedCompletions.value" + i);
            if(name != null && value != null) {
                result.put(name, value);
            }
        }

        return result;
    }

	/**
	 * to choose the current GUI
	 * 
	 * TODO: DOCUMENT ME!
	 */
	public void loadComplete() {
		if(completionGUIs.size() == 0) {
			return;
		}

		if(activeGUI == null) {
			setCurrentGUI((CompletionGUI) completionGUIs.get(0));

			return;
		}

		Iterator it = completionGUIs.iterator();

		while(it.hasNext()) {
			CompletionGUI cGUI = (CompletionGUI) it.next();

			if(cGUI.getTitle().equals(activeGUI)) {
				setCurrentGUI(cGUI);

				return;
			}
		}

		setCurrentGUI((CompletionGUI) completionGUIs.get(0));
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param cel TODO: DOCUMENT ME!
	 */
	public void attachEditorManager(OrderEditorList cel) {
		if(editors != null) {
			editors.removeExternalKeyListener(this);
			editors.removeExternalCaretListener(this);
			editors.removeExternalFocusListener(this);
		}

		editors = cel;

		if(editors != null) {
			editors.addExternalKeyListener(this);
			editors.addExternalCaretListener(this);
			editors.addExternalFocusListener(this);
		}
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param cGUI TODO: DOCUMENT ME!
	 */
	public void addCompletionGUI(CompletionGUI cGUI) {
		cGUI.init(this);
		completionGUIs.add(cGUI);
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @return TODO: DOCUMENT ME!
	 */
	public List getCompletionGUIs() {
		return completionGUIs;
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param cGUI TODO: DOCUMENT ME!
	 */
	public void setCurrentGUI(CompletionGUI cGUI) {
		if(log.isDebugEnabled()) {
			log.debug("AutoCompletion.setCurrentGUI called with " + cGUI);
		}

		if(!completionGUIs.contains(cGUI)) {
			addCompletionGUI(cGUI);
		}

		if(currentGUI != null) {
			currentGUI.stopOffer();
		}

		currentGUI = cGUI;
		settings.setProperty("AutoCompletion.CompletionGUI", cGUI.getTitle());
		timer.restart();
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @return TODO: DOCUMENT ME!
	 */
	public CompletionGUI getCurrentGUI() {
		return currentGUI;
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param c TODO: DOCUMENT ME!
	 */
	public void setCompleter(Completer c) {
		completer = c;
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param e TODO: DOCUMENT ME!
	 */
	public void selectionChanged(SelectionEvent e) {
		if(log.isDebugEnabled()) {
			log.debug("AutoCompletion.selectionChanged called with " + e);
		}

		// stop offering a completion
		if(currentGUI != null) {
			currentGUI.stopOffer();
		}

		// let the editor update
		if(editors != null) {
			editors.selectionChanged(e);
		}

		// search for new completion
		JTextComponent j = editors.getCurrentEditor();

		if((j != null) && enableAutoCompletion) {
			timer.restart();
		}
	}

	protected void offerCompletion(JTextComponent j) {
		if(!enableAutoCompletion || (currentGUI == null) || (completer == null) || (j == null) ||
			   (completer == null) || !j.isVisible()) {
			return;
		}

		// find the piece of text
		String line = getCurrentLine(j);

		if(line == null) {
			return;
		}

		if((line.length() == 0) ||
			   ((j.getCaretPosition() > 0) &&
			   (j.getText().charAt(j.getCaretPosition() - 1) == '\n')) ||
			   ((j.getCaretPosition() > 0) &&
			   (j.getText().charAt(j.getCaretPosition() - 1) == '\r'))) {
			// new line, delete old completions
			completions = null;
		} else if(lastCaretPosition > j.getCaretPosition()) {
			// Caret went backwards so line must be parsed again
			completions = null;
		} else if((j.getCaretPosition() > 0) &&
					  (j.getText().charAt(j.getCaretPosition() - 1) == ' ')) {
			// if Space typed, delete old completions to enforce new parsing
			completions = null;
		}

		// remember CaretPosition
		lastCaretPosition = j.getCaretPosition();

		// run completer engine
		if(editors.getCurrentUnit() != null) {
			completions = completer.getCompletions(editors.getCurrentUnit(), line, completions);

			// determine, wheter the curser is in a word
			boolean inWord = true;

			if((j.getText().length() == j.getCaretPosition()) || (j.getCaretPosition() == 0)) {
				inWord = false;
			} else {
				char c = j.getText().charAt(j.getCaretPosition());

				if((c == ' ') || (c == '\n') || (c == '\t')) {
					inWord = false;
				} else {
					c = j.getText().charAt(j.getCaretPosition() - 1);

					if((c == ' ') || (c == '\n') || (c == '\t')) {
						inWord = false;
					}
				}
			}

			// show completions
			if(line.length() > 0) {
				String stub = getStub(line);
				lastStub = stub;

				if((emptyStubMode || (stub.length() > 0)) && (completions != null) &&
					   (completions.size() > 0) && !inWord) {
					currentGUI.offerCompletion(j, completions, stub);
					completionIndex = 0;
				}
			}
		}
	}

	/**
	 * TODO: DOCUMENT ME!
	 */
	public void cycleForward() {
		if((completions == null) || (completions.size() == 1) || (editors == null)) {
			return;
		}

		completionIndex++;
		completionIndex %= completions.size();

		if(currentGUI.isOfferingCompletion()) {
			currentGUI.cycleCompletion(editors.getCurrentEditor(), completions, lastStub,
									   completionIndex);
		}
	}

	/**
	 * TODO: DOCUMENT ME!
	 */
	public void cycleBackward() {
		if((completions == null) || (completions.size() == 1) || (editors == null)) {
			return;
		}

		completionIndex--;

		if(completionIndex < 0) {
			completionIndex += completions.size();
		}

		completionIndex %= completions.size();

		if(currentGUI.isOfferingCompletion()) {
			currentGUI.cycleCompletion(editors.getCurrentEditor(), completions, lastStub,
									   completionIndex);
		}
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param completion TODO: DOCUMENT ME!
	 */
	public void insertCompletion(Completion completion) {
		if(!enableAutoCompletion) {
			return;
		}

		completions = null;

		if(currentGUI != null) {
			currentGUI.stopOffer();
		}

		JTextComponent j = editors.getCurrentEditor();
		int caretPos = j.getCaretPosition();
		String line = getCurrentLine(j);
		String stub = getStub(line);
		int stubLen = stub.length();
		int stubBeg = caretPos - stubLen;
		String text = j.getText();
		int temp1 = text.indexOf('\n', caretPos);

		if(temp1 == -1) {
			temp1 = Integer.MAX_VALUE;
		}

		int temp2 = text.indexOf('\r', caretPos);

		if(temp2 == -1) {
			temp2 = Integer.MAX_VALUE;
		}

		int temp3 = text.indexOf('\t', caretPos);

		if(temp3 == -1) {
			temp3 = Integer.MAX_VALUE;
		}

		int temp4 = text.indexOf(' ', caretPos);

		if(temp4 == -1) {
			temp4 = Integer.MAX_VALUE;
		}

		temp1 = Math.min(temp1, temp2);
		temp3 = Math.min(temp3, temp4);

		int stubEnd = Math.min(temp1, temp3);

		if(stubEnd == Integer.MAX_VALUE) {
			stubEnd = text.length();
		} else if(text.charAt(stubEnd) == ' ') {
			stubEnd++;
		}

		stubLen = stubEnd - stubBeg;

		try {
			j.getDocument().remove(stubBeg, stubLen);
			j.getDocument().insertString(stubBeg, completion.getValue(), new SimpleAttributeSet());
			j.getCaret().setDot((stubBeg + completion.getValue().length()) -
								completion.getCursorOffset());

			// pavkovic 2003.03.04: enforce focus request
			j.requestFocus();
		} catch(BadLocationException exc) {
			log.info(exc);
		}
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param j TODO: DOCUMENT ME!
	 *
	 * @return TODO: DOCUMENT ME!
	 */
	public static String getCurrentLine(JTextComponent j) {
		int offset = j.getCaretPosition();
		int lineBounds[] = getCurrentLineBounds(j.getText(), offset);

		if(lineBounds[0] < 0) {
			return null;
		}

		lineBounds[1] = Math.min(offset, lineBounds[1]) - lineBounds[0];

		try {
			return j.getText(lineBounds[0], lineBounds[1]);
		} catch(BadLocationException ble) {
		}

		return null;
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param text TODO: DOCUMENT ME!
	 * @param offset TODO: DOCUMENT ME!
	 *
	 * @return TODO: DOCUMENT ME!
	 */
	public static int[] getCurrentLineBounds(String text, int offset) {
		int ret[] = { -1, -1 };

		if((offset > -1) && (offset <= text.length())) {
			for(ret[0] = offset - 1; ret[0] > -1; ret[0]--) {
				char c = text.charAt(ret[0]);

				if((c == '\n') || (c == '\r')) {
					break;
				}
			}

			ret[0]++;
			ret[1] = text.indexOf('\n', offset);

			if(ret[1] == -1) {
				ret[1] = text.length();
			}
		}

		return ret;
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param txt TODO: DOCUMENT ME!
	 *
	 * @return TODO: DOCUMENT ME!
	 */
	public static String getStub(String txt) {
		StringBuffer retVal = new StringBuffer();

		for(int i = txt.length() - 1; i >= 0; i--) {
			char c = txt.charAt(i);

			if((c == '"') || (c == '_') || (c == '-') || (Character.isLetterOrDigit(c) == true)) {
				retVal.append(c);
			} else {
				break;
			}
		}

		return retVal.reverse().toString();
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param p1 TODO: DOCUMENT ME!
	 */
	public void keyReleased(java.awt.event.KeyEvent p1) {
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param e TODO: DOCUMENT ME!
	 */
	public void keyPressed(java.awt.event.KeyEvent e) {
		if(!enableAutoCompletion || (currentGUI == null) || !currentGUI.isOfferingCompletion()) {
			return;
		}

		int code = e.getKeyCode();
		int modifiers = e.getModifiers();
		boolean plain = (e.getModifiers() == 0);

		if((completerKeys[0][0] == modifiers) && (completerKeys[0][1] == code)) {
			cycleForward();
			e.consume();

			return;
		}

		if((completerKeys[1][0] == modifiers) && (completerKeys[1][1] == code)) {
			cycleBackward();
			e.consume();

			return;
		}

		if((completerKeys[2][0] == modifiers) && (completerKeys[2][1] == code)) {
			Completion cmp = currentGUI.getSelectedCompletion();

			if(cmp != null) {
				insertCompletion(cmp);
			}

			e.consume();

			return;
		}

		if((completerKeys[3][0] == modifiers) && (completerKeys[3][1] == code)) {
			currentGUI.stopOffer();

			return;
		}

		if(!plain) {
			return;
		}

		int keys[] = currentGUI.getSpecialKeys();

		if(keys != null) {
			for(int i = 0; i < keys.length; i++) {
				if(code == keys[i]) {
					currentGUI.specialKeyPressed(code);
					e.consume();
				}
			}
		}
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param p1 TODO: DOCUMENT ME!
	 */
	public void keyTyped(java.awt.event.KeyEvent p1) {
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param e TODO: DOCUMENT ME!
	 */
	public void actionPerformed(java.awt.event.ActionEvent e) {
		if(log.isDebugEnabled()) {
			log.debug("AutoCompletion.actionPerformed called with " + e);
		}

		timer.stop();

		if(enableAutoCompletion) {
			offerCompletion(editors.getCurrentEditor());
		}
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param e TODO: DOCUMENT ME!
	 */
	public void caretUpdate(javax.swing.event.CaretEvent e) {
		if(log.isDebugEnabled()) {
			log.debug("AutoCompletion.caretUpdate called with " + e);
		}

		if(enableAutoCompletion && (currentGUI != null) && !currentGUI.editorMayUpdateCaret()) {
			currentGUI.stopOffer();
			timer.restart();
		}
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param e TODO: DOCUMENT ME!
	 */
	public void gameDataChanged(GameDataEvent e) {
		setCompleter(e.getGameData().getGameSpecificStuff().getCompleter(e.getGameData(), this));

		if(currentGUI != null) {
			currentGUI.stopOffer();
		}
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @return TODO: DOCUMENT ME!
	 */
	public PreferencesAdapter getPreferencesAdapter() {
		return new DetailAutoCompletionPreferencesAdapter(this);
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param e TODO: DOCUMENT ME!
	 */
	public void focusGained(java.awt.event.FocusEvent e) {
		if(log.isDebugEnabled()) {
			log.debug("AutoCompletion.focusGained called with " + e);
		}

		if(enableAutoCompletion) {
			timer.restart();
		}
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param p1 TODO: DOCUMENT ME!
	 */
	public void focusLost(java.awt.event.FocusEvent p1) {
		if((currentGUI != null) && !currentGUI.editorMayLoseFocus()) {
			currentGUI.stopOffer();
		}
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param b TODO: DOCUMENT ME!
	 */
	public void setEnableAutoCompletion(boolean b) {
		enableAutoCompletion = b;
		settings.setProperty("AutoCompletion.Enabled", enableAutoCompletion ? "true" : "false");

		if(!b && (currentGUI != null)) {
			currentGUI.stopOffer();
		}
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @return TODO: DOCUMENT ME!
	 */
	public boolean isEnableAutoCompletion() {
		return enableAutoCompletion;
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param value TODO: DOCUMENT ME!
	 */
	public void setLimitMakeCompletion(boolean value) {
		limitMakeCompletion = value;
		settings.setProperty("AutoCompletion.limitMakeCompletion", value ? "true" : "false");
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @return TODO: DOCUMENT ME!
	 */
	public boolean getLimitMakeCompletion() {
		return limitMakeCompletion;
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param b TODO: DOCUMENT ME!
	 */
	public void setEmptyStubMode(boolean b) {
		emptyStubMode = b;
		settings.setProperty("AutoCompletion.EmptyStubMode", emptyStubMode ? "true" : "false");
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @return TODO: DOCUMENT ME!
	 */
	public boolean getEmptyStubMode() {
		return emptyStubMode;
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @return TODO: DOCUMENT ME!
	 */
	public int getActivationTime() {
		return time;
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param t TODO: DOCUMENT ME!
	 */
	public void setActivationTime(int t) {
		time = t;

		if(time < 1) {
			time = 1;
		}

		settings.setProperty("AutoCompletion.ActivationTime", String.valueOf(time));
		timer.setDelay(time);
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @return TODO: DOCUMENT ME!
	 */
	public int[][] getCompleterKeys() {
		return completerKeys;
	}

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @param ck TODO: DOCUMENT ME!
	 */
	public void setCompleterKeys(int ck[][]) {
		completerKeys = ck;
		settings.setProperty("AutoCompletion.Keys.Cycle.Forward",
							 String.valueOf(ck[0][0]) + ',' + String.valueOf(ck[0][1]));
		settings.setProperty("AutoCompletion.Keys.Cycle.Backward",
							 String.valueOf(ck[1][0]) + ',' + String.valueOf(ck[1][1]));
		settings.setProperty("AutoCompletion.Keys.Complete",
							 String.valueOf(ck[2][0]) + ',' + String.valueOf(ck[2][1]));
		settings.setProperty("AutoCompletion.Keys.Break",
							 String.valueOf(ck[3][0]) + ',' + String.valueOf(ck[3][1]));
	}

	/**
	 * Returns a Vector containing the self defined completions as Completion objects.
	 *
	 * @return TODO: DOCUMENT ME!
	 */
	public List getSelfDefinedCompletions() {
		List retVal = new Vector();

		for(Iterator iter = selfDefinedCompletions.keySet().iterator(); iter.hasNext();) {
			String name = (String) iter.next();
			String value = (String) selfDefinedCompletions.get(name);
			Completion c = new Completion(name, value, "", 0);
			retVal.add(c);
		}

        for(Iterator iter = selfDefinedCompletions2.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String value = (String) selfDefinedCompletions2.get(name);
            Completion c = new Completion(name, value, "", 0);
            retVal.add(c);
        }

		return retVal;
	}

	private class DetailAutoCompletionPreferencesAdapter extends JPanel
		implements PreferencesAdapter
	{
		protected AutoCompletion source;
		protected JCheckBox cEnable;
		protected JCheckBox iPopup;
		protected JCheckBox limitMakeCompletion;
		protected JComboBox forGUIs;
		protected JTextField tTime;
		protected KeyTextField keyFields[];

		// a copy of AutoCompletion.selfDefinedCompletions
		private Map selfDefinedCompletions;

		/**
		 * Creates a new DetailAutoCompletionPreferencesAdapter object.
		 *
		 * @param s TODO: DOCUMENT ME!
		 */
		public DetailAutoCompletionPreferencesAdapter(AutoCompletion s) {
			source = s;
			this.setLayout(new java.awt.GridBagLayout());

			GridBagConstraints c = new GridBagConstraints(0, 0, 2, 1, 0.1, 1.0,
														  GridBagConstraints.WEST,
														  GridBagConstraints.HORIZONTAL,
														  new Insets(2, 2, 2, 2), 0, 0);

			this.add(new JPanel(), c);

			c.gridwidth = 1;
			c.weighty = 0;
			c.gridy++;
			cEnable = new JCheckBox(getString("prefs.autocompletion"),
									source.isEnableAutoCompletion());
			this.add(cEnable, c);

			c.gridy++;
			limitMakeCompletion = new JCheckBox(getString("prefs.limitmakecompletion"),
												source.getLimitMakeCompletion());
			limitMakeCompletion.setToolTipText(getString("prefs.limitmakecompletion.tooltip"));
			this.add(limitMakeCompletion, c);

			iPopup = new JCheckBox(getString("prefs.stubmode"), source.getEmptyStubMode());
			c.gridy++;
			this.add(iPopup, c);

			c.gridy++;

			JPanel inner = new JPanel(new GridBagLayout());
			GridBagConstraints con2 = new GridBagConstraints(0, 0, 1, 1, 0, 0,
															 GridBagConstraints.WEST,
															 GridBagConstraints.HORIZONTAL,
															 c.insets, 0, 0);

			inner.add(new JLabel(getString("prefs.time")), con2);
			con2.gridy++;
			inner.add(new JLabel(getString("prefs.gui") + ":"), con2);

			con2.gridx = 1;
			con2.gridy = 0;
			con2.weightx = 1;
			tTime = new JTextField(String.valueOf(source.getActivationTime()), 5);
			inner.add(tTime, con2);
			con2.gridy++;

			forGUIs = new JComboBox(completionGUIs);
			forGUIs.setEditable(false);

			if(source.getCurrentGUI() != null) {
				forGUIs.setSelectedItem(source.getCurrentGUI());
			}

			inner.add(forGUIs, con2);

			this.add(inner, c);

			Component keys = createKeyComponents(s);
			c.gridx = 1;
			c.gridy = 1;
			c.weightx = 1;
			c.gridheight = 4;
			this.add(keys, c);

			/**
			 * Code for self defined completions.
			 */

			// make a copy of the self defined completions that will be
			// written back in applyPreferences()
			this.selfDefinedCompletions = CollectionFactory.createOrderedHashtable(source.selfDefinedCompletions);

			c.gridx = 0;
			c.gridy = 5;
			c.gridheight = 1;
			c.gridwidth = 2;
			c.weighty = 0;
			c.insets = new Insets(10, 0, 10, 0);
			this.add(new JSeparator(SwingConstants.HORIZONTAL), c);

			JPanel sDCPanel = getSelfDefinedCompletionPanel();
			c.gridy = 6;
			c.weighty = 0.2;
			c.fill = GridBagConstraints.BOTH;
			c.insets = new Insets(0, 0, 0, 0);
			this.add(sDCPanel, c);

			c.weighty = 1;
			c.gridy++;
			this.add(new JPanel(), c);
		}

		private JPanel getSelfDefinedCompletionPanel() {
			JPanel sDCPanel = new JPanel();
			sDCPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
			sDCPanel.setLayout(new GridBagLayout());

			GridBagConstraints c = new GridBagConstraints(0, 0, 1, 1, 0.5, 0,
														  GridBagConstraints.CENTER,
														  GridBagConstraints.BOTH,
														  new Insets(2, 2, 2, 2), 0, 0);
			sDCPanel.add(new JLabel(getString("prefs.SelfDefinedCompletions.title") + ":"), c);

			final JLabel completionValue = new JLabel();
			JScrollPane temp = new JScrollPane(completionValue);
			temp.setBorder(new CompoundBorder(new TitledBorder(BorderFactory.createEtchedBorder(),
															   getString("prefs.SelfDefinedCompletions.completionValue.title")),
											  new EmptyBorder(5, 5, 5, 5)));
			c.gridx = 1;
			c.gridy = 1;
			c.weighty = 0.5;
			sDCPanel.add(temp, c);

			List l = CollectionFactory.createLinkedList(this.selfDefinedCompletions.keySet());
			Collections.sort(l);

			DefaultListModel listModel = new DefaultListModel();

			for(Iterator iter = l.iterator(); iter.hasNext();) {
				listModel.addElement(iter.next());
			}

			final JList completionNames = new JList(listModel);
			completionNames.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
			completionNames.addListSelectionListener(new ListSelectionListener() {
					public void valueChanged(ListSelectionEvent e) {
						if(!e.getValueIsAdjusting()) {
							String str = (String) completionNames.getSelectedValue();
							String display = "";

							if(str != null) {
								str = (String) DetailAutoCompletionPreferencesAdapter.this.selfDefinedCompletions.get(str);
								display = "<html><b><p>";

								for(int i = 0; i < str.length(); i++) {
									if(str.charAt(i) == '\n') {
										display += "</p><p>";
									} else {
										display += str.charAt(i);
									}
								}

								display += "</p></b></html>";
							}

							completionValue.setText(display);
						}
					}
				});

			if(completionNames.getModel().getSize() > 0) {
				completionNames.setSelectedIndex(0);
			}

			temp = new JScrollPane(completionNames);
			temp.setBorder(new TitledBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED),
											getString("prefs.SelfDefinedCompletions.completionNames.title")));
			c.gridx = 0;
			c.gridheight = 3;
			sDCPanel.add(temp, c);

			final JButton delete = new JButton(getString("prefs.SelfDefinedCompletions.deleteButton.caption"));
			delete.setMnemonic(getString("prefs.SelfDefinedCompletions.deleteButton.mnemonic")
								   .charAt(0));

			if(completionNames.getModel().getSize() == 0) {
				delete.setEnabled(false);
			}

			delete.addActionListener(new ActionListener() {
					public void actionPerformed(ActionEvent e) {
						int index = completionNames.getSelectedIndex();
						String name = (String) completionNames.getSelectedValue();
						((DefaultListModel) completionNames.getModel()).remove(index);

						if(completionNames.getModel().getSize() == 0) {
							delete.setEnabled(false);
							completionValue.setText("");
						} else if(completionNames.getModel().getSize() > index) {
							completionNames.setSelectedIndex(index);
						} else {
							completionNames.setSelectedIndex(index - 1);
						}

						completionNames.repaint();
						DetailAutoCompletionPreferencesAdapter.this.selfDefinedCompletions.remove(name);
					}
				});

			final JButton newCompletion = new JButton(getString("prefs.SelfDefinedCompletions.newCompletionButton.caption"));
			newCompletion.setMnemonic(getString("prefs.SelfDefinedCompletions.newCompletionButton.mnemonic")
										  .charAt(0));
			newCompletion.addActionListener(new ActionListener() {
					public void actionPerformed(ActionEvent e) {
						String nameAndValue[] = (new DefineCompletionDialog(JOptionPane.getFrameForComponent(newCompletion))).getNewCompletionNameAndValue();
						String name = nameAndValue[0];
						String value = nameAndValue[1];

						if(!name.equals("") && !value.equals("")) {
							DetailAutoCompletionPreferencesAdapter.this.selfDefinedCompletions.put(name,
																								   value);

							DefaultListModel lstModel = (DefaultListModel) completionNames.getModel();

							if(!lstModel.contains(name)) {
								lstModel.addElement(name);
							}

							completionNames.clearSelection();
							completionNames.setSelectedIndex(lstModel.indexOf(name));
							completionNames.repaint();
							delete.setEnabled(true);
						}
					}
				});

			c.gridx = 1;
			c.gridy = 2;
			c.gridheight = 1;
			c.fill = GridBagConstraints.HORIZONTAL;
			c.weighty = 0;
			sDCPanel.add(newCompletion, c);

			c.gridy = 3;
			sDCPanel.add(delete, c);

			return sDCPanel;
		}

		protected Component createKeyComponents(AutoCompletion s) {
			JPanel p = new JPanel(new java.awt.GridBagLayout());
			java.awt.GridBagConstraints c = new java.awt.GridBagConstraints(0, 0, 1, 1, 0, 0,
																			GridBagConstraints.WEST,
																			GridBagConstraints.HORIZONTAL,
																			new Insets(2, 2, 2, 2),
																			0, 0);

			for(int i = 0; i < 4; i++) {
				c.gridy = i;
				p.add(new JLabel(getString("prefs.keys." + String.valueOf(i))), c);
			}

			c.gridx = 1;
			keyFields = new KeyTextField[4];

			int ck[][] = s.getCompleterKeys();

			for(int i = 0; i < 4; i++) {
				c.gridy = i;
				keyFields[i] = new KeyTextField();
				keyFields[i].init(ck[i][0], ck[i][1]);
				p.add(keyFields[i], c);
			}

			return p;
		}

		/**
		 * TODO: DOCUMENT ME!
		 *
		 * @param cGUI TODO: DOCUMENT ME!
		 */
		public void addCompletionGUI(CompletionGUI cGUI) {
			forGUIs.addItem(cGUI);
			this.revalidate();
			this.doLayout();
		}

		/**
		 * TODO: DOCUMENT ME!
		 *
		 * @param cGUI TODO: DOCUMENT ME!
		 */
		public void setCurrentGUI(CompletionGUI cGUI) {
			forGUIs.setSelectedItem(cGUI);
		}

		/**
		 * TODO: DOCUMENT ME!
		 *
		 * @return TODO: DOCUMENT ME!
		 */
		public Component getComponent() {
			return this;
		}

		/**
		 * TODO: DOCUMENT ME!
		 *
		 * @return TODO: DOCUMENT ME!
		 */
		public String getTitle() {
			return getString("prefs.title");
		}

        /** TODO: DOCUMENT ME!
         * @see com.eressea.swing.preferences.PreferencesAdapter#initPreferences()
         */
        public void initPreferences() {
            // TODO: implement it
        }
        
		/**
		 * TODO: DOCUMENT ME!
		 */
		public void applyPreferences() {
			source.setEnableAutoCompletion(cEnable.isSelected());
			source.setCurrentGUI((CompletionGUI) forGUIs.getSelectedItem());
			source.setLimitMakeCompletion(limitMakeCompletion.isSelected());
			source.setEmptyStubMode(iPopup.isSelected());

			int t = 150;

			try {
				t = Integer.parseInt(tTime.getText());
			} catch(Exception exc) {
				tTime.setText("150");
			}

			source.setActivationTime(t);

			// maybe we could use the given array from AutoCompletion directly?
			int ck[][] = new int[4][2];

			for(int i = 0; i < 4; i++) {
				ck[i][0] = keyFields[i].getModifiers();
				ck[i][1] = keyFields[i].getKeyCode();
			}

			source.setCompleterKeys(ck);

			/** Apply preferences for self defined completions */

			// delete old entries out of settings file
			String s = (String) settings.get("AutoCompletion.SelfDefinedCompletions.count");
			int completionCount = 0;

			if(s != null) {
				completionCount = Integer.parseInt(s);
			}

			for(int i = 0; i < completionCount; i++) {
				settings.remove("AutoCompletion.SelfDefinedCompletions.name" + i);
				settings.remove("AutoCompletion.SelfDefinedCompletions.value" + i);
			}

			// insert new values
			completionCount = 0;

			for(Iterator iter = selfDefinedCompletions.keySet().iterator(); iter.hasNext();) {
				String name = (String) iter.next();
				String value = (String) selfDefinedCompletions.get(name);
				settings.setProperty("AutoCompletion.SelfDefinedCompletions.name" +
									 completionCount, name);
				settings.setProperty("AutoCompletion.SelfDefinedCompletions.value" +
									 completionCount, value);
				completionCount++;
			}

			settings.setProperty("AutoCompletion.SelfDefinedCompletions.count",
								 String.valueOf(completionCount));

			// update selfDefinedCompletion table of AutoCompletion
			source.selfDefinedCompletions.clear();
			source.selfDefinedCompletions.putAll(this.selfDefinedCompletions);
		}

		private class KeyTextField extends JTextField implements KeyListener {
			protected int modifiers = 0;
			protected int key = 0;

			/**
			 * Creates a new KeyTextField object.
			 */
			public KeyTextField() {
				super(20);
				this.addKeyListener(this);
			}

			/**
			 * TODO: DOCUMENT ME!
			 *
			 * @param modifiers TODO: DOCUMENT ME!
			 * @param key TODO: DOCUMENT ME!
			 */
			public void init(int modifiers, int key) {
				this.key = key;
				this.modifiers = modifiers;

				String s = KeyEvent.getKeyModifiersText(modifiers);

				if((s != null) && (s.length() > 0)) {
					s += ('+' + KeyEvent.getKeyText(key));
				} else {
					s = KeyEvent.getKeyText(key);
				}

				setText(s);
			}

			/**
			 * TODO: DOCUMENT ME!
			 *
			 * @param p1 TODO: DOCUMENT ME!
			 */
			public void keyReleased(java.awt.event.KeyEvent p1) {
				// maybe should delete any input if there's no "stable"(non-modifying) key
			}

			/**
			 * TODO: DOCUMENT ME!
			 *
			 * @param p1 TODO: DOCUMENT ME!
			 */
			public void keyPressed(java.awt.event.KeyEvent p1) {
				modifiers = p1.getModifiers();
				key = p1.getKeyCode();

				// avoid double string
				if((key == KeyEvent.VK_SHIFT) || (key == KeyEvent.VK_CONTROL) ||
					   (key == KeyEvent.VK_ALT) || (key == KeyEvent.VK_ALT_GRAPH)) {
					int xored = 0;

					switch(key) {
					case KeyEvent.VK_SHIFT:
						xored = KeyEvent.SHIFT_MASK;

						break;

					case KeyEvent.VK_CONTROL:
						xored = KeyEvent.CTRL_MASK;

						break;

					case KeyEvent.VK_ALT:
						xored = KeyEvent.ALT_MASK;

						break;

					case KeyEvent.VK_ALT_GRAPH:
						xored = KeyEvent.ALT_GRAPH_MASK;

						break;
					}

					modifiers ^= xored;
				}

				String s = KeyEvent.getKeyModifiersText(modifiers);

				if((s != null) && (s.length() > 0)) {
					s += ('+' + KeyEvent.getKeyText(key));
				} else {
					s = KeyEvent.getKeyText(key);
				}

				setText(s);
				p1.consume();
			}

			/**
			 * TODO: DOCUMENT ME!
			 *
			 * @param p1 TODO: DOCUMENT ME!
			 */
			public void keyTyped(java.awt.event.KeyEvent p1) {
			}

			/** to allow "tab" as a key
			 * @see javax.swing.JComponent#isManagingFocus()
			 */
			public boolean isManagingFocus() {
				return true;
			}

			/**
			 * TODO: DOCUMENT ME!
			 *
			 * @return TODO: DOCUMENT ME!
			 */
			public int getKeyCode() {
				return key;
			}

			/**
			 * TODO: DOCUMENT ME!
			 *
			 * @return TODO: DOCUMENT ME!
			 */
			public int getModifiers() {
				return modifiers;
			}
		}

		private class DefineCompletionDialog extends InternationalizedDialog {
			private JTextField name;
			private JTextArea value;
			private JButton ok;
			private JButton cancel;

			private DefineCompletionDialog(Frame frame) {
				super(frame, true);
				this.setTitle(AutoCompletion.getString("DefineCompletionDialog.title"));
				this.setSize(500, 200);

				JPanel cp = new JPanel();
				this.getContentPane().add(cp);
				cp.setBorder(new CompoundBorder(BorderFactory.createEtchedBorder(),
												new EmptyBorder(5, 5, 5, 5)));
				cp.setLayout(new GridBagLayout());

				GridBagConstraints c = new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0,
															  GridBagConstraints.CENTER,
															  GridBagConstraints.HORIZONTAL,
															  new Insets(2, 2, 2, 2), 0, 0);

				name = new JTextField();
				name.setBorder(new TitledBorder(BorderFactory.createEtchedBorder(),
												AutoCompletion.getString("DefineCompletionDialog.nameField.title")));
				cp.add(name, c);

				value = new JTextArea();
				value.setMargin(new Insets(4, 4, 4, 4));

				JScrollPane temp = new JScrollPane(value);
				temp.setBorder(new TitledBorder(BorderFactory.createEtchedBorder(),
												AutoCompletion.getString("DefineCompletionDialog.valueField.title")));
				c.gridy = 1;
				c.fill = GridBagConstraints.BOTH;
				c.weighty = 1.0;
				cp.add(temp, c);

				ok = new JButton(AutoCompletion.getString("DefineCompletionDialog.okButton.caption"));
				ok.setMnemonic(AutoCompletion.getString("DefineCompletionDialog.okButton.mnemonic")
											 .charAt(0));
				c.gridy = 0;
				c.gridx = 1;
				c.weighty = 0.0;
				c.weightx = 0.0;
				c.fill = GridBagConstraints.HORIZONTAL;
				cp.add(ok, c);

				cancel = new JButton(AutoCompletion.getString("DefineCompletionDialog.cancelButton.caption"));
				cancel.setMnemonic(AutoCompletion.getString("DefineCompletionDialog.cancelButton.mnemonic")
												 .charAt(0));
				cancel.addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent e) {
							DefineCompletionDialog.this.quit();
						}
					});
				c.gridy = 1;
				c.anchor = GridBagConstraints.NORTH;
				cp.add(cancel, c);

				name.setNextFocusableComponent(value);
				value.setNextFocusableComponent(ok);
				ok.setNextFocusableComponent(cancel);
				cancel.setNextFocusableComponent(name);
			}

			private String[] getNewCompletionNameAndValue() {
				final String retVal[] = { "", "" };
				ok.addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent e) {
							retVal[0] = name.getText();
							retVal[1] = value.getText();
							quit();
						}
					});
				this.setLocationRelativeTo(getOwner());
				this.show();

				return retVal;
			}
		}
	}

	private static String getString(String key) {
		return Translations.getTranslation(AutoCompletion.class, key);
	}

	// pavkovic 2003.01.28: this is a Map of the default Translations mapped to this class
	// it is called by reflection (we could force the implementation of an interface,
	// this way it is more flexible.)
	// Pls use this mechanism, so the translation files can be created automagically
	// by inspecting all classes.
	private static Map defaultTranslations;

	/**
	 * TODO: DOCUMENT ME!
	 *
	 * @return TODO: DOCUMENT ME!
	 */
	public static synchronized Map getDefaultTranslations() {
		if(defaultTranslations == null) {
			defaultTranslations = CollectionFactory.createHashtable();
			defaultTranslations.put("prefs.autocompletion", "activate auto completion");
			defaultTranslations.put("prefs.limitmakecompletion", "limit completion of MAKE");
			defaultTranslations.put("prefs.limitmakecompletion.tooltip",
									"Determines, whether the completions of the make order shall be limited " +
									"to those items, whose resources are available.");
			defaultTranslations.put("prefs.stubmode", "Immediate proposal");
			defaultTranslations.put("prefs.time", "Time");
			defaultTranslations.put("prefs.gui", "Mode");
			defaultTranslations.put("prefs.SelfDefinedCompletions.title",
									"Selfdefined order completions");
			defaultTranslations.put("prefs.SelfDefinedCompletions.completionValue.title", "Value");
			defaultTranslations.put("prefs.SelfDefinedCompletions.completionNames.title", "Names");
			defaultTranslations.put("prefs.SelfDefinedCompletions.deleteButton.caption", "Delete");
			defaultTranslations.put("prefs.SelfDefinedCompletions.deleteButton.mnemonic", "d");
			defaultTranslations.put("prefs.SelfDefinedCompletions.newCompletionButton.caption",
									"Add");
			defaultTranslations.put("prefs.SelfDefinedCompletions.newCompletionButton.mnemonic", "a");
			defaultTranslations.put("prefs.keys.0", "Forward");
			defaultTranslations.put("prefs.keys.1", "Backward");
			defaultTranslations.put("prefs.keys.2", "Complete");
			defaultTranslations.put("prefs.keys.3", "Cancel");
			defaultTranslations.put("prefs.title", "Order Completion");
			defaultTranslations.put("DefineCompletionDialog.title", "Define new order completion...");
			defaultTranslations.put("DefineCompletionDialog.nameField.title", "Name");
			defaultTranslations.put("DefineCompletionDialog.valueField.title", "Value");
			defaultTranslations.put("DefineCompletionDialog.okButton.caption", "OK");
			defaultTranslations.put("DefineCompletionDialog.okButton.mnemonic", "o");
			defaultTranslations.put("DefineCompletionDialog.cancelButton.caption", "Cancel");
			defaultTranslations.put("DefineCompletionDialog.cancelButton.mnemonic", "C");
		}

		return defaultTranslations;
	}
}




See more files for this project here

Magellan-Client

The Magellan Client is basicly a GUI for the pbem game eressea but can be used for other pbems based on \"atlantis\" too.

Project homepage: http://sourceforge.net/projects/magellan-client
Programming language(s): Java
License: other

  AutoCompletion.java
  Completer.java
  CompleterSettingsProvider.java
  Completion.java
  OrderParser.java