/**
   * Creates the basic layout of the panel.
   *
   * @param c the container where all the components will be layed out.
   * @param gbc the grid bag constraints.
   */
  protected void createBasicLayout(Container c, GridBagConstraints gbc) {
    SuperiorObjectClassesChangedListener listener =
        new SuperiorObjectClassesChangedListener() {
          /** {@inheritDoc} */
          @Override
          public void parentObjectClassesChanged(SuperiorObjectClassesChangedEvent ev) {
            if (ignoreChangeEvents) {
              return;
            }
            updateAttributesWithParent(true);
            checkEnableSaveChanges();
            if (ev.getNewObjectClasses().size() > 1) {
              lSuperior.setText(INFO_CTRL_PANEL_OBJECTCLASS_PARENTS_LABEL.get().toString());
            } else {
              lSuperior.setText(INFO_CTRL_PANEL_OBJECTCLASS_PARENT_LABEL.get().toString());
            }
          }
        };
    superiors.addParentObjectClassesChangedListener(listener);

    DefaultComboBoxModel model = new DefaultComboBoxModel();
    for (ObjectClassType t : ObjectClassType.values()) {
      model.addElement(t);
    }
    type.setModel(model);
    type.setSelectedItem(ObjectClassType.STRUCTURAL);
    SchemaElementComboBoxCellRenderer renderer = new SchemaElementComboBoxCellRenderer(type);
    type.setRenderer(renderer);

    attributes = new DoubleAddRemovePanel<>(0, AttributeType.class);
    Comparator<AttributeType> comparator =
        new Comparator<AttributeType>() {
          /** {@inheritDoc} */
          @Override
          public int compare(AttributeType attr1, AttributeType attr2) {
            return attr1.getNameOrOID().toLowerCase().compareTo(attr2.getNameOrOID().toLowerCase());
          }
        };
    attributes.getAvailableListModel().setComparator(comparator);
    attributes.getSelectedListModel1().setComparator(comparator);
    attributes.getSelectedListModel2().setComparator(comparator);

    gbc.gridy = 0;
    gbc.gridwidth = 2;
    addErrorPane(c, gbc);
    gbc.gridy++;

    gbc.anchor = GridBagConstraints.WEST;
    titlePanel.setTitle(INFO_CTRL_PANEL_OBJECTCLASS_DETAILS.get());
    gbc.fill = GridBagConstraints.NONE;
    gbc.insets.top = 5;
    gbc.insets.bottom = 7;
    c.add(titlePanel, gbc);

    gbc.insets.bottom = 0;
    gbc.insets.top = 8;
    gbc.gridy++;
    gbc.gridwidth = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;

    Component[] basicComps = {name, oid, description, superiors};
    JLabel[] basicLabels = {lName, lOID, lDescription, lSuperior};
    JLabel[] basicInlineHelp = new JLabel[] {null, null, null, null};
    add(basicLabels, basicComps, basicInlineHelp, c, gbc);

    gbc.gridx = 0;
    gbc.weightx = 0.0;
    gbc.insets.left = 0;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.anchor = GridBagConstraints.NORTHWEST;
    c.add(lAttributes, gbc);

    gbc.gridx++;
    gbc.fill = GridBagConstraints.BOTH;
    gbc.weightx = 1.0;
    gbc.weighty = 1.0;
    gbc.insets.left = 10;
    c.add(attributes, gbc);
    attributes
        .getAvailableLabel()
        .setText(INFO_CTRL_PANEL_ADDREMOVE_AVAILABLE_ATTRIBUTES.get().toString());
    attributes
        .getSelectedLabel1()
        .setText(INFO_CTRL_PANEL_ADDREMOVE_REQUIRED_ATTRIBUTES.get().toString());
    attributes
        .getSelectedLabel2()
        .setText(INFO_CTRL_PANEL_ADDREMOVE_OPTIONAL_ATTRIBUTES.get().toString());
    AttributeTypeCellRenderer listRenderer = new AttributeTypeCellRenderer();
    attributes.getAvailableList().setCellRenderer(listRenderer);
    attributes.getSelectedList1().setCellRenderer(listRenderer);
    attributes.getSelectedList2().setCellRenderer(listRenderer);

    gbc.gridy++;
    gbc.weighty = 0.0;
    gbc.insets.top = 3;
    JLabel explanation =
        Utilities.createInlineHelpLabel(INFO_CTRL_PANEL_INHERITED_ATTRIBUTES_HELP.get());
    gbc.insets.top = 3;
    c.add(explanation, gbc);

    final BasicExpander expander = new BasicExpander(INFO_CTRL_PANEL_EXTRA_OPTIONS_EXPANDER.get());

    obsolete.setText("Obsolete");

    Component[] comps = {aliases, origin, file, type, obsolete};
    JLabel[] labels = {lAliases, lOrigin, lFile, lType, null};
    JLabel[] inlineHelps = {
      Utilities.createInlineHelpLabel(INFO_CTRL_PANEL_SEPARATED_WITH_COMMAS_HELP.get()),
      null,
      Utilities.createInlineHelpLabel(
          INFO_CTRL_PANEL_SCHEMA_FILE_OBJECTCLASS_HELP.get(File.separator)),
      null,
      null
    };
    gbc.gridwidth = 2;
    gbc.gridx = 0;
    gbc.weighty = 0.0;
    gbc.insets.left = 0;
    gbc.gridy++;
    c.add(expander, gbc);
    final JPanel p = new JPanel(new GridBagLayout());
    gbc.insets.left = 15;
    gbc.gridy++;
    c.add(p, gbc);
    gbc.gridy++;
    p.setOpaque(false);

    GridBagConstraints gbc1 = new GridBagConstraints();
    gbc1.fill = GridBagConstraints.HORIZONTAL;
    gbc1.gridy = 0;

    add(labels, comps, inlineHelps, p, gbc1);
    ChangeListener changeListener =
        new ChangeListener() {
          /** {@inheritDoc} */
          @Override
          public void stateChanged(ChangeEvent e) {
            p.setVisible(expander.isSelected());
          }
        };
    expander.addChangeListener(changeListener);
    expander.setSelected(false);
    changeListener.stateChanged(null);

    DocumentListener docListener =
        new DocumentListener() {
          /** {@inheritDoc} */
          @Override
          public void insertUpdate(DocumentEvent ev) {
            checkEnableSaveChanges();
          }

          /** {@inheritDoc} */
          @Override
          public void removeUpdate(DocumentEvent ev) {
            checkEnableSaveChanges();
          }

          /** {@inheritDoc} */
          @Override
          public void changedUpdate(DocumentEvent arg0) {
            checkEnableSaveChanges();
          }
        };
    JTextField[] tfs = {name, description, oid, aliases, origin, file};
    for (JTextField tf : tfs) {
      tf.getDocument().addDocumentListener(docListener);
    }

    ActionListener actionListener =
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent ev) {
            checkEnableSaveChanges();
          }
        };

    type.addActionListener(actionListener);

    ListDataListener dataListener =
        new ListDataListener() {
          /** {@inheritDoc} */
          @Override
          public void contentsChanged(ListDataEvent e) {
            checkEnableSaveChanges();
          }
          /** {@inheritDoc} */
          @Override
          public void intervalAdded(ListDataEvent e) {
            checkEnableSaveChanges();
          }
          /** {@inheritDoc} */
          @Override
          public void intervalRemoved(ListDataEvent e) {
            checkEnableSaveChanges();
          }
        };
    SortableListModel<AttributeType> list1 = attributes.getSelectedListModel1();
    SortableListModel<AttributeType> list2 = attributes.getSelectedListModel2();
    list1.addListDataListener(dataListener);
    list2.addListDataListener(dataListener);

    obsolete.addActionListener(actionListener);
  }