Qualtagh/JBroTable

How to add columns into ModelFieldGroup dynamically?

Closed this issue · 4 comments

Hello, does it possible add columns dynamically into ModelFieldGroup or to realise it in future?

Hi!
I'm sorry for a late response.
Yes, it's possible.

ModelData data = table.getData();
ModelRow rows[] = data.getRows();
// Here goes your logic of adding a new column:
int idx[] = data.getIndexOfModelFieldGroup( "group_id" ); // get existing group position
ModelFieldGroup group = ( ModelFieldGroup )data.getFieldGroups().get( idx[ 1 ] )[ idx[ 0 ] ]; // get group itself
group.withChild( new ModelField( "unique_id", "caption" ) ); // add a new column as a child
// Important step! Copy fields data:
data = new ModelData( ModelField.copyOfModelFields( data.getFields() ) );
// Extend existing rows (if you use ModelRow):
for ( ModelRow row : rows ) // it just adds an empty cell at the end
  row.setLength( row.getLength() + 1 ); // provide data and shift cells if needed
data.setRows( rows );
table.setData( data );

Wow! Thanks. I'll try it.
I made it in more complicated way. Like i understand ModelFieldGroup must have at least one ModelField, at start i must show empty group so at init JBroTable i add some "EMPTY_COLUMN", but after adding new column i remove it.

/**
     * Add new column in last position of specific FieldGroup into JBroTable 
     */
    private void addColumnIntoJBroTable(JBroTable broTable, String insertIntoFieldGroupIdentifier, String newColumnIdentifier, String newColumnHeader) {
        try {
            IModelFieldGroup prevGroups[], newGroups[];

            prevGroups = broTable.getModel().getData().getFieldGroups().get(0);
            int groupLength = prevGroups.length;
            newGroups = new IModelFieldGroup[groupLength];
            for (int a = groupLength - 1; a >= 0; a--) {
                if (!prevGroups[a].getIdentifier().equals(insertIntoFieldGroupIdentifier)) {
                    newGroups[a] = prevGroups[a];
                } else {
                    ModelFieldGroup modelFieldGroup = new ModelFieldGroup(insertIntoFieldGroupIdentifier, insertIntoFieldGroupIdentifier);
                    for (IModelFieldGroup childField : ((ModelFieldGroup) prevGroups[a]).getChildren()) {
                        if (!childField .getIdentifier().equals(EMPTY_COLUMN))
                            modelFieldGroup.withChild(childField );
                    }
                    modelFieldGroup.withChild(new ModelField(newColumnIdentifier, newColumnHeader));
                    newGroups[a] = modelFieldGroup;
                }
            }
            //initilize future columns ModelFields
            ModelField[] modelFields = ModelFieldGroup.getBottomFields(newGroups);

            //expand table data row array to column length
            int columnsNewCount = modelFields.length;
            ModelRow[] prevModelRowsData = broTable.getModel().getData().getRows();
            if (prevModelRowsData != null)
                for (ModelRow modelRow : prevModelRowsData) {
                    modelRow.setLength(columnsNewCount);
                    for (int a = modelRow.getValues().length; a >= 0; a--) {
                        if (modelRow.getValue(a) == null) {
                            modelRow.setValue(a, new String());
                        }
                    }
                }

            //set new fields model
            broTable.getModel().getData().setFields(modelFields);
            //set data for table with new column structure
            broTable.getModel().getData().setRows(prevModelRowsData);
            //fire update gui of table
            broTable.getModel().fireTableStructureChanged();
            //restore renderer for columns
            defineCellRendererAndEditor(broTable);
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    }

Like i understand ModelFieldGroup must have at least one ModelField

It's not intended to. I have just checked an empty ModelData for JBroTableColumnModelShowcase test and it works. It's a bug if it doesn't work in some situation. Post a sample as an issue please and I'll try to fix it.

Ok. For this topic of issue your answer is work, with one remark, need check if there is no data(rows) in table. And i'll recommend to restore renderers and editors after this operation if they have been set before.
At the end i get this

/**
     * Добавить колонку в группу колонок таблицы JBroTable
     * Add new column in last position of specific FieldGroup
     * @param broTable JBroTable source table
     * @param existingFieldGroupIdentifier String identifier of ModelFieldGroup where you need to add a column
     * @param newColumnIdentifier String identifier of a new column, must be unique
     * @param newColumnHeader String header name of new column
     */
    private void addColumnIntoJBroTableFieldGroup(JBroTable broTable, String existingFieldGroupIdentifier, String newColumnIdentifier, String newColumnHeader) {
        try {
            ModelData data = broTable.getData();
            ModelRow rows[] = data.getRows();
            // Here goes your logic of adding a new column:
            int idx[] = data.getIndexOfModelFieldGroup(existingFieldGroupIdentifier); // get existing group position
            ModelFieldGroup group = (ModelFieldGroup) data.getFieldGroups().get(idx[1])[idx[0]]; // get group itself
            group.withChild(new ModelField(newColumnIdentifier, newColumnHeader)); // add a new column as a child
            // Important step! Copy fields data:
            data = new ModelData(ModelField.copyOfModelFields(data.getFields()));
            // Extend existing rows (if you use ModelRow):
            if (rows != null)
                for (ModelRow row : rows) // it just adds an empty cell at the end
                    row.setLength(row.getLength() + 1); // provide data and shift cells if needed
            data.setRows(rows);
            broTable.setData(data);
            //restore renderer for columns
            //defineCellRendererAndEditor(broTable);
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    }