package com.framsticks.gui.windows.console; import com.framsticks.communication.*; import com.framsticks.gui.ImageProvider; import com.framsticks.util.lang.Pair; import com.framsticks.util.lang.Strings; import org.apache.log4j.Logger; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.ArrayList; import java.util.Collections; /** * Frame with text field for sending commands and text pane for displaying manager responses. */ @SuppressWarnings("serial") public class ConsoleFrame extends JFrame { private static final Logger log = Logger.getLogger(ConsoleFrame.class.getName()); /** * Painter coloring manager responses before display. */ private final ConsolePainter consolePainter; /** * Text field for typing commands. */ private final JTextField commandLine; /** * Reference to connection. */ protected final ClientConnection connection; /** * List of sent messages. * TODO: is it used at all? */ private final ArrayList sentMessages = new ArrayList(); /** * Current visible tip list. */ private ArrayList tipList = null; private int msgIndex = 0; private int tipIndex = 0; private Boolean clearMsgIndex = false; /** * Default constructor creates frame with console. */ @SuppressWarnings("unchecked") public ConsoleFrame(ClientConnection connection) { this.connection = connection; this.setTitle("Console"); this.setLayout(new BorderLayout()); this.setSize(new Dimension(440, 400)); this.setMinimumSize(new Dimension(440, 400)); this.setIconImage(ImageProvider.loadImage(ImageProvider.LOGO).getImage()); JFrame.setDefaultLookAndFeelDecorated(true); JTextPane text = new JTextPane(); consolePainter = new ConsolePainter(text); text.setEditable(false); final JScrollPane scrollText = new JScrollPane(text); scrollText.setBorder(BorderFactory.createEtchedBorder()); JPanel scrollPanel = new JPanel(); scrollPanel.setLayout(new BorderLayout()); scrollPanel.add(scrollText, BorderLayout.CENTER); scrollPanel.setBorder(BorderFactory.createEmptyBorder(7, 7, 7, 7)); commandLine = new JTextField(); commandLine.addKeyListener(new KeyListener() { @Override public void keyTyped(KeyEvent e) { } @Override public void keyPressed(KeyEvent e) { onKeyPressed(e.getKeyCode()); } @Override public void keyReleased(KeyEvent e) { } }); commandLine.setFocusTraversalKeys( KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Collections.EMPTY_SET); this.addWindowListener(new WindowAdapter() { public void windowActivated(WindowEvent e) { commandLine.requestFocusInWindow(); } }); JButton sendButton = new JButton("Send"); sendButton.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { buttonSendAction(); } }); final Box cmdBox = new Box(BoxLayout.LINE_AXIS); cmdBox.add(commandLine); cmdBox.add(Box.createHorizontalStrut(10)); cmdBox.add(sendButton); cmdBox.setBorder(BorderFactory.createEmptyBorder(0, 7, 7, 7)); this.getContentPane().add(scrollPanel, BorderLayout.CENTER); this.getContentPane().add(cmdBox, BorderLayout.PAGE_END); this.setVisible(false); } public void setCommandLine(String command) { commandLine.setText(command); } /** * Shows console frame, sets location relative to parent. * * @param parent Frame relative to which console window will be localized. */ public void show(JFrame parent) { final Point parentLocation = parent.getLocation(); final Point location = new Point(parentLocation.x + 20, parentLocation.y + 20); this.setLocation(location); this.setVisible(true); } /** * Adds query to console window. * * @param line Line of string query. */ private void addQuery(String line) { consolePainter.userMsg(line + "\n"); } /** * Sends message to manager and adds message to console frame. */ public void buttonSendAction() { if (!connection.isConnected()) { JOptionPane.showMessageDialog(this, "missing connection to manager"); return; } String commandText = commandLine.getText(); Pair command = Strings.splitIntoPair(commandText, ' ', "\n"); Request request = Request.createRequestByTypeString(command.first); if (request == null) { log.warn("not a valid request: " + commandText); return; } request.parseRest(command.second); addQuery(commandText); addSentMessage(commandText); commandLine.setText(""); connection.send(request, new ResponseCallback() { @Override public void process(Response response) { for (File f : response.getFiles()) { consolePainter.paintMessage(f); } } }); } private void onKeyPressed(int keyCode) { if (keyCode == KeyEvent.VK_TAB) { String tmp = commandLine.getText(); int selStart = commandLine.getSelectionStart(); tmp = tmp.substring(0, selStart); if (selStart > 0) { if (tipList == null) { createTipList(tmp.substring(0, selStart)); tipIndex = tipList.size() - 1; } if (tipList.size() > 0) { String element = tipList.get(tipIndex); tipIndex--; if (tipIndex < 0) { tipIndex = tipList.size() - 1; } commandLine.setText(element); } } } else { tipList = null; } if (keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_DOWN) { int dir = (keyCode == KeyEvent.VK_UP ? -1 : 1); if (clearMsgIndex) { msgIndex = sentMessages.size(); clearMsgIndex = false; } msgIndex += dir; if (msgIndex < 0) { msgIndex = 0; } else if (msgIndex >= sentMessages.size()) { msgIndex = sentMessages.size() - 1; } String element = sentMessages.get(msgIndex); commandLine.setText(element); return; } if (keyCode == KeyEvent.VK_ENTER) { clearMsgIndex = true; buttonSendAction(); return; } clearMsgIndex = true; } /** * Creates commands tip list. * @param startText Text that user typed. */ private void createTipList(String startText) { tipList = new ArrayList(); for (String next : sentMessages) { if (next.startsWith(startText)) { tipList.add(next); } } } public void addSentMessage(String msg) { if (!sentMessages.contains(msg)) { sentMessages.add(msg); } } }