Package de.mud.jta.plugin

Source Code of de.mud.jta.plugin.ButtonBar

/*
* This file is part of "JTA - Telnet/SSH for the JAVA(tm) platform".
*
* (c) Matthias L. Jugel, Marcus Meißner 1996-2005. All Rights Reserved.
*
* Please visit http://javatelnet.org/ for updates and contact.
*
* --LICENSE NOTICE--
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* --LICENSE NOTICE--
*
*/

package de.mud.jta.plugin;

import de.mud.jta.FilterPlugin;
import de.mud.jta.Plugin;
import de.mud.jta.PluginBus;
import de.mud.jta.PluginConfig;
import de.mud.jta.VisualPlugin;
import de.mud.jta.event.ConfigurationListener;
import de.mud.jta.event.SocketRequest;
import de.mud.jta.event.TelnetCommandRequest;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
* Implementation of a programmable button bar to be used as a plugin
* in the Java(tm) Telnet Applet/Application. The button bar is configured
* using a input file that contains the setup for the button bar.<P>
* A typical setup file may look like:
* <PRE>
* #
* # Example for writing a button bar config file.
* #
* # The syntaxt for defining buttons, input fields and breaks is as follows:
* #
* # - defining a button:
* # A button is defined by giving the keyword 'button' followed by the text
* # of the button and the command that should be sent when pressing the
* # button. If the command contains whitespace characters, enclode it in
* # quote (") characters!
* #
* button    Connect    "\$connect(\@host@,\@port@)"
* #
* # - defining a label:
* # A labvel is defined by giving the keyword 'label' followed by the text
* # of the label. If the label contains whitespace characters, enclode it in
* # quote (") characters!
* #
* label     "Hello User"
* #
* # - defining an input field:
* # An input field is defined just like the button above, but it has one more
* # parameter, the size of the input field. So you define it, by giving the
* # keyword 'input' followed by the name of the input field (for reference)
* # followed by the size of the input field and optionally a third parameter
* # which is the initial text to be displayed in that field.
* #
* input    host  20  "tanis"
* stretch
* input    port  4  "23"
* #
* # Now after the button and two input fields we define another button which
* # will be shown last in the row. Order is significant for the order in
* # which the buttons and fields appear.
* #
* button    Disconnect  "\\$disconnect()" break
* #
* # To implement an input line that is cleared and sends text use this:
* # The following line send the text in the input field "send" and appends
* # a newline.
* input    send  20  "\\@send@\n"  "ls"
* #
* # - Defining a choice
* # A choice is defined just like the button above, but it has multiple
* # text/command pairs. If the text or command contain whitespace characters,
* # enclose them in quote (") characters. The text and command data may be
* # spread over several lines for better readability. Make the first command
* # empty because it is initially selected, and choosing it will have no
* # effect until some other item has been chosen.
* #choice       "- choose -"   ""
* #             "Text 1"       "Command 1"
* #             "Text 2"       "Command 2"
* #             "Text 3"       "Command 3"
* # etc...

* </PRE>
* Other possible keywords are <TT>break</TT> which does introduce a new
* line so that buttons and input fields defined next will appear in a new
* line below and <TT>stretch</TT> to make the just defined button or input
* field stretched as far as possible on the line. That last keyword is
* useful to fill the space.
*
* @version $Id: ButtonBar.java 499 2005-09-29 08:24:54Z leo $
* @author  Matthias L. Jugel, Marcus Mei�ner
*/
public class ButtonBar extends Plugin
        implements FilterPlugin, VisualPlugin, ActionListener, ListSelectionListener {

  /** the panel that contains the buttons and input fields */
  protected JPanel panel = new JPanel();

  // these tables contain our buttons and fields.
  private Map buttons = null;
  private Map choices = null;
  private Map fields = null;

  // the switch for clearing input fields after enter
  private boolean clearFields = true;

  /**
   * Initialize the button bar and register plugin listeners
   */
  public ButtonBar(PluginBus bus, final String id) {
    super(bus, id);

    // configure the button bar
    bus.registerPluginListener(new ConfigurationListener() {
      public void setConfiguration(PluginConfig cfg) {
        String file = cfg.getProperty("ButtonBar", id, "setup");
        clearFields =
                (new Boolean(cfg.getProperty("ButtonBar", id, "clearFields")))
                .booleanValue();

        // check for the setup file
        if (file == null) {
          ButtonBar.this.error("no setup file");
          return;
        }

        StreamTokenizer setup = null;
        InputStream is = null;

        try {
          is = getClass().getResourceAsStream(file);
        } catch (Exception e) {
          // ignore any errors here
        }

        // if the resource access fails, try URL
        if (is == null)
          try {
            is = new URL(file).openStream();
          } catch (Exception ue) {
            ButtonBar.this.error("could not find: " + file);
            return;
          }

        // create a new stream tokenizer to read the file
        try {
          InputStreamReader ir = new InputStreamReader(is);
          setup = new StreamTokenizer(new BufferedReader(ir));
        } catch (Exception e) {
          ButtonBar.this.error("cannot load " + file + ": " + e);
          return;
        }

        setup.commentChar('#');
        setup.quoteChar('"');

        fields = new HashMap();
        buttons = new HashMap();
        choices = new HashMap();

        GridBagLayout l = new GridBagLayout();
        GridBagConstraints c = new GridBagConstraints();
        panel.setLayout(l);
        c.fill = GridBagConstraints.BOTH;

        int token;
        int ChoiceCount = 0;
        JList list;
        // parse the setup file
        try {
          while ((token = setup.nextToken()) != StreamTokenizer.TT_EOF) {
            switch (token) {
              case StreamTokenizer.TT_WORD:
                // reset the constraints
                c.gridwidth = 1;
                c.weightx = 0.0;
                c.weighty = 0.0;
                // keyword found, parse arguments
                if (setup.sval.equals("button")) {
                  if ((token = setup.nextToken()) != StreamTokenizer.TT_EOF) {
                    String descr = setup.sval;
                    if ((token = setup.nextToken()) != StreamTokenizer.TT_EOF) {
                      JButton b = new JButton(descr);
                      buttons.put(b, setup.sval);
                      b.addActionListener(ButtonBar.this);
                      l.setConstraints(b, constraints(c, setup));
                      panel.add(b);
                    } else
                      ButtonBar.this.error(descr + ": missing button command");
                  } else
                    ButtonBar.this.error("unexpected end of file");
                } else if (setup.sval.equals("label")) {
                  if ((token = setup.nextToken()) != StreamTokenizer.TT_EOF) {
                    String descr = setup.sval;
                    JLabel b = new JLabel(descr);
                    l.setConstraints(b, constraints(c, setup));
                    panel.add(b);
                  } else
                    ButtonBar.this.error("unexpected end of file");
                  /* choice - new stuff added APS 07-dec-2001 for Choice
                   * buttons
                   * Choice info is held in the choices hash. There are two
                   * sorts of hash entry:
                   * 1) for each choices button on the terminal, key=choice
                   *    object, value=ID ("C1.", "C2.", etc)
                   * 2) for each item, key=ID+user's text (eg "C1.opt1"),
                   *    value=user's command
                   */

                } else if (setup.sval.equals("choice")) {
                  ChoiceCount++;
                  String ident = "C" + ChoiceCount + ".";
                  list = new JList();
                  choices.put(list, ident);
                  list.addListSelectionListener(ButtonBar.this);// Choices use ItemListener, not Action
                  l.setConstraints(list, constraints(c, setup));
                  panel.add(list);
                  while ((token = setup.nextToken()) != StreamTokenizer.TT_EOF) {
                    if (isKeyword(setup.sval)) {// Got command ... Back off.
                      setup.pushBack();
                      break;
                    }
                    String descr = setup.sval;  // This is the hash key.
                    token = setup.nextToken();
                    if (token == StreamTokenizer.TT_EOF) {
                      ButtonBar.this.error("unexpected end of file");
                    } else {
                      String value = setup.sval;
                      if (isKeyword(value)) {   // Missing command - complain but continue
                        System.err.println(descr + ": missing choice command");
                        setup.pushBack();
                        break;
                      }
                      System.out.println("choice: name='" + descr + "', value='" + value);
                      list.add(descr, new JLabel(descr));
                      choices.put(ident + descr, value);
                    }
                  }
                  ButtonBar.this.error("choices hash: " + choices);
                } else if (setup.sval.equals("input")) {
                  if ((token = setup.nextToken()) != StreamTokenizer.TT_EOF) {
                    String descr = setup.sval;
                    if ((token = setup.nextToken()) ==
                            StreamTokenizer.TT_NUMBER) {
                      int size = (int) setup.nval;
                      String init = "", command = "";
                      token = setup.nextToken();
                      if (isKeyword(setup.sval))
                        setup.pushBack();
                      else
                        command = setup.sval;
                      token = setup.nextToken();
                      if (isKeyword(setup.sval)) {
                        setup.pushBack();
                        init = command;
                      } else
                        init = setup.sval;
                      JTextField t = new JTextField(init, size);
                      if (!init.equals(command)) {
                        buttons.put(t, command);
                        t.addActionListener(ButtonBar.this);
                      }
                      fields.put(descr, t);
                      l.setConstraints(t, constraints(c, setup));
                      panel.add(t);
                    } else
                      ButtonBar.this.error(descr + ": missing field size");
                  } else
                    ButtonBar.this.error("unexpected end of file");
                }
                break;
              default:
                ButtonBar.this.error("syntax error at line " + setup.lineno());
            }
          }
        } catch (IOException e) {
          ButtonBar.this.error("unexpected error while reading setup: " + e);
        }
        panel.validate();
      }
    });
  }

  private GridBagConstraints constraints(GridBagConstraints c,
                                         StreamTokenizer setup)
          throws IOException {
    if (setup.nextToken() == StreamTokenizer.TT_WORD)
      if (setup.sval.equals("break"))
        c.gridwidth = GridBagConstraints.REMAINDER;
      else if (setup.sval.equals("stretch"))
        c.weightx = 1.0;
      else
        setup.pushBack();
    else
      setup.pushBack();
    return c;
  }

  public void valueChanged(ListSelectionEvent evt) {
    String tmp, ident;
    if ((ident = (String) choices.get(evt.getSource())) != null) {
      // It's a choice - get the text from the selected item
      JList list = (JList) evt.getSource();
      tmp = (String) choices.get(ident + list.getSelectedValue());
      if (tmp != null) processEvent(tmp);
    }
  }

  public void actionPerformed(ActionEvent evt) {
    String tmp;
    if ((tmp = (String) buttons.get(evt.getSource())) != null)
      processEvent(tmp);
  }


  private void processEvent(String tmp) {
    String cmd = "", function = null;
    int idx = 0, oldidx = 0;
    while ((idx = tmp.indexOf('\\', oldidx)) >= 0 &&
            ++idx <= tmp.length()) {
      cmd += tmp.substring(oldidx, idx - 1);
      switch (tmp.charAt(idx)) {
        case 'b':
          cmd += "\b";
          break;
        case 'e':
          cmd += "";
          break;
        case 'n':
          cmd += "\n";
          break;
        case 'r':
          cmd += "\r";
          break;
        case '$':
          {
            int ni = tmp.indexOf('(', idx + 1);
            if (ni < idx) {
              error("ERROR: Function: missing '('");
              break;
            }
            if (ni == ++idx) {
              error("ERROR: Function: missing name");
              break;
            }
            function = tmp.substring(idx, ni);
            idx = ni + 1;
            ni = tmp.indexOf(')', idx);
            if (ni < idx) {
              error("ERROR: Function: missing ')'");
              break;
            }
            tmp = tmp.substring(idx, ni);
            idx = oldidx = 0;
            continue;
          }
        case '@':
          {
            int ni = tmp.indexOf('@', idx + 1);
            if (ni < idx) {
              error("ERROR: Input Field: '@'-End Marker not found");
              break;
            }
            if (ni == ++idx) {
              error("ERROR: Input Field: no name specified");
              break;
            }
            String name = tmp.substring(idx, ni);
            idx = ni;
            JTextField t;
            if (fields == null || (t = (JTextField) fields.get(name)) == null) {
              error("ERROR: Input Field: requested input \"" +
                    name + "\" does not exist");
              break;
            }
            cmd += t.getText();
            if (clearFields) t.setText("");
            break;
          }
        default :
          cmd += tmp.substring(idx, ++idx);
      }
      oldidx = ++idx;
    }

    if (oldidx <= tmp.length()) cmd += tmp.substring(oldidx, tmp.length());

    if (function != null) {
      if (function.equals("break")) {
        bus.broadcast(new TelnetCommandRequest((byte) 243)); // BREAK
        return;
      }
      if (function.equals("exit")) {
        try {
          System.exit(0);
        } catch (Exception e) {
          error("cannot exit: " + e);
        }
      }
      if (function.equals("connect")) {
        String address = null;
        int port = -1;
        try {
          if ((idx = cmd.indexOf(",")) >= 0) {
            try {
              port = Integer.parseInt(cmd.substring(idx + 1, cmd.length()));
            } catch (Exception e) {
              port = -1;
            }
            cmd = cmd.substring(0, idx);
          }
          if (cmd.length() > 0) address = cmd;
          if (address != null)
            if (port != -1)
              bus.broadcast(new SocketRequest(address, port));
            else
              bus.broadcast(new SocketRequest(address, 23));
          else
            error("connect: no address");
        } catch (Exception e) {
          error("connect(): failed");
          e.printStackTrace();
        }
      } else if (function.equals("disconnect"))
        bus.broadcast(new SocketRequest());
      else if (function.equals("detach")) {
        error("detach not implemented yet");
      } else
        error("ERROR: function not implemented: \"" + function + "\"");
      return;
    }
    // cmd += tmp.substring(oldidx, tmp.length());
    if (cmd.length() > 0)
      try {
        write(cmd.getBytes());
      } catch (IOException e) {
        error("send: " + e);
      }
  }

  public JComponent getPluginVisual() {
    return panel;
  }

  public JMenu getPluginMenu() {
    return null;
  }


  FilterPlugin source;

  public void setFilterSource(FilterPlugin source) {
    this.source = source;
  }

  public FilterPlugin getFilterSource() {
    return source;
  }

  public int read(byte[] b) throws IOException {
    return source.read(b);
  }

  public void write(byte[] b) throws IOException {
    source.write(b);
  }

  private static boolean isKeyword(String txt) {
    return (
            txt.equals("button") ||
            txt.equals("label") ||
            txt.equals("input") ||
            txt.equals("stretch") ||
            txt.equals("choice") ||
            txt.equals("break")
            );
  }
}
TOP

Related Classes of de.mud.jta.plugin.ButtonBar

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.