/* User pressed the "Update" button. Read the GUI fields and
  send a SettingsMsg with the requested values. When the
  requested settings are bad, we silently update them to sane
  values. */
  public void updateSettings() {
    SettingsMsg smsg = new SettingsMsg();
    short alert = 0;
    short detect = 0;
    int checkInterval = Constants.DEFAULT_CHECK_INTERVAL;

    /* Extract current interval value, fixing bad values */
    String intervalS = fieldInterval.getText().trim();
    try {
      int newInterval = Integer.parseInt(intervalS);
      if (newInterval < 10) throw new NumberFormatException();
      checkInterval = newInterval;
    } catch (NumberFormatException e) {
      /* Reset field when value is bad */
      fieldInterval.setText("" + checkInterval);
    }

    /* Extract alert settings */
    if (repLedCb.isSelected()) alert |= Constants.ALERT_LEDS;
    if (repSirenCb.isSelected()) alert |= Constants.ALERT_SOUND;
    if (repNeighboursCb.isSelected()) alert |= Constants.ALERT_RADIO;
    if (repServerCb.isSelected()) alert |= Constants.ALERT_ROOT;
    if (alert == 0) {
      /* If nothing select, force-select LEDs */
      alert = Constants.ALERT_LEDS;
      repLedCb.setSelected(true);
    }

    /* Extract detection settings */
    if (detDarkCb.isSelected()) detect |= Constants.DETECT_DARK;
    if (detAccelCb.isSelected()) detect |= Constants.DETECT_ACCEL;
    if (detect == 0) {
      /* If no detection selected, force-select dark */
      detect = Constants.DETECT_DARK;
      detDarkCb.setSelected(true);
    }

    /* Build and send settings message */
    smsg.set_alert(alert);
    smsg.set_detect(detect);
    smsg.set_checkInterval(checkInterval);
    try {
      mote.send(MoteIF.TOS_BCAST_ADDR, smsg);
    } catch (IOException e) {
      error("Cannot send message to mote");
    }
  }
  /* Build up the GUI using Swing magic. Nothing very exciting here - the
  BagPanel class makes the code a bit cleaner/easier to read. */
  private void guiInit() throws Exception {
    JPanel mainPanel = new JPanel(new BorderLayout());
    mainPanel.setMinimumSize(new Dimension(500, 250));
    mainPanel.setPreferredSize(new Dimension(500, 300));

    /* The message area */
    JScrollPane mssgPanel = new JScrollPane();
    mssgPanel.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    mssgPanel.setAutoscrolls(true);
    mssgArea = new JTextArea();
    mssgArea.setFont(new java.awt.Font("Monospaced", Font.PLAIN, 20));
    mainPanel.add(mssgPanel, BorderLayout.CENTER);
    mssgPanel.getViewport().add(mssgArea, null);

    /* The button area */
    BagPanel buttonPanel = new BagPanel();
    GridBagConstraints c = buttonPanel.c;

    c.fill = GridBagConstraints.HORIZONTAL;
    c.gridwidth = GridBagConstraints.REMAINDER;

    buttonPanel.makeLabel("Detection", JLabel.CENTER);
    c.gridwidth = GridBagConstraints.RELATIVE;
    detDarkCb = buttonPanel.makeCheckBox("Dark", true);
    c.gridwidth = GridBagConstraints.REMAINDER;
    detAccelCb = buttonPanel.makeCheckBox("Movement", false);
    buttonPanel.makeSeparator(SwingConstants.HORIZONTAL);

    buttonPanel.makeLabel("Theft Reports", JLabel.CENTER);
    c.gridwidth = GridBagConstraints.RELATIVE;
    repLedCb = buttonPanel.makeCheckBox("LED", true);
    c.gridwidth = GridBagConstraints.REMAINDER;
    repSirenCb = buttonPanel.makeCheckBox("Siren", false);
    c.gridwidth = GridBagConstraints.RELATIVE;
    repServerCb = buttonPanel.makeCheckBox("Server", false);
    c.gridwidth = GridBagConstraints.REMAINDER;
    repNeighboursCb = buttonPanel.makeCheckBox("Neighbours", false);
    buttonPanel.makeSeparator(SwingConstants.HORIZONTAL);

    buttonPanel.makeLabel("Interval", JLabel.CENTER);
    fieldInterval = buttonPanel.makeTextField(10, null);
    fieldInterval.setText(Integer.toString(Constants.DEFAULT_CHECK_INTERVAL));

    ActionListener settingsAction =
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            updateSettings();
          }
        };
    buttonPanel.makeButton("Update", settingsAction);

    mainPanel.add(buttonPanel, BorderLayout.EAST);

    /* The frame part */
    frame = new JFrame("AntiTheft");
    frame.setSize(mainPanel.getPreferredSize());
    frame.getContentPane().add(mainPanel);
    frame.setVisible(true);
    frame.addWindowListener(
        new WindowAdapter() {
          public void windowClosing(WindowEvent e) {
            System.exit(0);
          }
        });
  }