private void relayout(int propCount) {
   // Lay out the panel.
   SpringUtilities.makeCompactGrid(
       genericTagPropertiesEditPanel,
       propCount,
       3, // rows, cols
       6,
       6, // initX, initY
       6,
       6); // xPad, yPad
   revalidate();
   repaint();
 }
  public static void getCategories(
      Map<String, Component> componentsMap,
      Map<String, Component> tabs,
      JComboBox<?> skinComboBox,
      ResourceBundle resourceBundle) {
    Map<String, Map<String, Field>> categorized = new HashMap<>();

    Map<String, Field> fields = Configuration.getConfigurationFields();
    String[] keys = new String[fields.size()];
    keys = fields.keySet().toArray(keys);
    Arrays.sort(keys);

    for (String name : keys) {
      Field field = fields.get(name);
      ConfigurationCategory cat = field.getAnnotation(ConfigurationCategory.class);
      String scat = cat == null ? "other" : cat.value();
      if (!categorized.containsKey(scat)) {
        categorized.put(scat, new HashMap<>());
      }

      categorized.get(scat).put(name, field);
    }

    for (String cat : categorized.keySet()) {
      JPanel configPanel = new JPanel(new SpringLayout());
      int itemCount = 0;
      for (String name : categorized.get(cat).keySet()) {
        Field field = categorized.get(cat).get(name);

        String locName = resourceBundle.getString("config.name." + name);

        try {
          ConfigurationItem item = (ConfigurationItem) field.get(null);

          ParameterizedType listType = (ParameterizedType) field.getGenericType();
          java.lang.reflect.Type itemType2 = listType.getActualTypeArguments()[0];
          if (!(itemType2 instanceof Class<?>)) {
            continue;
          }

          Class itemType = (Class<?>) itemType2;

          String description = resourceBundle.getString("config.description." + name);

          Object defaultValue = Configuration.getDefaultValue(field);
          if (name.equals("gui.skin")) {
            Class c;
            try {
              c = Class.forName((String) defaultValue);
              defaultValue = c.getField("NAME").get(c);
            } catch (ClassNotFoundException | NoSuchFieldException | SecurityException ex) {
              Logger.getLogger(AdvancedSettingsDialog.class.getName()).log(Level.SEVERE, null, ex);
            }
          }

          if (defaultValue != null) {
            description += " (" + resourceBundle.getString("default") + ": " + defaultValue + ")";
          }

          JLabel l = new JLabel(locName, JLabel.TRAILING);
          l.setToolTipText(description);
          configPanel.add(l);
          Component c = null;
          if (name.equals("gui.skin")) {
            skinComboBox.setToolTipText(description);
            skinComboBox.setMaximumSize(
                new Dimension(Integer.MAX_VALUE, skinComboBox.getPreferredSize().height));
            c = skinComboBox;
          } else if ((itemType == String.class)
              || (itemType == Integer.class)
              || (itemType == Long.class)
              || (itemType == Double.class)
              || (itemType == Float.class)
              || (itemType == Calendar.class)) {
            JTextField tf = new JTextField();
            Object val = item.get();
            if (val == null) {
              val = "";
            }
            if (itemType == Calendar.class) {
              tf.setText(new SimpleDateFormat().format(((Calendar) item.get()).getTime()));
            } else {
              tf.setText(val.toString());
            }
            tf.setToolTipText(description);
            tf.setMaximumSize(new Dimension(Integer.MAX_VALUE, tf.getPreferredSize().height));
            c = tf;
          } else if (itemType == Boolean.class) {
            JCheckBox cb = new JCheckBox();
            cb.setSelected((Boolean) item.get());
            cb.setToolTipText(description);
            c = cb;
          } else if (itemType.isEnum()) {
            JComboBox<String> cb = new JComboBox<>();
            @SuppressWarnings("unchecked")
            EnumSet enumValues = EnumSet.allOf(itemType);
            String stringValue = null;
            for (Object enumValue : enumValues) {
              String enumValueStr = enumValue.toString();
              if (stringValue == null) {
                stringValue = enumValueStr;
              }
              cb.addItem(enumValueStr);
            }
            if (item.get() != null) {
              stringValue = item.get().toString();
            }
            cb.setToolTipText(description);
            cb.setSelectedItem(stringValue);
            cb.setMaximumSize(new Dimension(Integer.MAX_VALUE, cb.getPreferredSize().height));
            c = cb;
          } else {
            throw new UnsupportedOperationException(
                "Configuration ttem type '" + itemType.getName() + "' is not supported");
          }

          componentsMap.put(name, c);
          l.setLabelFor(c);
          configPanel.add(c);
        } catch (IllegalArgumentException | IllegalAccessException ex) {
          // Reflection exceptions. This should never happen
          throw new Error(ex.getMessage());
        }

        itemCount++;
      }

      SpringUtilities.makeCompactGrid(
          configPanel,
          itemCount,
          2, // rows, cols
          6,
          6, // initX, initY
          6,
          6); // xPad, yPad
      tabs.put(cat, new JScrollPane(configPanel));
    }
  }