/** * Returns the zero-based index of the table column containing the current offset. Returns -1 if * we are not inside a table. */ public static int getCurrentColumnIndex(IVexWidget vexWidget) { VEXElement row = getCurrentTableRow(vexWidget); if (row == null) { return -1; } final int offset = vexWidget.getCaretOffset(); final int[] column = new int[] {-1}; LayoutUtils.iterateTableCells( vexWidget.getStyleSheet(), row, new ElementOrRangeCallback() { private int i = 0; public void onElement(Element child, String displayStyle) { if (offset > child.getStartOffset() && offset <= child.getEndOffset()) { column[0] = i; } i++; } public void onRange(VEXElement parent, int startOffset, int endOffset) { i++; } }); return column[0]; }
/** * Iterate over all rows in the table containing the caret. * * @param vexWidget IVexWidget to iterate over. * @param callback Caller-provided callback that this method calls for each row in the current * table. */ public static void iterateTableRows(IVexWidget vexWidget, ElementOrRangeCallback callback) { final StyleSheet ss = vexWidget.getStyleSheet(); final VEXDocument doc = vexWidget.getDocument(); final int offset = vexWidget.getCaretOffset(); // This may or may not be a table // In any case, it's the element that contains the top-level table // children VEXElement table = doc.getElementAt(offset); while (table != null && !LayoutUtils.isTableChild(ss, table)) { table = table.getParent(); } while (table != null && LayoutUtils.isTableChild(ss, table)) { table = table.getParent(); } if (table == null || table.getParent() == null) { return; } final List<Element> tableChildren = new ArrayList<Element>(); final boolean[] found = new boolean[] {false}; LayoutUtils.iterateChildrenByDisplayStyle( ss, LayoutUtils.TABLE_CHILD_STYLES, table, new ElementOrRangeCallback() { public void onElement(Element child, String displayStyle) { if (offset >= child.getStartOffset() && offset <= child.getEndOffset()) { found[0] = true; } tableChildren.add(child); } public void onRange(VEXElement parent, int startOffset, int endOffset) { if (!found[0]) { tableChildren.clear(); } } }); if (!found[0]) { return; } int startOffset = tableChildren.get(0).getStartOffset(); int endOffset = tableChildren.get(tableChildren.size() - 1).getEndOffset() + 1; LayoutUtils.iterateTableRows(ss, table, startOffset, endOffset, callback); }
/** * Returns a RowColumnInfo structure containing information about the table containing the caret. * Returns null if the caret is not currently inside a table. * * @param vexWidget IVexWidget to inspect. */ public static RowColumnInfo getRowColumnInfo(IVexWidget vexWidget) { final boolean[] found = new boolean[1]; final RowColumnInfo[] rcInfo = new RowColumnInfo[] {new RowColumnInfo()}; final int offset = vexWidget.getCaretOffset(); rcInfo[0].cellIndex = -1; rcInfo[0].rowIndex = -1; iterateTableCells( vexWidget, new ITableCellCallback() { private int rowColumnCount; public void startRow(Object row, int rowIndex) { rowColumnCount = 0; } public void onCell(Object row, Object cell, int rowIndex, int cellIndex) { found[0] = true; if (LayoutUtils.elementOrRangeContains(row, offset)) { rcInfo[0].row = row; rcInfo[0].rowIndex = rowIndex; rcInfo[0].columnCount++; if (LayoutUtils.elementOrRangeContains(cell, offset)) { rcInfo[0].cell = cell; rcInfo[0].cellIndex = cellIndex; } } rowColumnCount++; } public void endRow(Object row, int rowIndex) { rcInfo[0].rowCount++; rcInfo[0].maxColumnCount = Math.max(rcInfo[0].maxColumnCount, rowColumnCount); } }); if (found[0]) { return rcInfo[0]; } else { return null; } }