Articles Projects Tips Downloads Contacts About

Tables in the JEditorPane/JTextPane (Row and Column Insert).
By Stanislav Lapitsky

I was asked to extend the tables in JEditorPane example and add methods to insert Row and Column in existing table. The short article below shows how to add the required methods.

The code from previous article was changed a bit to use typified collections of ElementSpec and recompiled under java 1.5. The methods add row or column after row or column where caret is set. They search for deepest table in that case. Thus if there is a nested table and caret is set in a row of the nested table and the "Insert" is called the new row (or column) will be added in the nested table. The 4 following images shows how tables are changed after adding rows and columns.

Table before

and after

adding row.

Table before

and after

adding column.

When row/column insertion is called we get deepest table for the offset to find the target nested table. If table is found we get proper row/column number for current caret position and insert properly structured array of ElementSpec. For row we close paragraph, cell, and row tags. Then add row, cells, and paragraphs inside and again open appropriate tags.

For column insertion the algorithm is a bit more complicated. We iterate through all rows inserting new cell in proper position for each row.

The code of the methods is following:

    public void insertRow(int offset) {
        Element root=getDefaultRootElement();
        int ind=root.getElementIndex(offset);
 
        Element table=getDeepesttableFromOffset(root, offset);
        if (table!=null) {
            int rowIndex=table.getElementIndex(offset)+1;
            insertRow(table, rowIndex);
        }
    }
 
    public void insertCol(int offset) {
        Element root=getDefaultRootElement();
        int ind=root.getElementIndex(offset);
 
        Element table=getDeepesttableFromOffset(root, offset);
        if (table!=null) {
            int rowIndex=table.getElementIndex(offset);
            Element row=table.getElement(rowIndex);
            int colIndex=row.getElementIndex(offset);
            insertCol(table, colIndex);
        }
    }
 
    protected Element getDeepesttableFromOffset(Element root, int offset) {
        int ind=root.getElementIndex(offset);
        Element table=root.getElement(ind);
        if (table.getName().equalsIgnoreCase(ELEMENT_NAME_TABLE)) {
            int rowIndex=table.getElementIndex(offset);
            Element row=table.getElement(rowIndex);
            int cellIndex=row.getElementIndex(offset);
            Element cell=row.getElement(cellIndex);
 
            int newInd=cell.getElementIndex(offset);
            Element newTable=cell.getElement(newInd);
            if (!newTable.getName().equalsIgnoreCase(ELEMENT_NAME_TABLE)) {
                return table;
            }
            else {
                return getDeepesttableFromOffset(cell, offset);
            }
        }
 
        return null;
    }
 
    public void insertRow(Element table, int rowNumber) {
        try {
            int[] colWidths=new int[table.getElement(0).getElementCount()];
            for (int i=0; i< colWidths.length; i++) {
                Element cell=table.getElement(0).getElement(i);
                colWidths[i]=(Integer)cell.getAttributes().getAttribute(PARAM_CELL_WIDTH);
            }
 
            int offset=table.getStartOffset();
            if (rowNumber>=table.getElementCount()) {
                //add after last row
                offset=table.getEndOffset();
            }
            else {
                Element row=table.getElement(rowNumber);
                offset=row.getStartOffset();
            }
 
            int depth=getTableDepth(table);
            SimpleAttributeSet attrs=new SimpleAttributeSet();
            ArrayList<ElementSpec> specs=new ArrayList<ElementSpec>();
 
            specs.add(new ElementSpec(attrs, ElementSpec.EndTagType)); //close paragraph tag
            specs.add(new ElementSpec(attrs, ElementSpec.EndTagType)); //close cell tag
            specs.add(new ElementSpec(attrs, ElementSpec.EndTagType)); //close row tag
 
            fillRowSpecs(specs, 1, colWidths);
 
            specs.add(new ElementSpec(attrs, ElementSpec.StartTagType)); //open new row
            specs.add(new ElementSpec(attrs, ElementSpec.StartTagType)); //open new cell
            specs.add(new ElementSpec(attrs, ElementSpec.StartTagType)); //open new paragraph
 
            ElementSpec[] spec = new ElementSpec[specs.size()];
            specs.toArray(spec);
 
            insert(offset, spec);
        } catch (BadLocationException e) {
            e.printStackTrace();  
        }

    }
    public void insertCol(Element table, int colNumber) {
        try {
            int colWidth=(Integer)table.getElement(0).getElement(colNumber).getAttributes().getAttribute(PARAM_CELL_WIDTH);
 
            for (int rn=0; rn<table.getElementCount(); rn++) {
                Element row=table.getElement(rn);
                Element cell=row.getElement(colNumber);
 
                SimpleAttributeSet attrs=new SimpleAttributeSet();
                ArrayList<ElementSpec> specs=new ArrayList<ElementSpec>();
 
                specs.add(new ElementSpec(attrs, ElementSpec.EndTagType)); //close paragraph tag
                specs.add(new ElementSpec(attrs, ElementSpec.EndTagType)); //close cell tag
 
                fillCellSpecs(specs, new int[] {colWidth});
 
                specs.add(new ElementSpec(attrs, ElementSpec.StartTagType)); //open new row
                specs.add(new ElementSpec(attrs, ElementSpec.StartTagType)); //open new cell
 
                ElementSpec[] spec = new ElementSpec[specs.size()];
                specs.toArray(spec);
 
                insert(cell.getEndOffset(), spec);
            }
        } catch (BadLocationException e) {
            e.printStackTrace();
        }

    }

You can download the example .jar file here. All the source code is included in the .jar file.

Back to Table of Content