X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=apps%2FOscilloscope%2Fjava%2FWindow.java;fp=apps%2FOscilloscope%2Fjava%2FWindow.java;h=d7979bf9f251b7656fbdbda5282522e06fcb488f;hb=1ba974b83d19fc41bf80acd52726f36f7f1df297;hp=0000000000000000000000000000000000000000;hpb=4db69a460ad5d18d33cbf5c3ef74ad584d9e2886;p=tinyos-2.x.git diff --git a/apps/Oscilloscope/java/Window.java b/apps/Oscilloscope/java/Window.java new file mode 100644 index 00000000..d7979bf9 --- /dev/null +++ b/apps/Oscilloscope/java/Window.java @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2006 Intel Corporation + * All rights reserved. + * + * This file is distributed under the terms in the attached INTEL-LICENSE + * file. If you do not find these files, copies can be found by writing to + * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, + * 94704. Attention: Intel License Inquiry. + */ + +import javax.swing.*; +import javax.swing.table.*; +import javax.swing.event.*; +import java.awt.*; +import java.awt.event.*; +import java.util.*; + +/* The main GUI object. Build the GUI and coordinate all user activities */ +class Window +{ + Oscilloscope parent; + Graph graph; + + Font smallFont = new Font("Dialog", Font.PLAIN, 8); + Font boldFont = new Font("Dialog", Font.BOLD, 12); + Font normalFont = new Font("Dialog", Font.PLAIN, 12); + MoteTableModel moteListModel; // GUI view of mote list + JLabel xLabel; // Label displaying X axis range + JTextField sampleText, yText; // inputs for sample period and Y axis range + JFrame frame; + + Window(Oscilloscope parent) { + this.parent = parent; + } + + /* A model for the mote table, and general utility operations on the mote + list */ + class MoteTableModel extends AbstractTableModel { + private ArrayList motes = new ArrayList(); + private ArrayList colors = new ArrayList(); + + /* Initial mote colors cycle through this list. Add more colors if + you want. */ + private Color[] cycle = { + Color.RED, Color.WHITE, Color.GREEN, Color.MAGENTA, + Color.YELLOW, Color.GRAY, Color.YELLOW + }; + int cycleIndex; + + /* TableModel methods for achieving our table appearance */ + public String getColumnName(int col) { + if (col == 0) + return "Mote"; + else + return "Color"; + } + public int getColumnCount() { return 2; } + public synchronized int getRowCount() { return motes.size(); } + public synchronized Object getValueAt(int row, int col) { + if (col == 0) + return motes.get(row); + else + return colors.get(row); + } + public Class getColumnClass(int col) { + return getValueAt(0, col).getClass(); + } + public boolean isCellEditable(int row, int col) { return col == 1; } + public synchronized void setValueAt(Object value, int row, int col) { + colors.set(row, value); + fireTableCellUpdated(row, col); + graph.repaint(); + } + + /* Return mote id of i'th mote */ + int get(int i) { return ((Integer)motes.get(i)).intValue(); } + + /* Return color of i'th mote */ + Color getColor(int i) { return (Color)colors.get(i); } + + /* Return number of motes */ + int size() { return motes.size(); } + + /* Add a new mote */ + synchronized void newNode(int nodeId) { + /* Shock, horror. No binary search. */ + int i, len = motes.size(); + + for (i = 0; ; i++) + if (i == len || nodeId < get(i)) { + motes.add(i, new Integer(nodeId)); + // Cycle through a set of initial colors + colors.add(i, cycle[cycleIndex++ % cycle.length]); + break; + } + fireTableRowsInserted(i, i); + } + + /* Remove all motes */ + void clear() { + motes = new ArrayList(); + colors = new ArrayList(); + fireTableDataChanged(); + } + } + + /* A simple full-color cell */ + static class MoteColor extends JLabel implements TableCellRenderer { + public MoteColor() { setOpaque(true); } + public Component getTableCellRendererComponent + (JTable table, Object color, + boolean isSelected, boolean hasFocus, int row, int column) { + setBackground((Color)color); + return this; + } + } + + /* Convenience methods for making buttons, labels and textfields. + Simplifies code and ensures a consistent style. */ + + JButton makeButton(String label, ActionListener action) { + JButton button = new JButton(); + button.setText(label); + button.setFont(boldFont); + button.addActionListener(action); + return button; + } + + JLabel makeLabel(String txt, int alignment) { + JLabel label = new JLabel(txt, alignment); + label.setFont(boldFont); + return label; + } + + JLabel makeSmallLabel(String txt, int alignment) { + JLabel label = new JLabel(txt, alignment); + label.setFont(smallFont); + return label; + } + + JTextField makeTextField(int columns, ActionListener action) { + JTextField tf = new JTextField(columns); + tf.setFont(normalFont); + tf.setMaximumSize(tf.getPreferredSize()); + tf.addActionListener(action); + return tf; + } + + /* Build the GUI */ + void setup() { + JPanel main = new JPanel(new BorderLayout()); + + main.setMinimumSize(new Dimension(500, 250)); + main.setPreferredSize(new Dimension(800, 400)); + + // Three panels: mote list, graph, controls + moteListModel = new MoteTableModel(); + JTable moteList = new JTable(moteListModel); + moteList.setDefaultRenderer(Color.class, new MoteColor()); + moteList.setDefaultEditor(Color.class, new ColorCellEditor("Pick Mote Color")); + moteList.setPreferredScrollableViewportSize(new Dimension(100, 400)); + JScrollPane motePanel = new JScrollPane(); + motePanel.getViewport().add(moteList, null); + main.add(motePanel, BorderLayout.WEST); + + graph = new Graph(this); + main.add(graph, BorderLayout.CENTER); + + // Controls. Organised using box layouts. + + // Sample period. + JLabel sampleLabel = makeLabel("Sample period (ms):", JLabel.RIGHT); + sampleText = makeTextField(6, new ActionListener() { + public void actionPerformed(ActionEvent e) { setSamplePeriod(); } + } ); + updateSamplePeriod(); + + // Clear data. + JButton clearButton = makeButton("Clear data", new ActionListener() { + public void actionPerformed(ActionEvent e) { clearData(); } + } ); + + // Adjust X-axis zoom. + Box xControl = new Box(BoxLayout.Y_AXIS); + xLabel = makeLabel("", JLabel.CENTER); + final JSlider xSlider = new JSlider(JSlider.HORIZONTAL, 0, 8, graph.scale); + Hashtable xTable = new Hashtable(); + for (int i = 0; i <= 8; i += 2) + xTable.put(new Integer(i), + makeSmallLabel("" + (Graph.MIN_WIDTH << i), + JLabel.CENTER)); + xSlider.setLabelTable(xTable); + xSlider.setPaintLabels(true); + graph.updateXLabel(); + graph.setScale(graph.scale); + xSlider.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + //if (!xSlider.getValueIsAdjusting()) + graph.setScale((int)xSlider.getValue()); + } + }); + xControl.add(xLabel); + xControl.add(xSlider); + + // Adjust Y-axis range. + JLabel yLabel = makeLabel("Y:", JLabel.RIGHT); + yText = makeTextField(12, new ActionListener() { + public void actionPerformed(ActionEvent e) { setYAxis(); } + } ); + yText.setText(graph.gy0 + " - " + graph.gy1); + + Box controls = new Box(BoxLayout.X_AXIS); + controls.add(clearButton); + controls.add(Box.createHorizontalGlue()); + controls.add(Box.createRigidArea(new Dimension(20, 0))); + controls.add(sampleLabel); + controls.add(sampleText); + controls.add(Box.createHorizontalGlue()); + controls.add(Box.createRigidArea(new Dimension(20, 0))); + controls.add(xControl); + controls.add(yLabel); + controls.add(yText); + main.add(controls, BorderLayout.SOUTH); + + // The frame part + frame = new JFrame("Oscilloscope"); + frame.setSize(main.getPreferredSize()); + frame.getContentPane().add(main); + frame.setVisible(true); + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { System.exit(0); } + }); + } + + /* User operation: clear data */ + void clearData() { + synchronized (parent) { + moteListModel.clear(); + parent.clear(); + graph.newData(); + } + } + + /* User operation: set Y-axis range. */ + void setYAxis() { + String val = yText.getText(); + + try { + int dash = val.indexOf('-'); + if (dash >= 0) { + String min = val.substring(0, dash).trim(); + String max = val.substring(dash + 1).trim(); + + if (!graph.setYAxis(Integer.parseInt(min), Integer.parseInt(max))) + error("Invalid range " + min + " - " + max + " (expected values between 0 and 65535)"); + return; + } + } + catch (NumberFormatException e) { } + error("Invalid range " + val + " (expected NN-MM)"); + } + + /* User operation: set sample period. */ + void setSamplePeriod() { + String periodS = sampleText.getText().trim(); + try { + int newPeriod = Integer.parseInt(periodS); + if (parent.setInterval(newPeriod)) + return; + } + catch (NumberFormatException e) { } + error("Invalid sample period " + periodS); + } + + /* Notification: sample period changed. */ + void updateSamplePeriod() { + sampleText.setText("" + parent.interval); + } + + /* Notification: new node. */ + void newNode(int nodeId) { + moteListModel.newNode(nodeId); + } + + /* Notification: new data. */ + void newData() { + graph.newData(); + } + + void error(String msg) { + JOptionPane.showMessageDialog(frame, msg, "Error", + JOptionPane.ERROR_MESSAGE); + } +}