/* * $Id$ * * Copyright (c) 2000-2003 by Rodney Kinney * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License (LGPL) as published by the Free Software Foundation. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, copies are available * at http://www.opensource.org. */ package VASSAL.configure; import java.util.StringTokenizer; import javax.swing.BoxLayout; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.SwingUtilities; import javax.swing.border.TitledBorder; import org.apache.commons.lang.StringUtils; import VASSAL.build.AutoConfigurable; import VASSAL.tools.ScrollPane; import VASSAL.tools.SequenceEncoder; /** * A Configurer that allows multi-line string input via a JTextArea */ public class TextConfigurer extends Configurer implements ConfigurerFactory { private JTextArea textArea; private JPanel p; private boolean wordWrap; public TextConfigurer() { this(null, null, null); } public TextConfigurer(String key, String name) { this(key, name, ""); } public TextConfigurer(String key, String name, String val) { super(key, name, val); } public TextConfigurer(String key, String name, String val, boolean wrap) { this(key, name, val); setWordWrap(wrap); } public Configurer getConfigurer(AutoConfigurable c, String key, String name) { this.key = key; this.name = name; return this; } public String getValueString() { return escapeNewlines((String) getValue()); } public void setWordWrap(boolean b) { wordWrap = b; } /** * Encodes a string by replacing newlines with '|' characters * * @param s * @return */ public static String escapeNewlines(String s) { SequenceEncoder se = new SequenceEncoder('|'); StringTokenizer st = new StringTokenizer(s, "\n\r", true); boolean wasNewLine = true; while (st.hasMoreTokens()) { String token = st.nextToken(); switch (token.charAt(0)) { case '\n': if (wasNewLine) { se.append(""); } wasNewLine = true; break; case '\r': break; default: se.append(token); wasNewLine = false; } } return se.getValue() == null ? "" : se.getValue(); } public void setValue(String s) { String text = restoreNewlines(s); setValue((Object) text); } public void setValue(Object o) { super.setValue(o); if (!noUpdate && textArea != null) { textArea.setText((String) o); } } /** * Restores a string by replacing '|' with newlines * * @param s * @return */ public static String restoreNewlines(String s) { return StringUtils.join(new SequenceEncoder.Decoder(s, '|'), '\n'); } public java.awt.Component getControls() { if (p == null) { p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS)); textArea = new JTextArea(6, 20); if (wordWrap) { textArea.setLineWrap(true); textArea.setWrapStyleWord(true); } textArea.addKeyListener(new java.awt.event.KeyAdapter() { public void keyReleased(java.awt.event.KeyEvent evt) { queueForUpdate(textArea.getText()); } }); textArea.setText((String) getValue()); JScrollPane scroll = new ScrollPane(textArea); if (name != null) { scroll.setBorder(new TitledBorder(name)); } p.add(scroll); } return p; } private long lastUpdate = System.currentTimeMillis(); private String updatedValue; private boolean updateQueued=false; private long updateFrequencey = 1000L; private void queueForUpdate(String s) { updatedValue = s; if (System.currentTimeMillis() > lastUpdate + updateFrequencey) { executeUpdate(); } else if (!updateQueued) { updateQueued = true; Runnable delayedUpdate = new Runnable() { public void run() { try { Thread.sleep(updateFrequencey); } catch (InterruptedException e) { } SwingUtilities.invokeLater(new Runnable() { public void run() { executeUpdate(); } }); } }; new Thread(delayedUpdate).start(); } } private void executeUpdate() { noUpdate = true; setValue((Object) updatedValue); lastUpdate = System.currentTimeMillis(); updateQueued = false; noUpdate = false; } }