X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fjexer%2FTTableWidget.java;h=749b7313c9e29874cacacc431305ebf81e6d70ce;hb=HEAD;hp=c001109a93d966732b27d264ba4a58b1b17dba9d;hpb=2b4274048c2f409b5eba8373ab3018aa75911c73;p=fanfix.git diff --git a/src/jexer/TTableWidget.java b/src/jexer/TTableWidget.java index c001109..749b731 100644 --- a/src/jexer/TTableWidget.java +++ b/src/jexer/TTableWidget.java @@ -28,17 +28,20 @@ */ package jexer; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import java.util.ResourceBundle; import jexer.bits.CellAttributes; +import jexer.bits.StringUtils; import jexer.event.TKeypressEvent; -import jexer.event.TMenuEvent; import jexer.event.TMouseEvent; import jexer.event.TResizeEvent; -import jexer.menu.TMenu; import static jexer.TKeypress.*; /** @@ -51,11 +54,6 @@ import static jexer.TKeypress.*; */ public class TTableWidget extends TWidget { - /** - * Translated strings. - */ - private static final ResourceBundle i18n = ResourceBundle.getBundle(TTableWidget.class.getName()); - // ------------------------------------------------------------------------ // Constants -------------------------------------------------------------- // ------------------------------------------------------------------------ @@ -85,6 +83,11 @@ public class TTableWidget extends TWidget { THICK, } + /** + * If true, put a grid of numbers in the cells. + */ + private static final boolean DEBUG = false; + /** * Row label width. */ @@ -103,12 +106,12 @@ public class TTableWidget extends TWidget { /** * Extra rows to add. */ - private static final int EXTRA_ROWS = 10; + private static final int EXTRA_ROWS = (DEBUG ? 10 : 0); /** * Extra columns to add. */ - private static final int EXTRA_COLUMNS = 10 * (8 + 1); + private static final int EXTRA_COLUMNS = (DEBUG ? 3 : 0); // ------------------------------------------------------------------------ // Variables -------------------------------------------------------------- @@ -611,65 +614,82 @@ public class TTableWidget extends TWidget { * @param y row relative to parent * @param width width of widget * @param height height of widget + * @param gridColumns number of columns in grid + * @param gridRows number of rows in grid */ public TTableWidget(final TWidget parent, final int x, final int y, - final int width, final int height) { + final int width, final int height, final int gridColumns, + final int gridRows) { super(parent, x, y, width, height); + /* + System.err.println("gridColumns " + gridColumns + + " gridRows " + gridRows); + */ + + if (gridColumns < 1) { + throw new IllegalArgumentException("Column count cannot be less " + + "than 1"); + } + if (gridRows < 1) { + throw new IllegalArgumentException("Row count cannot be less " + + "than 1"); + } + // Initialize the starting row and column. rows.add(new Row(0)); columns.add(new Column(0)); + assert (rows.get(0).height == 1); // Place a grid of cells that fit in this space. - int row = 0; - for (int i = 0; i < height + EXTRA_ROWS; i += rows.get(0).height) { - int column = 0; - for (int j = 0; j < width + EXTRA_COLUMNS; - j += columns.get(0).width) { - - Cell cell = new Cell(this, 0, 0, /* j, i, */ columns.get(0).width, - rows.get(0).height, column, row); - - // DEBUG: set a grid of cell index labels - // TODO: remove this - cell.setText("" + row + " " + column); + for (int row = 0; row < gridRows; row++) { + for (int column = 0; column < gridColumns; column++) { + Cell cell = new Cell(this, 0, 0, COLUMN_DEFAULT_WIDTH, 1, + column, row); + + if (DEBUG) { + // For debugging: set a grid of cell index labels. + cell.setText("" + row + " " + column); + } rows.get(row).add(cell); columns.get(column).add(cell); - if ((i == 0) && - (j + columns.get(0).width < width + EXTRA_COLUMNS) - ) { + + if (columns.size() < gridColumns) { columns.add(new Column(column + 1)); } - column++; } - if (i + rows.get(0).height < height + EXTRA_ROWS) { + if (row < gridRows - 1) { rows.add(new Row(row + 1)); } - row++; } for (int i = 0; i < rows.size(); i++) { rows.get(i).setY(i + (showColumnLabels ? COLUMN_LABEL_HEIGHT : 0)); } for (int j = 0; j < columns.size(); j++) { - columns.get(j).setX((j * COLUMN_DEFAULT_WIDTH) + + columns.get(j).setX((j * (COLUMN_DEFAULT_WIDTH + 1)) + (showRowLabels ? ROW_LABEL_WIDTH : 0)); } activate(columns.get(selectedColumn).get(selectedRow)); alignGrid(); + } - // Set the menu to match the flags. - getApplication().getMenuItem(TMenu.MID_TABLE_VIEW_ROW_LABELS). - setChecked(showRowLabels); - getApplication().getMenuItem(TMenu.MID_TABLE_VIEW_COLUMN_LABELS). - setChecked(showColumnLabels); - getApplication().getMenuItem(TMenu.MID_TABLE_VIEW_HIGHLIGHT_ROW). - setChecked(highlightRow); - getApplication().getMenuItem(TMenu.MID_TABLE_VIEW_HIGHLIGHT_COLUMN). - setChecked(highlightColumn); - + /** + * Public constructor. + * + * @param parent parent widget + * @param x column relative to parent + * @param y row relative to parent + * @param width width of widget + * @param height height of widget + */ + public TTableWidget(final TWidget parent, final int x, final int y, + final int width, final int height) { + this(parent, x, y, width, height, + width / (COLUMN_DEFAULT_WIDTH + 1) + EXTRA_COLUMNS, + height + EXTRA_ROWS); } // ------------------------------------------------------------------------ @@ -801,185 +821,7 @@ public class TTableWidget extends TWidget { public void onResize(final TResizeEvent event) { super.onResize(event); - alignGrid(); - } - - /** - * Handle posted menu events. - * - * @param menu menu event - */ - @Override - public void onMenu(final TMenuEvent menu) { - TInputBox inputBox; - - switch (menu.getId()) { - case TMenu.MID_TABLE_RENAME_COLUMN: - inputBox = inputBox(i18n.getString("renameColumnInputTitle"), - i18n.getString("renameColumnInputCaption"), - getColumnLabel(selectedColumn), TMessageBox.Type.OKCANCEL); - if (inputBox.isOk()) { - setColumnLabel(selectedColumn, inputBox.getText()); - } - break; - case TMenu.MID_TABLE_RENAME_ROW: - inputBox = inputBox(i18n.getString("renameRowInputTitle"), - i18n.getString("renameRowInputCaption"), - getRowLabel(selectedRow), TMessageBox.Type.OKCANCEL); - if (inputBox.isOk()) { - setRowLabel(selectedRow, inputBox.getText()); - } - break; - case TMenu.MID_TABLE_VIEW_ROW_LABELS: - showRowLabels = getApplication().getMenuItem(menu.getId()).getChecked(); - break; - case TMenu.MID_TABLE_VIEW_COLUMN_LABELS: - showColumnLabels = getApplication().getMenuItem(menu.getId()).getChecked(); - break; - case TMenu.MID_TABLE_VIEW_HIGHLIGHT_ROW: - highlightRow = getApplication().getMenuItem(menu.getId()).getChecked(); - break; - case TMenu.MID_TABLE_VIEW_HIGHLIGHT_COLUMN: - highlightColumn = getApplication().getMenuItem(menu.getId()).getChecked(); - break; - case TMenu.MID_TABLE_BORDER_NONE: - topBorder = Border.NONE; - leftBorder = Border.NONE; - for (int i = 0; i < columns.size(); i++) { - columns.get(i).rightBorder = Border.NONE; - } - for (int i = 0; i < rows.size(); i++) { - rows.get(i).bottomBorder = Border.NONE; - rows.get(i).height = 1; - } - break; - case TMenu.MID_TABLE_BORDER_ALL: - topBorder = Border.SINGLE; - leftBorder = Border.SINGLE; - for (int i = 0; i < columns.size(); i++) { - columns.get(i).rightBorder = Border.SINGLE; - } - for (int i = 0; i < rows.size(); i++) { - rows.get(i).bottomBorder = Border.SINGLE; - rows.get(i).height = 2; - } - break; - case TMenu.MID_TABLE_BORDER_CELL_NONE: - if (selectedRow == 0) { - topBorder = Border.NONE; - } - if (selectedColumn == 0) { - leftBorder = Border.NONE; - } - columns.get(selectedColumn).rightBorder = Border.NONE; - rows.get(selectedRow).bottomBorder = Border.NONE; - rows.get(selectedRow).height = 1; - break; - case TMenu.MID_TABLE_BORDER_CELL_ALL: - if (selectedRow == 0) { - topBorder = Border.SINGLE; - } - if (selectedColumn == 0) { - leftBorder = Border.SINGLE; - } - columns.get(selectedColumn).rightBorder = Border.SINGLE; - rows.get(selectedRow).bottomBorder = Border.SINGLE; - rows.get(selectedRow).height = 2; - break; - case TMenu.MID_TABLE_BORDER_RIGHT: - columns.get(selectedColumn).rightBorder = Border.SINGLE; - break; - case TMenu.MID_TABLE_BORDER_LEFT: - if (selectedColumn == 0) { - leftBorder = Border.SINGLE; - } else { - columns.get(selectedColumn - 1).rightBorder = Border.SINGLE; - } - break; - case TMenu.MID_TABLE_BORDER_TOP: - if (selectedRow == 0) { - topBorder = Border.SINGLE; - } else { - rows.get(selectedRow - 1).bottomBorder = Border.SINGLE; - rows.get(selectedRow - 1).height = 2; - } - break; - case TMenu.MID_TABLE_BORDER_BOTTOM: - rows.get(selectedRow).bottomBorder = Border.SINGLE; - rows.get(selectedRow).height = 2; - break; - case TMenu.MID_TABLE_BORDER_DOUBLE_BOTTOM: - rows.get(selectedRow).bottomBorder = Border.DOUBLE; - rows.get(selectedRow).height = 2; - break; - case TMenu.MID_TABLE_BORDER_THICK_BOTTOM: - rows.get(selectedRow).bottomBorder = Border.THICK; - rows.get(selectedRow).height = 2; - break; - case TMenu.MID_TABLE_DELETE_LEFT: - deleteCellShiftLeft(); - activate(columns.get(selectedColumn).get(selectedRow)); - break; - case TMenu.MID_TABLE_DELETE_UP: - deleteCellShiftUp(); - activate(columns.get(selectedColumn).get(selectedRow)); - break; - case TMenu.MID_TABLE_DELETE_ROW: - deleteRow(selectedColumn); - activate(columns.get(selectedColumn).get(selectedRow)); - break; - case TMenu.MID_TABLE_DELETE_COLUMN: - deleteColumn(selectedColumn); - activate(columns.get(selectedColumn).get(selectedRow)); - break; - case TMenu.MID_TABLE_INSERT_LEFT: - insertColumnLeft(selectedColumn); - activate(columns.get(selectedColumn).get(selectedRow)); - break; - case TMenu.MID_TABLE_INSERT_RIGHT: - insertColumnRight(selectedColumn); - activate(columns.get(selectedColumn).get(selectedRow)); - break; - case TMenu.MID_TABLE_INSERT_ABOVE: - insertRowAbove(selectedColumn); - activate(columns.get(selectedColumn).get(selectedRow)); - break; - case TMenu.MID_TABLE_INSERT_BELOW: - insertRowBelow(selectedColumn); - activate(columns.get(selectedColumn).get(selectedRow)); - break; - case TMenu.MID_TABLE_COLUMN_NARROW: - columns.get(selectedColumn).width--; - for (Cell cell: getSelectedColumn().cells) { - cell.setWidth(columns.get(selectedColumn).width); - cell.field.setWidth(columns.get(selectedColumn).width); - } - for (int i = selectedColumn + 1; i < columns.size(); i++) { - columns.get(i).setX(columns.get(i).getX() - 1); - } - break; - case TMenu.MID_TABLE_COLUMN_WIDEN: - columns.get(selectedColumn).width++; - for (Cell cell: getSelectedColumn().cells) { - cell.setWidth(columns.get(selectedColumn).width); - cell.field.setWidth(columns.get(selectedColumn).width); - } - for (int i = selectedColumn + 1; i < columns.size(); i++) { - columns.get(i).setX(columns.get(i).getX() + 1); - } - break; - case TMenu.MID_TABLE_FILE_SAVE_CSV: - // TODO - break; - case TMenu.MID_TABLE_FILE_SAVE_TEXT: - // TODO - break; - default: - super.onMenu(menu); - } - - // Fix/redraw the display. - alignGrid(); + bottomRightCorner(); } // ------------------------------------------------------------------------ @@ -1258,6 +1100,78 @@ public class TTableWidget extends TWidget { alignGrid(); } + /** + * Get the highlight row flag. + * + * @return true if the selected row is highlighted + */ + public boolean getHighlightRow() { + return highlightRow; + } + + /** + * Set the highlight row flag. + * + * @param highlightRow if true, the selected row will be highlighted + */ + public void setHighlightRow(final boolean highlightRow) { + this.highlightRow = highlightRow; + } + + /** + * Get the highlight column flag. + * + * @return true if the selected column is highlighted + */ + public boolean getHighlightColumn() { + return highlightColumn; + } + + /** + * Set the highlight column flag. + * + * @param highlightColumn if true, the selected column will be highlighted + */ + public void setHighlightColumn(final boolean highlightColumn) { + this.highlightColumn = highlightColumn; + } + + /** + * Get the show row labels flag. + * + * @return true if row labels are shown + */ + public boolean getShowRowLabels() { + return showRowLabels; + } + + /** + * Set the show row labels flag. + * + * @param showRowLabels if true, the row labels will be shown + */ + public void setShowRowLabels(final boolean showRowLabels) { + this.showRowLabels = showRowLabels; + } + + /** + * Get the show column labels flag. + * + * @return true if column labels are shown + */ + public boolean getShowColumnLabels() { + return showColumnLabels; + } + + /** + * Set the show column labels flag. + * + * @param showColumnLabels if true, the column labels will be shown + */ + public void setShowColumnLabels(final boolean showColumnLabels) { + this.showColumnLabels = showColumnLabels; + } + /** * Get the number of columns. * @@ -1276,10 +1190,34 @@ public class TTableWidget extends TWidget { return rows.size(); } + + /** + * Push top and left to the bottom-most right corner of the available + * grid. + */ + private void bottomRightCorner() { + int viewColumns = getWidth(); + if (showRowLabels == true) { + viewColumns -= ROW_LABEL_WIDTH; + } + + // Set left and top such that the table stays on screen if possible. + top = rows.size() - getHeight(); + left = columns.size() - (getWidth() / (viewColumns / (COLUMN_DEFAULT_WIDTH + 1))); + // Now ensure the selection is visible. + alignGrid(); + } + /** * Align the grid so that the selected cell is fully visible. */ private void alignGrid() { + + /* + System.err.println("alignGrid() # columns " + columns.size() + + " # rows " + rows.size()); + */ + int viewColumns = getWidth(); if (showRowLabels == true) { viewColumns -= ROW_LABEL_WIDTH; @@ -1445,13 +1383,308 @@ public class TTableWidget extends TWidget { } /** - * Save contents to file. + * Load contents from file in CSV format. + * + * @param csvFile a File referencing the CSV data + * @throws IOException if a java.io operation throws + */ + public void loadCsvFile(final File csvFile) throws IOException { + BufferedReader reader = null; + + try { + reader = new BufferedReader(new FileReader(csvFile)); + + String line = null; + boolean first = true; + for (line = reader.readLine(); line != null; + line = reader.readLine()) { + + List list = StringUtils.fromCsv(line); + if (list.size() == 0) { + continue; + } + + if (list.size() > columns.size()) { + int n = list.size() - columns.size(); + for (int i = 0; i < n; i++) { + selectedColumn = columns.size() - 1; + insertColumnRight(selectedColumn); + } + } + assert (list.size() == columns.size()); + + if (first) { + // First row: just replace what is here. + selectedRow = 0; + first = false; + } else { + // All other rows: append to the end. + selectedRow = rows.size() - 1; + insertRowBelow(selectedRow); + selectedRow = rows.size() - 1; + } + for (int i = 0; i < list.size(); i++) { + rows.get(selectedRow).get(i).setText(list.get(i)); + } + } + } finally { + if (reader != null) { + reader.close(); + } + } + + left = 0; + top = 0; + selectedRow = 0; + selectedColumn = 0; + alignGrid(); + activate(columns.get(selectedColumn).get(selectedRow)); + } + + /** + * Save contents to file in CSV format. * * @param filename file to save to * @throws IOException if a java.io operation throws */ - public void saveToFilename(final String filename) throws IOException { - // TODO + public void saveToCsvFilename(final String filename) throws IOException { + BufferedWriter writer = null; + + try { + writer = new BufferedWriter(new FileWriter(filename)); + for (Row row: rows) { + List list = new ArrayList(row.cells.size()); + for (Cell cell: row.cells) { + list.add(cell.getText()); + } + writer.write(StringUtils.toCsv(list)); + writer.write("\n"); + } + } finally { + if (writer != null) { + writer.close(); + } + } + } + + /** + * Save contents to file in text format with lines. + * + * @param filename file to save to + * @throws IOException if a java.io operation throws + */ + public void saveToTextFilename(final String filename) throws IOException { + BufferedWriter writer = null; + + try { + writer = new BufferedWriter(new FileWriter(filename)); + + if ((topBorder == Border.SINGLE) && (leftBorder == Border.SINGLE)) { + // Emit top-left corner. + writer.write("\u250c"); + } + + if (topBorder == Border.SINGLE) { + int cellI = 0; + for (Cell cell: rows.get(0).cells) { + for (int i = 0; i < columns.get(cellI).width; i++) { + writer.write("\u2500"); + } + + if (columns.get(cellI).rightBorder == Border.SINGLE) { + if (cellI < columns.size() - 1) { + // Emit top tee. + writer.write("\u252c"); + } else { + // Emit top-right corner. + writer.write("\u2510"); + } + } + cellI++; + } + } + writer.write("\n"); + + int rowI = 0; + for (Row row: rows) { + + if (leftBorder == Border.SINGLE) { + // Emit left border. + writer.write("\u2502"); + } + + int cellI = 0; + for (Cell cell: row.cells) { + writer.write(String.format("%" + + columns.get(cellI).width + "s", cell.getText())); + + if (columns.get(cellI).rightBorder == Border.SINGLE) { + // Emit right border. + writer.write("\u2502"); + } + cellI++; + } + writer.write("\n"); + + if (row.bottomBorder == Border.NONE) { + // All done, move on to the next row. + continue; + } + + // Emit the bottom borders and intersections. + if ((leftBorder == Border.SINGLE) + && (row.bottomBorder != Border.NONE) + ) { + if (rowI < rows.size() - 1) { + if (row.bottomBorder == Border.SINGLE) { + // Emit left tee. + writer.write("\u251c"); + } else if (row.bottomBorder == Border.DOUBLE) { + // Emit left tee (double). + writer.write("\u255e"); + } else if (row.bottomBorder == Border.THICK) { + // Emit left tee (thick). + writer.write("\u251d"); + } + } + + if (rowI == rows.size() - 1) { + if (row.bottomBorder == Border.SINGLE) { + // Emit left bottom corner. + writer.write("\u2514"); + } else if (row.bottomBorder == Border.DOUBLE) { + // Emit left bottom corner (double). + writer.write("\u2558"); + } else if (row.bottomBorder == Border.THICK) { + // Emit left bottom corner (thick). + writer.write("\u2515"); + } + } + } + + cellI = 0; + for (Cell cell: row.cells) { + + for (int i = 0; i < columns.get(cellI).width; i++) { + if (row.bottomBorder == Border.SINGLE) { + writer.write("\u2500"); + } + if (row.bottomBorder == Border.DOUBLE) { + writer.write("\u2550"); + } + if (row.bottomBorder == Border.THICK) { + writer.write("\u2501"); + } + } + + if ((rowI < rows.size() - 1) + && (cellI == columns.size() - 1) + && (row.bottomBorder == Border.SINGLE) + && (columns.get(cellI).rightBorder == Border.SINGLE) + ) { + // Emit right tee. + writer.write("\u2524"); + } + if ((rowI < rows.size() - 1) + && (cellI == columns.size() - 1) + && (row.bottomBorder == Border.DOUBLE) + && (columns.get(cellI).rightBorder == Border.SINGLE) + ) { + // Emit right tee (double). + writer.write("\u2561"); + } + if ((rowI < rows.size() - 1) + && (cellI == columns.size() - 1) + && (row.bottomBorder == Border.THICK) + && (columns.get(cellI).rightBorder == Border.SINGLE) + ) { + // Emit right tee (thick). + writer.write("\u2525"); + } + if ((rowI == rows.size() - 1) + && (cellI == columns.size() - 1) + && (row.bottomBorder == Border.SINGLE) + && (columns.get(cellI).rightBorder == Border.SINGLE) + ) { + // Emit right bottom corner. + writer.write("\u2518"); + } + if ((rowI == rows.size() - 1) + && (cellI == columns.size() - 1) + && (row.bottomBorder == Border.DOUBLE) + && (columns.get(cellI).rightBorder == Border.SINGLE) + ) { + // Emit right bottom corner (double). + writer.write("\u255b"); + } + if ((rowI == rows.size() - 1) + && (cellI == columns.size() - 1) + && (row.bottomBorder == Border.THICK) + && (columns.get(cellI).rightBorder == Border.SINGLE) + ) { + // Emit right bottom corner (thick). + writer.write("\u2519"); + } + if ((rowI < rows.size() - 1) + && (cellI < columns.size() - 1) + && (row.bottomBorder == Border.SINGLE) + && (columns.get(cellI).rightBorder == Border.SINGLE) + ) { + // Emit intersection. + writer.write("\u253c"); + } + if ((rowI < rows.size() - 1) + && (cellI < columns.size() - 1) + && (row.bottomBorder == Border.DOUBLE) + && (columns.get(cellI).rightBorder == Border.SINGLE) + ) { + // Emit intersection (double). + writer.write("\u256a"); + } + if ((rowI < rows.size() - 1) + && (cellI < columns.size() - 1) + && (row.bottomBorder == Border.THICK) + && (columns.get(cellI).rightBorder == Border.SINGLE) + ) { + // Emit intersection (thick). + writer.write("\u253f"); + } + if ((rowI == rows.size() - 1) + && (cellI < columns.size() - 1) + && (row.bottomBorder == Border.SINGLE) + && (columns.get(cellI).rightBorder == Border.SINGLE) + ) { + // Emit bottom tee. + writer.write("\u2534"); + } + if ((rowI == rows.size() - 1) + && (cellI < columns.size() - 1) + && (row.bottomBorder == Border.DOUBLE) + && (columns.get(cellI).rightBorder == Border.SINGLE) + ) { + // Emit bottom tee (double). + writer.write("\u2567"); + } + if ((rowI == rows.size() - 1) + && (cellI < columns.size() - 1) + && (row.bottomBorder == Border.THICK) + && (columns.get(cellI).rightBorder == Border.SINGLE) + ) { + // Emit bottom tee (thick). + writer.write("\u2537"); + } + + cellI++; + } + + writer.write("\n"); + rowI++; + } + } finally { + if (writer != null) { + writer.close(); + } + } } /** @@ -1602,7 +1835,26 @@ public class TTableWidget extends TWidget { throw new IndexOutOfBoundsException("Column count is " + columns.size() + ", requested index " + column); } + + if (width < 4) { + // Columns may not be smaller than 4 cells wide. + return; + } + + int delta = width - columns.get(column).width; columns.get(column).width = width; + for (Cell cell: columns.get(column).cells) { + cell.setWidth(columns.get(column).width); + cell.field.setWidth(columns.get(column).width); + } + for (int i = column + 1; i < columns.size(); i++) { + columns.get(i).setX(columns.get(i).getX() + delta); + } + if (column == columns.size() - 1) { + bottomRightCorner(); + } else { + alignGrid(); + } } /** @@ -1670,7 +1922,7 @@ public class TTableWidget extends TWidget { Row newRow = new Row(idx); for (int i = 0; i < columns.size(); i++) { Cell cell = new Cell(this, columns.get(i).getX(), - rows.get(selectedRow).getY(), COLUMN_DEFAULT_WIDTH, 1, i, idx); + rows.get(idx).getY(), COLUMN_DEFAULT_WIDTH, 1, i, idx); newRow.add(cell); columns.get(i).cells.add(idx, cell); } @@ -1701,8 +1953,9 @@ public class TTableWidget extends TWidget { throw new IndexOutOfBoundsException("Row count is " + rows.size() + ", requested index " + row); } - insertRowAt(selectedRow); + insertRowAt(row); selectedRow++; + activate(columns.get(selectedColumn).get(selectedRow)); } /** @@ -1715,22 +1968,24 @@ public class TTableWidget extends TWidget { throw new IndexOutOfBoundsException("Row count is " + rows.size() + ", requested index " + row); } - int idx = selectedRow + 1; + int idx = row + 1; if (idx < rows.size()) { insertRowAt(idx); + activate(columns.get(selectedColumn).get(selectedRow)); return; } - // selectedRow is the last row, we need to perform an append. + // row is the last row, we need to perform an append. Row newRow = new Row(idx); for (int i = 0; i < columns.size(); i++) { Cell cell = new Cell(this, columns.get(i).getX(), - rows.get(selectedRow).getY(), COLUMN_DEFAULT_WIDTH, 1, i, idx); + rows.get(row).getY(), COLUMN_DEFAULT_WIDTH, 1, i, idx); newRow.add(cell); columns.get(i).cells.add(cell); } rows.add(newRow); alignGrid(); + activate(columns.get(selectedColumn).get(selectedRow)); } /** @@ -1743,7 +1998,33 @@ public class TTableWidget extends TWidget { throw new IndexOutOfBoundsException("Row count is " + rows.size() + ", requested index " + row); } - // TODO + if (rows.size() == 1) { + // Don't delete the last row. + return; + } + for (int i = 0; i < columns.size(); i++) { + Cell cell = columns.get(i).cells.remove(row); + getChildren().remove(cell); + } + rows.remove(row); + + for (int x = 0; x < columns.size(); x++) { + for (int y = row; y < rows.size(); y++) { + columns.get(x).get(y).row = y; + columns.get(x).get(y).column = x; + } + } + for (int i = row; i < rows.size(); i++) { + String oldRowLabel = Integer.toString(i + 1); + if (rows.get(i).label.equals(oldRowLabel)) { + rows.get(i).label = Integer.toString(i); + } + } + if (selectedRow == rows.size()) { + selectedRow--; + } + activate(columns.get(selectedColumn).get(selectedRow)); + bottomRightCorner(); } /** @@ -1754,7 +2035,7 @@ public class TTableWidget extends TWidget { private void insertColumnAt(final int idx) { Column newColumn = new Column(idx); for (int i = 0; i < rows.size(); i++) { - Cell cell = new Cell(this, columns.get(selectedColumn).getX(), + Cell cell = new Cell(this, columns.get(idx).getX(), rows.get(i).getY(), COLUMN_DEFAULT_WIDTH, 1, idx, i); newColumn.add(cell); rows.get(i).cells.add(idx, cell); @@ -1786,8 +2067,9 @@ public class TTableWidget extends TWidget { throw new IndexOutOfBoundsException("Column count is " + columns.size() + ", requested index " + column); } - insertColumnAt(selectedColumn); + insertColumnAt(column); selectedColumn++; + activate(columns.get(selectedColumn).get(selectedRow)); } /** @@ -1800,22 +2082,24 @@ public class TTableWidget extends TWidget { throw new IndexOutOfBoundsException("Column count is " + columns.size() + ", requested index " + column); } - int idx = selectedColumn + 1; + int idx = column + 1; if (idx < columns.size()) { insertColumnAt(idx); + activate(columns.get(selectedColumn).get(selectedRow)); return; } - // selectedColumn is the last column, we need to perform an append. + // column is the last column, we need to perform an append. Column newColumn = new Column(idx); for (int i = 0; i < rows.size(); i++) { - Cell cell = new Cell(this, columns.get(selectedColumn).getX(), + Cell cell = new Cell(this, columns.get(column).getX(), rows.get(i).getY(), COLUMN_DEFAULT_WIDTH, 1, idx, i); newColumn.add(cell); rows.get(i).cells.add(cell); } columns.add(newColumn); alignGrid(); + activate(columns.get(selectedColumn).get(selectedRow)); } /** @@ -1828,21 +2112,55 @@ public class TTableWidget extends TWidget { throw new IndexOutOfBoundsException("Column count is " + columns.size() + ", requested index " + column); } - // TODO + if (columns.size() == 1) { + // Don't delete the last column. + return; + } + for (int i = 0; i < rows.size(); i++) { + Cell cell = rows.get(i).cells.remove(column); + getChildren().remove(cell); + } + columns.remove(column); + + for (int x = column; x < columns.size(); x++) { + for (int y = 0; y < rows.size(); y++) { + columns.get(x).get(y).row = y; + columns.get(x).get(y).column = x; + } + } + for (int i = column; i < columns.size(); i++) { + String oldColumnLabel = makeColumnLabel(i + 1); + if (columns.get(i).label.equals(oldColumnLabel)) { + columns.get(i).label = makeColumnLabel(i); + } + } + if (selectedColumn == columns.size()) { + selectedColumn--; + } + activate(columns.get(selectedColumn).get(selectedRow)); + bottomRightCorner(); } /** * Delete the selected cell, shifting cells over to the left. */ public void deleteCellShiftLeft() { - // TODO + // All we do is copy the text from every cell in this row over. + for (int i = selectedColumn + 1; i < columns.size(); i++) { + setCellText(i - 1, selectedRow, getCellText(i, selectedRow)); + } + setCellText(columns.size() - 1, selectedRow, ""); } /** * Delete the selected cell, shifting cells from below up. */ public void deleteCellShiftUp() { - // TODO + // All we do is copy the text from every cell in this column up. + for (int i = selectedRow + 1; i < rows.size(); i++) { + setCellText(selectedColumn, i - 1, getCellText(selectedColumn, i)); + } + setCellText(selectedColumn, rows.size() - 1, ""); } /** @@ -1898,4 +2216,144 @@ public class TTableWidget extends TWidget { } } + /** + * Set all borders across the entire table to Border.NONE. + */ + public void setBorderAllNone() { + topBorder = Border.NONE; + leftBorder = Border.NONE; + for (int i = 0; i < columns.size(); i++) { + columns.get(i).rightBorder = Border.NONE; + } + for (int i = 0; i < rows.size(); i++) { + rows.get(i).bottomBorder = Border.NONE; + rows.get(i).height = 1; + } + bottomRightCorner(); + } + + /** + * Set all borders across the entire table to Border.SINGLE. + */ + public void setBorderAllSingle() { + topBorder = Border.SINGLE; + leftBorder = Border.SINGLE; + for (int i = 0; i < columns.size(); i++) { + columns.get(i).rightBorder = Border.SINGLE; + } + for (int i = 0; i < rows.size(); i++) { + rows.get(i).bottomBorder = Border.SINGLE; + rows.get(i).height = 2; + } + alignGrid(); + } + + /** + * Set all borders around the selected cell to Border.NONE. + */ + public void setBorderCellNone() { + if (selectedRow == 0) { + topBorder = Border.NONE; + } + if (selectedColumn == 0) { + leftBorder = Border.NONE; + } + if (selectedColumn > 0) { + columns.get(selectedColumn - 1).rightBorder = Border.NONE; + } + columns.get(selectedColumn).rightBorder = Border.NONE; + if (selectedRow > 0) { + rows.get(selectedRow - 1).bottomBorder = Border.NONE; + rows.get(selectedRow - 1).height = 1; + } + rows.get(selectedRow).bottomBorder = Border.NONE; + rows.get(selectedRow).height = 1; + bottomRightCorner(); + } + + /** + * Set all borders around the selected cell to Border.SINGLE. + */ + public void setBorderCellSingle() { + if (selectedRow == 0) { + topBorder = Border.SINGLE; + } + if (selectedColumn == 0) { + leftBorder = Border.SINGLE; + } + if (selectedColumn > 0) { + columns.get(selectedColumn - 1).rightBorder = Border.SINGLE; + } + columns.get(selectedColumn).rightBorder = Border.SINGLE; + if (selectedRow > 0) { + rows.get(selectedRow - 1).bottomBorder = Border.SINGLE; + rows.get(selectedRow - 1).height = 2; + } + rows.get(selectedRow).bottomBorder = Border.SINGLE; + rows.get(selectedRow).height = 2; + alignGrid(); + } + + /** + * Set the column border to the right of the selected cell to + * Border.SINGLE. + */ + public void setBorderColumnRightSingle() { + columns.get(selectedColumn).rightBorder = Border.SINGLE; + alignGrid(); + } + + /** + * Set the column border to the right of the selected cell to + * Border.SINGLE. + */ + public void setBorderColumnLeftSingle() { + if (selectedColumn == 0) { + leftBorder = Border.SINGLE; + } else { + columns.get(selectedColumn - 1).rightBorder = Border.SINGLE; + } + alignGrid(); + } + + /** + * Set the row border above the selected cell to Border.SINGLE. + */ + public void setBorderRowAboveSingle() { + if (selectedRow == 0) { + topBorder = Border.SINGLE; + } else { + rows.get(selectedRow - 1).bottomBorder = Border.SINGLE; + rows.get(selectedRow - 1).height = 2; + } + alignGrid(); + } + + /** + * Set the row border below the selected cell to Border.SINGLE. + */ + public void setBorderRowBelowSingle() { + rows.get(selectedRow).bottomBorder = Border.SINGLE; + rows.get(selectedRow).height = 2; + alignGrid(); + } + + /** + * Set the row border below the selected cell to Border.DOUBLE. + */ + public void setBorderRowBelowDouble() { + rows.get(selectedRow).bottomBorder = Border.DOUBLE; + rows.get(selectedRow).height = 2; + alignGrid(); + } + + /** + * Set the row border below the selected cell to Border.THICK. + */ + public void setBorderRowBelowThick() { + rows.get(selectedRow).bottomBorder = Border.THICK; + rows.get(selectedRow).height = 2; + alignGrid(); + } + }