/**
   * Creates preview for the device(video) in the video container.
   *
   * @param device the device
   * @param videoContainer the container
   * @throws IOException a problem accessing the device.
   * @throws MediaException a problem getting preview.
   */
  private static void createPreview(MediaDevice device, final JComponent videoContainer)
      throws IOException, MediaException {
    videoContainer.removeAll();

    videoContainer.revalidate();
    videoContainer.repaint();

    if (device == null) return;

    Component c =
        (Component)
            GuiActivator.getMediaService()
                .getVideoPreviewComponent(
                    device, videoContainer.getSize().width, videoContainer.getSize().height);

    videoContainer.add(c);
  }
  /**
   * Saves all configuration settings when the "Save" button is pressed.
   *
   * @param e the <tt>ActionEvent</tt> that notified us of the button action
   */
  public void actionPerformed(ActionEvent e) {
    JButton button = (JButton) e.getSource();

    if (button.equals(saveButton)) {
      Iterator<ChatRoomConfigurationFormField> configurationSet = configForm.getConfigurationSet();

      while (configurationSet.hasNext()) {
        ChatRoomConfigurationFormField formField = configurationSet.next();

        // If the field is of type fixed the user could not change it,
        // so we skip it.
        if (formField.getType().equals(ChatRoomConfigurationFormField.TYPE_TEXT_FIXED)) continue;

        JComponent c = uiFieldsTable.get(formField.getName());

        if (c instanceof JTextComponent) {
          String newValue = ((JTextComponent) c).getText();

          if (formField.getType().equals(ChatRoomConfigurationFormField.TYPE_ID_MULTI)) {
            // extract values
            StringTokenizer idTokens =
                new StringTokenizer(newValue, System.getProperty("line.separator"));
            while (idTokens.hasMoreTokens()) {
              formField.addValue(idTokens.nextToken());
            }
          } else formField.addValue(newValue);
        } else if (c instanceof AbstractButton) {
          boolean isSelected = ((AbstractButton) c).isSelected();

          formField.addValue(isSelected);
        } else if (c instanceof JComboBox) {
          Object selectedObject = ((JComboBox) c).getSelectedItem();

          formField.addValue(selectedObject);
        } else if (c instanceof JPanel) {
          Component[] components = c.getComponents();

          for (Component comp : components) {
            if (!(comp instanceof JCheckBox)) continue;

            JCheckBox checkBox = (JCheckBox) comp;

            formField.addValue(checkBox.getText());
          }
        }
      }

      new Thread() {
        @Override
        public void run() {
          try {
            configForm.submit();
          } catch (Exception e) {
            new ErrorDialog(
                    ChatRoomConfigurationWindow.this,
                    GuiActivator.getResources().getI18NString("service.gui.ERROR"),
                    GuiActivator.getResources()
                        .getI18NString("service.gui.CHAT_ROOM_CONFIGURATION_SUBMIT_FAILED"),
                    e)
                .showDialog();
          }
        }
      }.start();
    }

    this.dispose();
  }
  /**
   * Create preview component.
   *
   * @param comboBox the options.
   * @return the component.
   */
  private static Component createPreview(final JComboBox comboBox) {
    final JComponent preview;

    JLabel noPreview =
        new JLabel(GuiActivator.getResources().getI18NString("impl.media.configform.NO_PREVIEW"));
    noPreview.setHorizontalAlignment(SwingConstants.CENTER);
    noPreview.setVerticalAlignment(SwingConstants.CENTER);

    preview = createVideoContainer(noPreview);

    preview.setPreferredSize(new Dimension(WIDTH, 280));
    preview.setMaximumSize(new Dimension(WIDTH, 280));

    final ActionListener comboBoxListener =
        new ActionListener() {
          public void actionPerformed(ActionEvent event) {
            MediaDevice device = (MediaDevice) comboBox.getSelectedItem();

            if ((device != null) && device.equals(videoDeviceInPreview)) return;

            Exception exception;
            try {
              createPreview(device, preview);
              exception = null;
            } catch (IOException ex) {
              exception = ex;
            } catch (MediaException ex) {
              exception = ex;
            }
            if (exception != null) {
              logger.error("Failed to create preview for device " + device, exception);

              device = null;
            }

            videoDeviceInPreview = device;
          }
        };
    comboBox.addActionListener(comboBoxListener);

    /*
     * We have to initialize the controls to reflect the configuration
     * at the time of creating this instance. Additionally, because the
     * video preview will stop when it and its associated controls
     * become unnecessary, we have to restart it when the mentioned
     * controls become necessary again. We'll address the two goals
     * described by pretending there's a selection in the video combo
     * box when the combo box in question becomes displayable.
     */
    comboBox.addHierarchyListener(
        new HierarchyListener() {
          public void hierarchyChanged(HierarchyEvent event) {
            if (((event.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0)
                && comboBox.isDisplayable()) {
              // let current changes end their execution
              // and after that trigger action on combobox
              SwingUtilities.invokeLater(
                  new Runnable() {
                    public void run() {
                      comboBoxListener.actionPerformed(null);
                    }
                  });
            } else {
              if (!comboBox.isDisplayable()) videoDeviceInPreview = null;
            }
          }
        });

    return preview;
  }
  /** Loads the configuration form obtained from the chat room. */
  protected void loadConfigurationForm() {
    Iterator<ChatRoomConfigurationFormField> configurationSet = configForm.getConfigurationSet();

    while (configurationSet.hasNext()) {
      ChatRoomConfigurationFormField formField = configurationSet.next();

      Iterator<?> values = formField.getValues();
      Iterator<String> options = formField.getOptions();

      JComponent field;
      JLabel label = new JLabel("", JLabel.RIGHT);

      if (formField.getLabel() != null) label.setText(formField.getLabel() + ": ");

      String fieldType = formField.getType();

      if (fieldType.equals(ChatRoomConfigurationFormField.TYPE_BOOLEAN)) {
        // Create a check box when the field is of type boolean.
        field = new SIPCommCheckBox(formField.getLabel());
        label.setText("");

        if (values.hasNext()) {
          ((JCheckBox) field).setSelected((Boolean) values.next());
        }
      } else if (fieldType.equals(ChatRoomConfigurationFormField.TYPE_TEXT_FIXED)) {
        field = new JLabel();

        if (values.hasNext()) {
          String value = values.next().toString();

          ((JLabel) field).setText(value);
          field.setFont(new Font(null, Font.ITALIC, 10));
          field.setForeground(Color.GRAY);
        }
      } else if (fieldType.equals(ChatRoomConfigurationFormField.TYPE_LIST_MULTI)) {
        field = new TransparentPanel(new GridLayout(0, 1));

        field.setBorder(BorderFactory.createLineBorder(Color.GRAY));

        Hashtable<Object, JCheckBox> optionCheckBoxes = new Hashtable<Object, JCheckBox>();

        while (options.hasNext()) {
          Object option = options.next();
          JCheckBox checkBox = new SIPCommCheckBox(option.toString());

          field.add(checkBox);
          optionCheckBoxes.put(option, checkBox);
        }

        while (values.hasNext()) {
          Object value = values.next();

          (optionCheckBoxes.get(value)).setSelected(true);
        }
      } else if (fieldType.equals(ChatRoomConfigurationFormField.TYPE_LIST_SINGLE)) {
        field = new JComboBox();

        while (options.hasNext()) {
          ((JComboBox) field).addItem(options.next());
        }

        if (values.hasNext()) {
          ((JComboBox) field).setSelectedItem(values.next());
        }
      } else if (fieldType.equals(ChatRoomConfigurationFormField.TYPE_TEXT_MULTI)) {
        field = new JEditorPane();

        if (values.hasNext()) {
          String value = values.next().toString();

          ((JEditorPane) field).setText(value);
        }
      } else if (fieldType.equals(ChatRoomConfigurationFormField.TYPE_TEXT_SINGLE)
          || fieldType.equals(ChatRoomConfigurationFormField.TYPE_ID_SINGLE)) {
        field = new JTextField();

        if (values.hasNext()) {
          String value = values.next().toString();

          ((JTextField) field).setText(value);
        }
      } else if (fieldType.equals(ChatRoomConfigurationFormField.TYPE_TEXT_PRIVATE)) {
        field = new JPasswordField();

        if (values.hasNext()) {
          String value = values.next().toString();

          ((JPasswordField) field).setText(value);
        }
      } else if (fieldType.equals(ChatRoomConfigurationFormField.TYPE_ID_MULTI)) {
        StringBuffer buff = new StringBuffer();

        while (values.hasNext()) {
          String value = values.next().toString();
          buff.append(value);

          if (values.hasNext()) buff.append(System.getProperty("line.separator"));
        }
        field = new JTextArea(buff.toString());
      } else {
        if (label.getText() == null) continue;

        field = new JTextField();

        if (values.hasNext()) {
          String value = values.next().toString();

          ((JTextField) field).setText(value);
        }
      }

      // If the field is not fixed (i.e. could be changed) we would like
      // to save it in a list in order to use it later when user saves
      // the configuration data.
      if (!fieldType.equals(ChatRoomConfigurationFormField.TYPE_TEXT_FIXED)) {
        uiFieldsTable.put(formField.getName(), field);
      }

      JPanel fieldPanel = new TransparentPanel(new GridLayout(1, 2));
      fieldPanel.setOpaque(false);

      if (!(field instanceof JLabel))
        fieldPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 8, 0));
      else fieldPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 1, 0));

      fieldPanel.add(label);
      fieldPanel.add(field);

      this.mainPanel.add(fieldPanel);
    }
  }