public Component getDemoPanel() {
    TableModel model = new SampleTableModel();

    _sortableTable = new SortableTable(model);
    _sortableTable.setAutoResizeMode(JideTable.AUTO_RESIZE_FILL);
    _sortableTable.setNestedTableHeader(true);
    _sortableTable.setFillsGrids(false);
    TableColumnGroup longText =
        new TableColumnGroup(
            "This is a very long column header title. You can resize the table header column and see how this long text automatically wraps according to the column width. "
                + "The current configuration specified {minimum two rows:f:red} and {maximum five rows:f:blue}. You could take a look at StyledLabelBuilderDemo to see what other annotations are available in the text.@r:3:2:5");
    longText.add(_sortableTable.getColumnModel().getColumn(0));
    longText.add(_sortableTable.getColumnModel().getColumn(1));
    longText.add(_sortableTable.getColumnModel().getColumn(2));
    longText.add(_sortableTable.getColumnModel().getColumn(3));
    longText.add(_sortableTable.getColumnModel().getColumn(4));
    longText.add(_sortableTable.getColumnModel().getColumn(5));
    longText.add(_sortableTable.getColumnModel().getColumn(6));

    if (_sortableTable.getTableHeader() instanceof NestedTableHeader) {
      NestedTableHeader header = (NestedTableHeader) _sortableTable.getTableHeader();
      header.addColumnGroup(longText);
    }
    TableHeaderPopupMenuInstaller installer = new TableHeaderPopupMenuInstaller(_sortableTable);
    installer.addTableHeaderPopupMenuCustomizer(new TableColumnChooserPopupMenuCustomizer());

    TableUtils.autoResizeAllColumns(_sortableTable);

    return new JScrollPane(_sortableTable);
  }
  public Component getDemoPanel() {
    JPanel panel = new JPanel(new BorderLayout(6, 6));
    DefaultTableModel model = new CustomizedTableModel(8, 8);
    model.setValueAt("no editing", 2, 2);
    model.setValueAt("no stop", 2, 3);
    model.setValueAt("valid", 2, 4);
    _table = new JideTable(model);
    _table.setNestedTableHeader(true);
    _table.setAlwaysRequestFocusForEditor(true);
    _table.setClickCountToStart(2);
    _table.setEditorAutoCompletionMode(JideTable.EDITOR_AUTO_COMPLETION_MODE_TABLE);

    TableColumnGroup all = new TableColumnGroup("AH");
    TableColumnGroup first = new TableColumnGroup("AB");
    first.add(_table.getColumnModel().getColumn(0));
    first.add(_table.getColumnModel().getColumn(1));
    TableColumnGroup second = new TableColumnGroup("CD");
    second.add(_table.getColumnModel().getColumn(2));
    second.add(_table.getColumnModel().getColumn(3));
    TableColumnGroup third = new TableColumnGroup("EF");
    third.add(_table.getColumnModel().getColumn(4));
    third.add(_table.getColumnModel().getColumn(5));
    TableColumnGroup fourth = new TableColumnGroup("GH");
    fourth.add(_table.getColumnModel().getColumn(6));
    fourth.add(_table.getColumnModel().getColumn(7));
    all.add(first);
    all.add(second);
    all.add(third);
    all.add(fourth);

    if (_table.getTableHeader() instanceof NestedTableHeader) {
      NestedTableHeader header = (NestedTableHeader) _table.getTableHeader();
      header.addColumnGroup(all);
    }

    panel.add(new JScrollPane(_table), BorderLayout.CENTER);
    _message = new JLabel();
    panel.add(_message, BorderLayout.AFTER_LAST_LINE);
    _table.addCellEditorListener(
        new JideCellEditorListener() {
          public boolean editingStarting(ChangeEvent e) {
            int row = ((CellChangeEvent) e).getRow();
            int column = ((CellChangeEvent) e).getColumn();
            if ("no editing".equals(_table.getValueAt(row, column))) {
              _message.setText("Editing is not started because editingStarting() returns false.");
              return false;
            } else {
              return true;
            }
          }

          public void editingStarted(ChangeEvent e) {}

          public boolean editingStopping(ChangeEvent e) {
            if (e.getSource() instanceof CellEditor) {
              if ("no stop".equals(((CellEditor) e.getSource()).getCellEditorValue())) {
                _message.setText("Editing is not stopped because editingStopping() returns false.");
                return false;
              }
            }
            return true;
          }

          public void editingCanceled(ChangeEvent e) {}

          public void editingStopped(ChangeEvent e) {}
        });

    _table.addValidator(
        new Validator() {
          public ValidationResult validating(ValidationObject e) {
            if ("invalid".equals(e.getNewValue())) {
              ValidationResult validationResult =
                  new ValidationResult(0, false, "The value is \"invalid\"");
              _message.setText(validationResult.getMessage());
              return validationResult;
            } else {
              return ValidationResult.OK;
            }
          }
        });
    _message.setForeground(Color.RED);
    _message.setText("");
    return panel;
  }