/* * Created on Jun 16, 2005 * */ package net.atlanticbb.tantlinger.ui.text.actions; import java.awt.event.ActionEvent; import java.io.StringWriter; import javax.swing.Action; import javax.swing.JEditorPane; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.Document; import javax.swing.text.Element; import javax.swing.text.html.HTML; import javax.swing.text.html.HTMLDocument; import org.bushe.swing.action.ShouldBeEnabledDelegate; import net.atlanticbb.tantlinger.ui.text.CompoundUndoManager; import net.atlanticbb.tantlinger.ui.text.ElementWriter; import net.atlanticbb.tantlinger.ui.text.HTMLUtils; /** * * Action for adding and removing table elements * * @author Bob Tantlinger * */ public class TableEditAction extends HTMLTextEditAction { /** * */ private static final long serialVersionUID = 1L; public static final int INSERT_CELL = 0; public static final int DELETE_CELL = 1; public static final int INSERT_ROW = 2; public static final int DELETE_ROW = 3; public static final int INSERT_COL = 4; public static final int DELETE_COL = 5; private static final String NAMES[] = { i18n.str("insert_cell"), i18n.str("delete_cell"), i18n.str("insert_row"), i18n.str("delete_row"), i18n.str("insert_column"), i18n.str("delete_column") }; private int type; public TableEditAction(int type) throws IllegalArgumentException { super(""); if(type < 0 || type >= NAMES.length) throw new IllegalArgumentException("Invalid type"); this.type = type; putValue(NAME, NAMES[type]); addShouldBeEnabledDelegate(new ShouldBeEnabledDelegate() { public boolean shouldBeEnabled(Action a) { return (getEditMode() != SOURCE) && isInTD(getCurrentEditor()); } }); } protected void wysiwygEditPerformed(ActionEvent e, JEditorPane ed) { HTMLDocument document = (HTMLDocument)ed.getDocument(); Element curElem = document.getParagraphElement(ed.getCaretPosition()); Element td = HTMLUtils.getParent(curElem, HTML.Tag.TD); Element tr = HTMLUtils.getParent(curElem, HTML.Tag.TR); //HTMLDocument document = getDocument(); if(td == null || tr == null || document == null) return; CompoundUndoManager.beginCompoundEdit(document); try { if(type == INSERT_CELL) document.insertAfterEnd(td, "<td></td>"); else if(type == DELETE_CELL) removeCell(td); else if(type == INSERT_ROW) insertRowAfter(tr); else if(type == DELETE_ROW) removeRow(tr); else if(type == INSERT_COL) insertColumnAfter(td); else if(type == DELETE_COL) removeColumn(td); } catch(Exception ex) { ex.printStackTrace(); } CompoundUndoManager.endCompoundEdit(document); } private void removeCell(Element td) throws Exception { Element tr = HTMLUtils.getParent(td, HTML.Tag.TR); if(tr != null && td.getName().equals("td")) { if(td.getEndOffset() != tr.getEndOffset()) remove(td); else if(getRowCellCount(tr) <= 1) remove(tr); else { StringWriter out = new StringWriter(); ElementWriter w = new ElementWriter(out, tr, tr.getStartOffset(), td.getStartOffset()); w.write(); HTMLDocument doc = (HTMLDocument)tr.getDocument(); doc.setOuterHTML(tr, out.toString()); } } } private void insertRowAfter(Element tr) throws Exception { Element table = HTMLUtils.getParent(tr, HTML.Tag.TABLE); if(table != null && tr.getName().equals("tr")) { HTMLDocument doc = (HTMLDocument)tr.getDocument(); if(tr.getEndOffset() != table.getEndOffset()) doc.insertAfterEnd(tr, getRowHTML(tr)); else { AttributeSet atr = table.getAttributes(); String tbl = HTMLUtils.getElementHTML(table, false); tbl += getRowHTML(tr); tbl = HTMLUtils.createTag(HTML.Tag.TABLE, atr, tbl); doc.setOuterHTML(table, tbl); } } } private void removeRow(Element tr) throws Exception { Element table = HTMLUtils.getParent(tr, HTML.Tag.TABLE); if(table != null && tr.getName().equals("tr")) { if(tr.getEndOffset() != table.getEndOffset()) remove(tr); else if(getTableRowCount(table) <= 1) remove(table); else { StringWriter out = new StringWriter(); ElementWriter w = new ElementWriter(out, table, table.getStartOffset(), tr.getStartOffset()); w.write(); HTMLDocument doc = (HTMLDocument)tr.getDocument(); doc.setOuterHTML(table, out.toString()); } } } private int getTableRowCount(Element table) { int count = 0; for(int i = 0; i < table.getElementCount(); i++) { Element e = table.getElement(i); if(e.getName().equals("tr")) count++; } return count; } private int getRowCellCount(Element tr) { int count = 0; for(int i = 0; i < tr.getElementCount(); i++) { Element e = tr.getElement(i); if(e.getName().equals("td")) count++; } return count; } private void remove(Element el) throws BadLocationException { int start = el.getStartOffset(); int len = el.getEndOffset() - start; Document document = el.getDocument(); if(el.getEndOffset() > document.getLength()) len = document.getLength() - start; document.remove(start, len); } private int getCellIndex(Element tr, Element td) { int tdIndex = -1; for(int i = 0; i < tr.getElementCount(); i++) { Element e = tr.getElement(i); if(e.getStartOffset() == td.getStartOffset()) { tdIndex = i; break; } } return tdIndex; } private void removeColumn(Element td) throws Exception { Element tr = HTMLUtils.getParent(td, HTML.Tag.TR); int tdIndex = getCellIndex(tr, td); if(tdIndex == -1) return; Element table = HTMLUtils.getParent(tr, HTML.Tag.TABLE); for(int i = 0; i < table.getElementCount(); i++) { Element row = table.getElement(i); if(row.getName().equals("tr")) { Element e = row.getElement(tdIndex); if(e != null && e.getName().equals("td")) removeCell(e); } } } private void insertColumnAfter(Element td) throws Exception { Element tr = HTMLUtils.getParent(td, HTML.Tag.TR); HTMLDocument doc = (HTMLDocument)tr.getDocument(); int tdIndex = getCellIndex(tr, td); if(tdIndex == -1) return; Element table = HTMLUtils.getParent(tr, HTML.Tag.TABLE); for(int i = 0; i < table.getElementCount(); i++) { Element row = table.getElement(i); if(row.getName().equals("tr")) { AttributeSet attr = row.getAttributes(); int cellCount = row.getElementCount(); String rowHTML = ""; String cell = "<td></td>"; for(int j = 0; j < cellCount; j++) { Element e = row.getElement(j); rowHTML += HTMLUtils.getElementHTML(e, true); if(j == tdIndex) rowHTML += cell; } int tds = row.getElementCount() - 1; if(tds < tdIndex) { for(; tds <= tdIndex; tds++) rowHTML += cell; } rowHTML = HTMLUtils.createTag(HTML.Tag.TR, attr, rowHTML); doc.setOuterHTML(row, rowHTML); } } } private String getRowHTML(Element tr) { String trTag = "<tr>"; if(tr.getName().equals("tr")) { for(int i = 0; i < tr.getElementCount(); i++) if (tr.getElement(i).getName().equals("td")) trTag += "<td></td>"; } trTag += "</tr>"; return trTag; } private boolean isInTD(JEditorPane tc) { Element td = null; if(tc != null) { HTMLDocument doc = (HTMLDocument)tc.getDocument(); try { Element curElem = doc.getParagraphElement(tc.getCaretPosition()); td = HTMLUtils.getParent(curElem, HTML.Tag.TD); } catch(Exception ex){} } return td != null; } protected void updateWysiwygContextState(JEditorPane wysEditor) { boolean isInTd = isInTD(wysEditor); if((isInTd && !isEnabled()) || (isEnabled() && !isInTd)) updateEnabled(); } /* (non-Javadoc) * @see net.atlanticbb.tantlinger.ui.text.actions.HTMLTextEditAction#sourceEditPerformed(java.awt.event.ActionEvent, javax.swing.JEditorPane) */ protected void sourceEditPerformed(ActionEvent e, JEditorPane editor) { } }