From 759cb83ebad2f861e50f39dab34f70eaafe6d6ed Mon Sep 17 00:00:00 2001 From: Kevin Lamonte Date: Sun, 28 Jul 2019 15:33:08 -0500 Subject: [PATCH] ttable scrollbars and mouse working --- src/jexer/TTableWidget.java | 226 ++++++++++++++++++++++++++++-- src/jexer/TTableWindow.java | 138 ++++++++++-------- src/jexer/TTableWindow.properties | 7 + 3 files changed, 303 insertions(+), 68 deletions(-) diff --git a/src/jexer/TTableWidget.java b/src/jexer/TTableWidget.java index bd53977..2e10a3f 100644 --- a/src/jexer/TTableWidget.java +++ b/src/jexer/TTableWidget.java @@ -28,12 +28,14 @@ */ package jexer; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import jexer.bits.CellAttributes; import jexer.event.TKeypressEvent; import jexer.event.TMenuEvent; +import jexer.event.TMouseEvent; import jexer.event.TResizeEvent; import jexer.menu.TMenu; import static jexer.TKeypress.*; @@ -318,6 +320,66 @@ public class TTableWidget extends TWidget { // Event handlers ----------------------------------------------------- // -------------------------------------------------------------------- + /** + * Handle mouse double-click events. + * + * @param mouse mouse double-click event + */ + @Override + public void onMouseDoubleClick(final TMouseEvent mouse) { + // Use TWidget's code to pass the event to the children. + super.onMouseDown(mouse); + + // Double-click means to start editing. + fieldText = field.getText(); + isEditing = true; + field.setEnabled(true); + activate(field); + + if (isActive()) { + // Let the table know that I was activated. + ((TTableWidget) getParent()).selectedRow = row; + ((TTableWidget) getParent()).selectedColumn = column; + ((TTableWidget) getParent()).alignGrid(); + } + } + + /** + * Handle mouse press events. + * + * @param mouse mouse button press event + */ + @Override + public void onMouseDown(final TMouseEvent mouse) { + // Use TWidget's code to pass the event to the children. + super.onMouseDown(mouse); + + if (isActive()) { + // Let the table know that I was activated. + ((TTableWidget) getParent()).selectedRow = row; + ((TTableWidget) getParent()).selectedColumn = column; + ((TTableWidget) getParent()).alignGrid(); + } + } + + /** + * Handle mouse release events. + * + * @param mouse mouse button release event + */ + @Override + public void onMouseUp(final TMouseEvent mouse) { + // Use TWidget's code to pass the event to the children. + super.onMouseDown(mouse); + + if (isActive()) { + // Let the table know that I was activated. + ((TTableWidget) getParent()).selectedRow = row; + ((TTableWidget) getParent()).selectedColumn = column; + ((TTableWidget) getParent()).alignGrid(); + } + } + /** * Handle keystrokes. * @@ -482,6 +544,31 @@ public class TTableWidget extends TWidget { // Event handlers --------------------------------------------------------- // ------------------------------------------------------------------------ + /** + * Handle mouse press events. + * + * @param mouse mouse button press event + */ + @Override + public void onMouseDown(final TMouseEvent mouse) { + if (mouse.isMouseWheelUp() || mouse.isMouseWheelDown()) { + // Treat wheel up/down as 3 up/down + TKeypressEvent keyEvent; + if (mouse.isMouseWheelUp()) { + keyEvent = new TKeypressEvent(kbUp); + } else { + keyEvent = new TKeypressEvent(kbDown); + } + for (int i = 0; i < 3; i++) { + onKeypress(keyEvent); + } + return; + } + + // Use TWidget's code to pass the event to the children. + super.onMouseDown(mouse); + } + /** * Handle keystrokes. * @@ -504,39 +591,65 @@ public class TTableWidget extends TWidget { } if (keypress.equals(kbLeft)) { + // Left if (selectedColumn > 0) { selectedColumn--; } activate(columns.get(selectedColumn).get(selectedRow)); } else if (keypress.equals(kbRight)) { + // Right if (selectedColumn < columns.size() - 1) { selectedColumn++; } activate(columns.get(selectedColumn).get(selectedRow)); } else if (keypress.equals(kbUp)) { + // Up if (selectedRow > 0) { selectedRow--; } activate(columns.get(selectedColumn).get(selectedRow)); } else if (keypress.equals(kbDown)) { + // Down if (selectedRow < rows.size() - 1) { selectedRow++; } activate(columns.get(selectedColumn).get(selectedRow)); } else if (keypress.equals(kbHome)) { + // Home - leftmost column selectedColumn = 0; activate(columns.get(selectedColumn).get(selectedRow)); } else if (keypress.equals(kbEnd)) { + // End - rightmost column selectedColumn = columns.size() - 1; activate(columns.get(selectedColumn).get(selectedRow)); } else if (keypress.equals(kbPgUp)) { - // TODO + // PgUp - Treat like multiple up + for (int i = 0; i < getHeight() - 2; i++) { + if (selectedRow > 0) { + selectedRow--; + } + } + activate(columns.get(selectedColumn).get(selectedRow)); } else if (keypress.equals(kbPgDn)) { - // TODO + // PgDn - Treat like multiple up + for (int i = 0; i < getHeight() - 2; i++) { + if (selectedRow < rows.size() - 1) { + selectedRow++; + } + } + activate(columns.get(selectedColumn).get(selectedRow)); } else if (keypress.equals(kbCtrlHome)) { - // TODO + // Ctrl-Home - go to top-left + selectedRow = 0; + selectedColumn = 0; + activate(columns.get(selectedColumn).get(selectedRow)); + activate(columns.get(selectedColumn).get(selectedRow)); } else if (keypress.equals(kbCtrlEnd)) { - // TODO + // Ctrl-End - go to bottom-right + selectedRow = rows.size() - 1; + selectedColumn = columns.size() - 1; + activate(columns.get(selectedColumn).get(selectedRow)); + activate(columns.get(selectedColumn).get(selectedRow)); } else { // Pass to the Cell. super.onKeypress(keypress); @@ -600,7 +713,7 @@ public class TTableWidget extends TWidget { columns.get(selectedColumn).width--; for (Cell cell: getSelectedColumn().cells) { cell.setWidth(columns.get(selectedColumn).width); - cell.field.setWidth(columns.get(selectedColumn).width - 1); + cell.field.setWidth(columns.get(selectedColumn).width); } for (int i = selectedColumn + 1; i < columns.size(); i++) { for (Cell cell: columns.get(i).cells) { @@ -613,7 +726,7 @@ public class TTableWidget extends TWidget { columns.get(selectedColumn).width++; for (Cell cell: getSelectedColumn().cells) { cell.setWidth(columns.get(selectedColumn).width); - cell.field.setWidth(columns.get(selectedColumn).width - 1); + cell.field.setWidth(columns.get(selectedColumn).width); } for (int i = selectedColumn + 1; i < columns.size(); i++) { for (Cell cell: columns.get(i).cells) { @@ -623,7 +736,10 @@ public class TTableWidget extends TWidget { alignGrid(); break; case TMenu.MID_TABLE_FILE_SAVE_CSV: + // TODO + break; case TMenu.MID_TABLE_FILE_SAVE_TEXT: + // TODO break; default: super.onMenu(menu); @@ -652,7 +768,9 @@ public class TTableWidget extends TWidget { break; } putStringXY(columns.get(i).get(top).getX(), 0, - String.format(" %-6s ", columns.get(i).label), + String.format(" %-" + + (columns.get(i).get(top).getWidth() - 2) + + "s ", columns.get(i).label), (i == selectedColumn ? labelColorSelected : labelColor)); } } @@ -717,12 +835,78 @@ public class TTableWidget extends TWidget { return rows.get(selectedRow); } + /** + * Get the currently-selected column number. 0 is the left-most column. + * + * @return the selected column number + */ + public int getSelectedColumnNumber() { + return selectedColumn; + } + + /** + * Set the currently-selected column number. 0 is the left-most column. + * + * @param column the column number to select + */ + public void setSelectedColumnNumber(final int column) { + if ((column < 0) || (column > columns.size() - 1)) { + throw new IndexOutOfBoundsException("Column count is " + + columns.size() + ", requested index " + column); + } + selectedColumn = column; + activate(columns.get(selectedColumn).get(selectedRow)); + alignGrid(); + } + + /** + * Get the currently-selected row number. 0 is the top-most row. + * + * @return the selected row number + */ + public int getSelectedRowNumber() { + return selectedRow; + } + + /** + * Set the currently-selected row number. 0 is the left-most column. + * + * @param row the row number to select + */ + public void setSelectedRowNumber(final int row) { + if ((row < 0) || (row > rows.size() - 1)) { + throw new IndexOutOfBoundsException("Row count is " + + rows.size() + ", requested index " + row); + } + selectedRow = row; + activate(columns.get(selectedColumn).get(selectedRow)); + alignGrid(); + } + + /** + * Get the number of columns. + * + * @return the number of columns + */ + public int getColumnCount() { + return columns.size(); + } + + /** + * Get the number of rows. + * + * @return the number of rows + */ + public int getRowCount() { + return rows.size(); + } + /** * Get the full horizontal width of this table. * * @return the width required to render the entire table */ - public int getMaximumWidth() { + private int getMaximumWidth() { int totalWidth = 0; if (showRowLabels == true) { // For now, all row labels are 8 cells wide. TODO: make this @@ -740,7 +924,7 @@ public class TTableWidget extends TWidget { * * @return the height required to render the entire table */ - public int getMaximumHeight() { + private int getMaximumHeight() { int totalHeight = 0; if (showColumnLabels == true) { // For now, all column labels are 1 cell tall. TODO: make this @@ -765,7 +949,17 @@ public class TTableWidget extends TWidget { */ for (int x = 0; x < columns.size(); x++) { for (int y = 0; y < rows.size(); y++) { - rows.get(y).cells.get(x).setVisible(true); + Cell cell = rows.get(y).cells.get(x); + cell.setVisible(true); + + // Special case: mouse double-clicks can lead to multiple + // cells in editing mode. Only allow a cell to remain + // editing if it is fact the active widget. + if (cell.isEditing && !cell.isActive()) { + cell.fieldText = cell.field.getText(); + cell.isEditing = false; + cell.field.setEnabled(false); + } } } @@ -817,7 +1011,7 @@ public class TTableWidget extends TWidget { left = selectedColumn; for (int x = selectedColumn - 1; x >= 0; x--) { newCellX -= rows.get(y).cells.get(x).getWidth() + 1; - if (newCellX - rows.get(y).cells.get(x).getWidth() + 1 >= 0) { + if (newCellX >= (showRowLabels ? 8 : 0)) { rows.get(y).cells.get(x).setVisible(true); rows.get(y).cells.get(x).setX(newCellX); left--; @@ -934,4 +1128,14 @@ public class TTableWidget extends TWidget { } + /** + * Save contents to file. + * + * @param filename file to save to + * @throws IOException if a java.io operation throws + */ + public void saveToFilename(final String filename) throws IOException { + // TODO + } + } diff --git a/src/jexer/TTableWindow.java b/src/jexer/TTableWindow.java index 33b8116..47a5b9e 100644 --- a/src/jexer/TTableWindow.java +++ b/src/jexer/TTableWindow.java @@ -28,6 +28,8 @@ */ package jexer; +import java.io.IOException; +import java.text.MessageFormat; import java.util.ResourceBundle; import jexer.event.TCommandEvent; @@ -151,18 +153,6 @@ public class TTableWindow extends TScrollableWindow { // TWindow ---------------------------------------------------------------- // ------------------------------------------------------------------------ - /** - * Draw the window. - */ - @Override - public void draw() { - // Draw as normal. - super.draw(); - - // Add borders on rows and columns. - // TODO - } - /** * Handle mouse press events. * @@ -175,19 +165,10 @@ public class TTableWindow extends TScrollableWindow { if (mouseOnTable(mouse)) { // The table might have changed, update the scollbars. - // TODO - /* - setBottomValue(editField.getMaximumRowNumber()); - setVerticalValue(editField.getVisibleRowNumber()); - setRightValue(editField.getMaximumColumnNumber()); - setHorizontalValue(editField.getEditingColumnNumber()); - */ - } else { - if (mouse.isMouseWheelUp() || mouse.isMouseWheelDown()) { - // Vertical scrollbar actions - // TODO - // editField.setVisibleRowNumber(getVerticalValue()); - } + setBottomValue(tableField.getRowCount() - 1); + setVerticalValue(tableField.getSelectedRowNumber()); + setRightValue(tableField.getColumnCount() - 1); + setHorizontalValue(tableField.getSelectedColumnNumber()); } } @@ -202,12 +183,13 @@ public class TTableWindow extends TScrollableWindow { super.onMouseUp(mouse); if (mouse.isMouse1() && mouseOnVerticalScroller(mouse)) { - // Clicked on vertical scrollbar - // TODO - // editField.setVisibleRowNumber(getVerticalValue()); + // Clicked/dragged on vertical scrollbar. + tableField.setSelectedRowNumber(getVerticalValue()); + } + if (mouse.isMouse1() && mouseOnHorizontalScroller(mouse)) { + // Clicked/dragged on horizontal scrollbar. + tableField.setSelectedColumnNumber(getHorizontalValue()); } - - // TODO: horizontal scrolling } /** @@ -221,22 +203,20 @@ public class TTableWindow extends TScrollableWindow { super.onMouseMotion(mouse); if (mouseOnTable(mouse) && mouse.isMouse1()) { - // The editor might have changed, update the scollbars. - // TODO - /* - setBottomValue(editField.getMaximumRowNumber()); - setVerticalValue(editField.getVisibleRowNumber()); - setRightValue(editField.getMaximumColumnNumber()); - setHorizontalValue(editField.getEditingColumnNumber()); - */ + // The table might have changed, update the scollbars. + setBottomValue(tableField.getRowCount() - 1); + setVerticalValue(tableField.getSelectedRowNumber()); + setRightValue(tableField.getColumnCount() - 1); + setHorizontalValue(tableField.getSelectedColumnNumber()); } else { if (mouse.isMouse1() && mouseOnVerticalScroller(mouse)) { - // Clicked/dragged on vertical scrollbar - // TODO - // editField.setVisibleRowNumber(getVerticalValue()); + // Clicked/dragged on vertical scrollbar. + tableField.setSelectedRowNumber(getVerticalValue()); + } + if (mouse.isMouse1() && mouseOnHorizontalScroller(mouse)) { + // Clicked/dragged on horizontal scrollbar. + tableField.setSelectedColumnNumber(getHorizontalValue()); } - - // TODO: horizontal scrolling } } @@ -251,14 +231,11 @@ public class TTableWindow extends TScrollableWindow { // Use TWidget's code to pass the event to the children. super.onKeypress(keypress); - // The editor might have changed, update the scollbars. - // TODO - /* - setBottomValue(editField.getMaximumRowNumber()); - setVerticalValue(editField.getVisibleRowNumber()); - setRightValue(editField.getMaximumColumnNumber()); - setHorizontalValue(editField.getEditingColumnNumber()); - */ + // The table might have changed, update the scollbars. + setBottomValue(tableField.getRowCount() - 1); + setVerticalValue(tableField.getSelectedRowNumber()); + setRightValue(tableField.getColumnCount() - 1); + setHorizontalValue(tableField.getSelectedColumnNumber()); } /** @@ -285,6 +262,54 @@ public class TTableWindow extends TScrollableWindow { } } + /** + * Method that subclasses can override to handle posted command events. + * + * @param command command event + */ + @Override + public void onCommand(final TCommandEvent command) { + if (command.equals(cmOpen)) { + try { + String filename = fileOpenBox("."); + if (filename != null) { + try { + // TODO + if (false) { + tableField.saveToFilename(filename); + } + } catch (IOException e) { + messageBox(i18n.getString("errorDialogTitle"), + MessageFormat.format(i18n. + getString("errorReadingFile"), e.getMessage())); + } + } + } catch (IOException e) { + messageBox(i18n.getString("errorDialogTitle"), + MessageFormat.format(i18n. + getString("errorOpeningFileDialog"), e.getMessage())); + } + return; + } + + if (command.equals(cmSave)) { + try { + String filename = fileSaveBox("."); + if (filename != null) { + tableField.saveToFilename(filename); + } + } catch (IOException e) { + messageBox(i18n.getString("errorDialogTitle"), + MessageFormat.format(i18n. + getString("errorSavingFile"), e.getMessage())); + } + return; + } + + // Didn't handle it, let children get it instead + super.onCommand(command); + } + // ------------------------------------------------------------------------ // TTableWindow ----------------------------------------------------------- // ------------------------------------------------------------------------ @@ -297,20 +322,19 @@ public class TTableWindow extends TScrollableWindow { vScroller = new TVScroller(this, getWidth() - 2, 0, getHeight() - 2); setMinimumWindowWidth(25); setMinimumWindowHeight(10); - setTopValue(1); - // setBottomValue(editField.getMaximumRowNumber()); - setLeftValue(1); - setRightValue(tableField.getMaximumWidth()); + setTopValue(tableField.getSelectedRowNumber()); + setBottomValue(tableField.getRowCount() - 1); + setLeftValue(tableField.getSelectedColumnNumber()); + setRightValue(tableField.getColumnCount() - 1); statusBar = newStatusBar(i18n.getString("statusBar")); statusBar.addShortcutKeypress(kbF1, cmHelp, i18n.getString("statusBarHelp")); - /* + statusBar.addShortcutKeypress(kbF2, cmSave, i18n.getString("statusBarSave")); statusBar.addShortcutKeypress(kbF3, cmOpen, i18n.getString("statusBarOpen")); - */ statusBar.addShortcutKeypress(kbF10, cmMenu, i18n.getString("statusBarMenu")); } diff --git a/src/jexer/TTableWindow.properties b/src/jexer/TTableWindow.properties index a93ecdd..152641d 100644 --- a/src/jexer/TTableWindow.properties +++ b/src/jexer/TTableWindow.properties @@ -1,3 +1,10 @@ statusBar=Editor statusBarHelp=Help +statusBarSave=Save +statusBarOpen=Open statusBarMenu=Menu + +errorDialogTitle=Error +errorReadingFile=Error reading file: {0} +errorOpeningFileDialog=Error opening file dialog: {0} +errorSavingFile=Error saving file: {0} -- 2.27.0