/*
 * File:     EditTypeDialog.java
 * Project:  MPI Linguistic Application
 * Date:     03 April 2006
 *
 * Copyright (C) 2001-2006  Max Planck Institute for Psycholinguistics
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package mpi.eudico.client.annotator.gui;

import mpi.eudico.client.annotator.Constants;
import mpi.eudico.client.annotator.ElanLocale;

import mpi.eudico.client.annotator.commands.Command;
import mpi.eudico.client.annotator.commands.ELANCommandFactory;

import mpi.eudico.server.corpora.clom.Tier;
import mpi.eudico.server.corpora.clom.Transcription;

import mpi.eudico.server.corpora.clomimpl.abstr.TierImpl;
import mpi.eudico.server.corpora.clomimpl.abstr.TranscriptionImpl;
import mpi.eudico.server.corpora.clomimpl.type.Constraint;
import mpi.eudico.server.corpora.clomimpl.type.ControlledVocabulary;
import mpi.eudico.server.corpora.clomimpl.type.IncludedIn;
import mpi.eudico.server.corpora.clomimpl.type.LinguisticType;
import mpi.eudico.server.corpora.clomimpl.type.SymbolicAssociation;
import mpi.eudico.server.corpora.clomimpl.type.SymbolicSubdivision;
import mpi.eudico.server.corpora.clomimpl.type.TimeSubdivision;

import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import java.util.Iterator;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;


/**
 * The DefineTypeDialog is a custom dialog for adding a Linguistic Type resp.
 * changing its attributes
 *
 * @author Alexander Klassmann
 * @version November 2001
 * @version Aug 2005 Identity removed
 */
public class EditTypeDialog extends JDialog implements ActionListener,
    ItemListener {
    /** Holds value of property DOCUMENT ME! */
    public static final int ADD = 0;

    /** Holds value of property DOCUMENT ME! */
    public static final int CHANGE = 1;

    /** Holds value of property DOCUMENT ME! */
    public static final int DELETE = 2;
    private TranscriptionImpl transcription;
    private LinguisticType oldType;
    private Vector types;
    private String oldConstraint;

    /** Holds value of property DOCUMENT ME! */
    public final String none = "None";
    private Frame frame;

    //    private String oldType=new String();
    private JLabel titleLabel = new JLabel();
    private JLabel currentTypesLabel = new JLabel();
    private JLabel typeLabel = new JLabel();
    private JLabel alignableLabel = new JLabel();
    private JLabel graphicReferencesLabel = new JLabel();
    private JLabel constraintsLabel = new JLabel();
    private JLabel cvLabel = new JLabel();
    private JTextField typeTextField = new JTextField(30);
    private JButton changeButton = new JButton();
    private JButton cancelButton = new JButton();
    private JCheckBox timeAlignableCheckbox = new JCheckBox("", false);
    private JCheckBox graphicReferencesCheckbox = new JCheckBox("", false);
    private JComboBox constraints = new JComboBox();
    private JComboBox currentTypes = new JComboBox();
    private JComboBox cvComboBox = new JComboBox();
    private JPanel buttonPanel = new JPanel(new GridLayout(1, 2, 6, 2));
    private int mode = ADD;

    /**
     * A general purpose constructor for adding, changing or deleting a
     * LinguisticType.<br>
     *
     * @param theFrame the parent frame
     * @param modal whether the dialog should be modal or not
     * @param theTranscription the Transcription containing the types
     * @param theIdentity the user identity, can be null
     * @param editMode the type of dialog, ADD, CHANGE or DELETE
     */
    public EditTypeDialog(Frame theFrame, boolean modal,
        Transcription theTranscription, int editMode) {
        super(theFrame, modal);
        frame = theFrame;
        transcription = (TranscriptionImpl) theTranscription;

        if ((editMode == ADD) || (editMode == CHANGE) || (editMode == DELETE)) {
            mode = editMode;
        }

        extractCurrentTypes();
        extractControlledVocabularies();
        createDialog();
        updateForModeAndLocale();
        pack();
        setResizable(false);
        setLocationRelativeTo(frame);

        if (editMode == ADD) {
            typeTextField.requestFocus();
        }
    }

    /**
     * Extract the linguistic types already present in the transcription.
     */
    private void extractCurrentTypes() {
        currentTypes.removeItemListener(this);
        currentTypes.removeAllItems();
        types = transcription.getLinguisticTypes();

        if (types == null) {
            types = new Vector();

            return;
        }

        LinguisticType lt = null;
        Iterator tIter = types.iterator();

        while (tIter.hasNext()) {
            lt = (LinguisticType) tIter.next();
            currentTypes.addItem(lt.getLinguisticTypeName());
        }

        currentTypes.addItemListener(this);
    }

    /**
     * Again axtract the types from the transcription after an add, change or
     * delete operation.
     */
    private void reextractTypes() {
        extractCurrentTypes();

        if (currentTypes.getItemCount() > 0) {
            currentTypes.setSelectedIndex(0);

            String name = (String) currentTypes.getSelectedItem();

            if (name != null) {
                updateUIForType(name);
            }
        } else {
            typeTextField.setText("");
        }

        if (mode == ADD) {
            typeTextField.setText("");
        }
    }

    /**
     * Fills the cv combo box with the Controlled Vocabularies present  in the
     * Transcription.
     */
    private void extractControlledVocabularies() {
        Vector cv = ((TranscriptionImpl) transcription).getControlledVocabularies();
        cvComboBox.addItem(none);

        for (int i = 0; i < cv.size(); i++) {
            cvComboBox.addItem(((ControlledVocabulary) cv.get(i)).getName());
        }
    }

    /**
     * Initialize UI elements with the attributes from the first element in the
     * types list.
     *
     * @param typeName the name of the LinguisticType
     */
    private void updateUIForType(String typeName) {
        if (typeName != null) {
            typeTextField.setText(typeName);

            Iterator typeIt = types.iterator();
            LinguisticType lt;

            while (typeIt.hasNext()) {
                lt = (LinguisticType) typeIt.next();

                if ((lt != null) &&
                        lt.getLinguisticTypeName().equals(typeName)) {
                    constraints.removeItemListener(this);

                    Constraint oldC = lt.getConstraints();

                    if (oldC != null) {
                        String stereoType = Constraint.stereoTypes[oldC.getStereoType()];
                        oldConstraint = stereoType;
                        constraints.setSelectedItem(stereoType);
                    } else {
                        oldConstraint = none;
                        constraints.setSelectedItem(none);
                    }

                    timeAlignableCheckbox.setSelected(lt.isTimeAlignable());
                    graphicReferencesCheckbox.setSelected(lt.hasGraphicReferences());

                    if (lt.isUsingControlledVocabulary()) {
                        String cvName = lt.getControlledVocabylaryName();
                        cvComboBox.getModel().setSelectedItem(cvName);
                    } else {
                        cvComboBox.getModel().setSelectedItem(none);
                    }

                    constraints.addItemListener(this);

                    break;
                }
            }
        }
    }

    private void createDialog() {
        timeAlignableCheckbox.setEnabled(false);

        // HB, 9-7-02, add 'None' to stereoTypes menu
        constraints.addItem(none);
        timeAlignableCheckbox.setSelected(true);

        //get all stereotypes and add them to the choice menu
        String[] publicStereoTypes = Constraint.publicStereoTypes;

        for (int i = 0; i < publicStereoTypes.length; i++) {
            constraints.addItem(publicStereoTypes[i]);
        }

        titleLabel.setFont(titleLabel.getFont().deriveFont((float) 16));

        // HS 24-07-2002: itemListener added for displaying the right status
        // of the timeAlignableCheckbox
        constraints.addItemListener(this);
        changeButton.addActionListener(this);
        cancelButton.addActionListener(this);

        buttonPanel.add(changeButton);
        buttonPanel.add(cancelButton);

        addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent event) {
                    dispose();
                }
            });

        //add Components
        getContentPane().setLayout(new GridBagLayout());

        GridBagConstraints c = new GridBagConstraints();
        c.insets = new Insets(2, 6, 2, 6);

        c.anchor = GridBagConstraints.NORTH;
        c.gridwidth = GridBagConstraints.REMAINDER;
        getContentPane().add(titleLabel, c);

        c.anchor = GridBagConstraints.WEST;
        c.gridwidth = 1;
        getContentPane().add(currentTypesLabel, c);

        currentTypes.setMaximumRowCount(Constants.COMBOBOX_VISIBLE_ROWS);
        c.gridwidth = GridBagConstraints.REMAINDER;
        getContentPane().add(currentTypes, c);

        c.anchor = GridBagConstraints.WEST;
        c.gridwidth = 1;

        //c.insets    = new Insets(0,0,0,0);
        getContentPane().add(typeLabel, c);

        c.gridwidth = GridBagConstraints.REMAINDER;
        getContentPane().add(typeTextField, c);

        // HS 17-06-2002: time-alignable checkbox and stereotypes added
        c.anchor = GridBagConstraints.WEST;
        c.gridwidth = 1;

        //c.insets    = new Insets(0,0,0,0);
        getContentPane().add(constraintsLabel, c);

        c.gridwidth = GridBagConstraints.REMAINDER;
        getContentPane().add(constraints, c);

        c.gridwidth = 1;
        getContentPane().add(cvLabel, c);

        c.gridwidth = GridBagConstraints.REMAINDER;
        getContentPane().add(cvComboBox, c);

        c.anchor = GridBagConstraints.WEST;
        c.gridwidth = 1;

        //c.insets    = new Insets(0,0,0,0);
        getContentPane().add(alignableLabel, c);

        c.gridwidth = GridBagConstraints.REMAINDER;
        getContentPane().add(timeAlignableCheckbox, c);

        c.gridwidth = 1;

        //c.insets	= new Insets(0,0,0,0);
        getContentPane().add(graphicReferencesLabel, c);

        c.gridwidth = GridBagConstraints.REMAINDER;
        getContentPane().add(graphicReferencesCheckbox, c);

        c.gridx = GridBagConstraints.RELATIVE;
        c.anchor = GridBagConstraints.SOUTH;

        //c.insets    = new Insets(5,0,5,0);
        c.fill = GridBagConstraints.NONE;
        getContentPane().add(buttonPanel, c);

        //pack();
        //setResizable(false);
        //setLocationRelativeTo(frame);
    }

    /**
     * Update the UI elements according to the current Locale and the current
     * edit mode.
     */
    private void updateForModeAndLocale() {
        typeLabel.setText(ElanLocale.getString("EditTypeDialog.Label.Type"));
        alignableLabel.setText(ElanLocale.getString(
                "EditTypeDialog.Label.TimeAlignable"));
        graphicReferencesLabel.setText(ElanLocale.getString(
                "EditTypeDialog.Label.Graphics"));
        constraintsLabel.setText(ElanLocale.getString(
                "EditTypeDialog.Label.Stereotype"));
        cvLabel.setText(ElanLocale.getString("EditTypeDialog.Label.CV"));
        cancelButton.setText(ElanLocale.getString("Button.Close"));

        switch (mode) {
        case ADD:
            setTitle(ElanLocale.getString("EditTypeDialog.Title.Add"));
            currentTypesLabel.setText(ElanLocale.getString(
                    "EditTypeDialog.CurrentTypes"));
            changeButton.setText(ElanLocale.getString("Button.Add"));

            break;

        case CHANGE:
            setTitle(ElanLocale.getString("EditTypeDialog.Title.Change"));
            currentTypesLabel.setText(ElanLocale.getString(
                    "EditTypeDialog.ChangeType"));
            changeButton.setText(ElanLocale.getString("Button.Change"));

            if (currentTypes.getModel().getSize() > 0) {
                updateUIForType((String) currentTypes.getItemAt(0));
                currentTypes.addItemListener(this);
            } else {
                changeButton.setEnabled(false);
            }

            //oldConstraint = (String)constraints.getSelectedItem();
            break;

        case DELETE:
            setTitle(ElanLocale.getString("EditTypeDialog.Title.Delete"));
            currentTypesLabel.setText(ElanLocale.getString(
                    "EditTypeDialog.DeleteType"));
            changeButton.setText(ElanLocale.getString("Button.Delete"));

            if (currentTypes.getModel().getSize() > 0) {
                updateUIForType((String) currentTypes.getItemAt(0));
                currentTypes.addItemListener(this);

                //typeTextField.setText((String)currentTypes.getItemAt(0));
            } else {
                changeButton.setEnabled(false);
            }

            typeTextField.setEditable(false);
            constraints.setEnabled(false);
            cvComboBox.setEnabled(false);
            graphicReferencesCheckbox.setEnabled(false);

            break;
        }

        titleLabel.setText(getTitle());
    }

    /**
     * Utility method for creating a Constraint for a given name.
     *
     * @param name the name of the constraint
     *
     * @return a Constraint or <code>null</code>
     */
    private Constraint getConstraintForName(String name) {
        Constraint c = null;

        if (name.equals(Constraint.stereoTypes[Constraint.TIME_SUBDIVISION])) {
            c = new TimeSubdivision();
        } else if (name.equals(
                    Constraint.stereoTypes[Constraint.SYMBOLIC_SUBDIVISION])) {
            c = new SymbolicSubdivision();
        } else if (name.equals(
                    Constraint.stereoTypes[Constraint.SYMBOLIC_ASSOCIATION])) {
            c = new SymbolicAssociation();
        } else if (name.equals(Constraint.stereoTypes[Constraint.INCLUDED_IN])) {
            c = new IncludedIn();
        }

        return c;
    }

    private void doAdd(String name) {
        // check existence
        LinguisticType lt = null;
        Iterator tIter = types.iterator();

        while (tIter.hasNext()) {
            lt = (LinguisticType) tIter.next();

            if (lt.getLinguisticTypeName().equals(name)) {
                String errorMessage = ElanLocale.getString(
                        "EditTypeDialog.Message.Exists");
                typeTextField.requestFocus();
                JOptionPane.showMessageDialog(this, errorMessage,
                    ElanLocale.getString("Message.Error"),
                    JOptionPane.ERROR_MESSAGE);

                return;
            }
        }

        //create new type
        String cons = (String) constraints.getSelectedItem();
        Constraint c = getConstraintForName(cons);
        boolean alignable = timeAlignableCheckbox.isSelected();
        boolean graphicsRef = graphicReferencesCheckbox.isSelected();
        String cvName = (String) cvComboBox.getSelectedItem();

        if (cvName.equals(none)) {
            cvName = null;
        }

        //create and execute a command
        Command com = ELANCommandFactory.createCommand(transcription,
                ELANCommandFactory.ADD_TYPE);
        Object[] args = new Object[5];
        args[0] = name;
        args[1] = c;
        args[2] = cvName;
        args[3] = new Boolean(alignable);
        args[4] = new Boolean(graphicsRef);
        com.execute(transcription, args);

        reextractTypes();

        //dispose();
    }

    private void doChange(String name) {
        String oldName = (String) currentTypes.getSelectedItem();
        LinguisticType lt = null;
        LinguisticType iterType = null;
        Iterator tIter = types.iterator();

        while (tIter.hasNext()) {
            iterType = (LinguisticType) tIter.next();

            if (iterType.getLinguisticTypeName().equals(oldName)) {
                lt = iterType;
            }

            if (iterType.getLinguisticTypeName().equals(name) &&
                    (iterType != lt)) {
                // name already exists
                String errorMessage = ElanLocale.getString(
                        "EditTypeDialog.Message.Exists");
                typeTextField.requestFocus();
                JOptionPane.showMessageDialog(this, errorMessage,
                    ElanLocale.getString("Message.Error"),
                    JOptionPane.ERROR_MESSAGE);

                return;
            }
        }

        if (lt == null) {
            // something is wrong
            String errorMessage = ElanLocale.getString(
                    "EditTypeDialog.Message.UnknownError");
            JOptionPane.showMessageDialog(this, errorMessage,
                ElanLocale.getString("Message.Error"), JOptionPane.ERROR_MESSAGE);

            //dispose();
            return;
        }

        String oldCV = null;

        if (lt.isUsingControlledVocabulary()) {
            oldCV = lt.getControlledVocabylaryName();
        }

        boolean oldGraphicsRef = lt.hasGraphicReferences();

        String cons = (String) constraints.getSelectedItem();
        Constraint c = getConstraintForName(cons);

        String cvName = (String) cvComboBox.getSelectedItem();

        if (cvName.equals(none)) {
            cvName = null;
        }

        boolean alignable = timeAlignableCheckbox.isSelected();
        boolean graphicsRef = graphicReferencesCheckbox.isSelected();

        // if nothing has changed do nothing
        if (name.equals(oldName) &&
                (((c == null) && (lt.getConstraints() == null)) ||
                (c == lt.getConstraints())) &&
                (((oldCV == null) && (cvName == null)) ||
                ((oldCV != null) && oldCV.equals(cvName))) &&
                (lt.isTimeAlignable() == alignable) &&
                (oldGraphicsRef == graphicsRef)) {
            return;
        }

        // warn if graphic references allowed has been deselected...
        if (oldGraphicsRef && !graphicsRef) {
            String warning = ElanLocale.getString(
                    "EditTypeDialog.Message.GraphicsLost") + "\n" +
                ElanLocale.getString("EditTypeDialog.Message.Confirm");
            int option = JOptionPane.showConfirmDialog(this, warning,
                    ElanLocale.getString("Message.Warning"),
                    JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);

            if (option != JOptionPane.YES_OPTION) {
                return;
            }
        }

        if (graphicsRef) {
            // check whether there are tiers using this type and 
            // whether these are the first tiers allowing graphic refs	
            checkGraphics(lt);
        }

        //create and execute a command
        Object[] args = new Object[6];
        args[0] = name;
        args[1] = c;
        args[2] = cvName;
        args[3] = new Boolean(alignable);
        args[4] = new Boolean(graphicsRef);
        args[5] = lt;

        Command com = ELANCommandFactory.createCommand(transcription,
                ELANCommandFactory.CHANGE_TYPE);
        com.execute(transcription, args);

        reextractTypes();

        //dispose();
    }

    private void doDelete() {
        String oldName = (String) currentTypes.getSelectedItem();
        LinguisticType lt = null;
        Iterator tIter = types.iterator();

        while (tIter.hasNext()) {
            lt = (LinguisticType) tIter.next();

            if (lt.getLinguisticTypeName().equals(oldName)) {
                break;
            }
        }

        if (lt == null) {
            // something is wrong
            String errorMessage = ElanLocale.getString(
                    "EditTypeDialog.Message.UnknownError");
            JOptionPane.showMessageDialog(this, errorMessage,
                ElanLocale.getString("Message.Error"), JOptionPane.ERROR_MESSAGE);

            //dispose();
            return;
        } else {
            //warn
            Vector clientTiers = transcription.getTiersWithLinguisticType(oldName);

            if (clientTiers.size() > 0) {
                StringBuffer errorBuffer = new StringBuffer(ElanLocale.getString(
                            "EditTypeDialog.Message.TypeInUse"));
                errorBuffer.append(":\n");

                Iterator clIter = clientTiers.iterator();

                while (clIter.hasNext()) {
                    errorBuffer.append("- ");
                    errorBuffer.append(((Tier) clIter.next()).getName());
                    errorBuffer.append("\n");
                }

                errorBuffer.append(ElanLocale.getString(
                        "EditTypeDialog.Message.Reassign"));
                JOptionPane.showMessageDialog(this, errorBuffer.toString(),
                    ElanLocale.getString("Message.Warning"),
                    JOptionPane.ERROR_MESSAGE);

                return;
            }
        }

        //create and execute a command
        Command com = ELANCommandFactory.createCommand(transcription,
                ELANCommandFactory.DELETE_TYPE);
        com.execute(transcription, new Object[] { lt });

        reextractTypes();

        //dispose();
    }

    /**
     * Shows a warning message when the document needs to be reopened  to view
     * graphic annotations.
     *
     * @param type the modified linguistic type
     */
    private void checkGraphics(LinguisticType type) {
        Vector tiersOfType = transcription.getTiersWithLinguisticType(type.getLinguisticTypeName());
        boolean alreadyThere = false;
        Vector allTiers = transcription.getTiers();
        Iterator tierIt = allTiers.iterator();
        TierImpl tier;
        LinguisticType otherType;

        while (tierIt.hasNext()) {
            tier = (TierImpl) tierIt.next();
            otherType = tier.getLinguisticType();

            if ((otherType != type) && otherType.hasGraphicReferences()) {
                alreadyThere = true;

                break;
            }
        }

        if (!alreadyThere && (tiersOfType.size() > 0)) {
            JOptionPane.showMessageDialog(this,
                ElanLocale.getString("EditTierDialog.Message.Graphics"),
                ElanLocale.getString("Message.Warning"),
                JOptionPane.WARNING_MESSAGE);
        }
    }

    //listeners
    public void actionPerformed(ActionEvent event) {
        if (event.getSource() == changeButton) {
            if (mode == DELETE) {
                doDelete();
            } else {
                String typeName = typeTextField.getText();
                typeName.replace('\n', ' ');
                typeName.trim();

                if (typeName.length() == 0) {
                    String errorMessage = ElanLocale.getString(
                            "EditTypeDialog.Message.TypeName");
                    typeTextField.requestFocus();
                    JOptionPane.showMessageDialog(this, errorMessage,
                        ElanLocale.getString("Message.Error"),
                        JOptionPane.ERROR_MESSAGE);

                    return;
                } else {
                    switch (mode) {
                    case ADD:
                        doAdd(typeName);

                        break;

                    case CHANGE:
                        doChange(typeName);

                        break;

                    default:
                        return;
                    }
                }
            }
        } else {
            dispose();
        }
    }

    /**
     * DOCUMENT ME!
     *
     * @param e DOCUMENT ME!
     */
    public void itemStateChanged(ItemEvent e) {
        if ((e.getSource() == currentTypes) &&
                (e.getStateChange() == ItemEvent.SELECTED)) {
            String name = (String) currentTypes.getSelectedItem();

            if (name != null) {
                updateUIForType(name);
            }
        } else if ((e.getSource() == constraints) &&
                (e.getStateChange() == ItemEvent.SELECTED)) {
            String constraint = (String) constraints.getSelectedItem();

            if ((constraint == none) || (constraint == "Time Subdivision")) {
                timeAlignableCheckbox.setSelected(true);
                graphicReferencesCheckbox.setEnabled(true);
            } else if ((constraint == "Symbolic Subdivision") ||
                    (constraint == "Symbolic Association")) {
                timeAlignableCheckbox.setSelected(false);
                graphicReferencesCheckbox.setSelected(false); // ??
                graphicReferencesCheckbox.setEnabled(false);
            }

            //if ((e.getSource() == constraints) && (oldType != null)) {	// warn if tiers use the type
            if ((mode == CHANGE) && (oldConstraint != constraint)) {
                String typeName = (String) currentTypes.getSelectedItem();
                Vector tiers = transcription.getTiersWithLinguisticType(typeName);

                if (tiers.size() > 0) {
                    StringBuffer mesBuf = new StringBuffer(ElanLocale.getString(
                                "EditTypeDialog.Message.TypeInUse"));
                    mesBuf.append("\n");
                    mesBuf.append(ElanLocale.getString(
                            "EditTypeDialog.Message.Corrupt"));
                    JOptionPane.showMessageDialog(null, mesBuf.toString(),
                        ElanLocale.getString("Message.Warning"),
                        JOptionPane.WARNING_MESSAGE);

                    /*
                       // HB, 9 may 03, restore old stereotype
                       Constraint oldC = oldType.getConstraints();
                       String oldStereoType = none;
                       if (oldC != null) {
                           oldStereoType = Constraint.stereoTypes[oldC.getStereoType()];
                       }
                       constraints.setSelectedItem(oldStereoType);
                     */
                    updateUIForType(typeName);
                }
            }
        }
    }
}
