diff --git a/notes.md b/notes.md index 25331f7b..b2556e44 100644 --- a/notes.md +++ b/notes.md @@ -1,3 +1,4 @@ +* Drill down for complex results (with double click or popup menu) * Rework kdb connection logic * No IPC protocol downgrade in case of first attempt failure * Fix logic to detect server disconnect diff --git a/src/studio/ui/QGrid.java b/src/studio/ui/QGrid.java index 06910dcb..c8e11d3a 100755 --- a/src/studio/ui/QGrid.java +++ b/src/studio/ui/QGrid.java @@ -5,6 +5,7 @@ import org.fife.ui.rtextarea.SearchContext; import studio.kdb.*; import studio.ui.action.CopyTableSelectionAction; +import studio.ui.action.TableUserAction; import studio.ui.search.*; import javax.swing.*; @@ -46,6 +47,7 @@ public int getRowCount() { private final JPopupMenu popupMenu = new JPopupMenu(); private final UserAction copyExcelFormatAction; private final UserAction copyHtmlFormatAction; + private final UserAction showSeparateAction; private long doubleClickTimeout; @@ -180,6 +182,9 @@ public void stateChanged(ChangeEvent ev) { KeyEvent.VK_H, null, new CopyTableSelectionAction(CopyTableSelectionAction.Format.Html, table)); + showSeparateAction = new TableUserAction.ShowSeparateAction(studioWindow, table); + + popupMenu.add(showSeparateAction); popupMenu.add(new JMenuItem(copyExcelFormatAction)); popupMenu.add(new JMenuItem(copyHtmlFormatAction)); @@ -230,10 +235,19 @@ private void copy(int row, int col) { if (row == -1 || col == -1) return; K.KBase b = (K.KBase) table.getValueAt(row, col); - //@TODO: we shouldn't duplicate the logic here. - KFormatContext formatContextForCell = new KFormatContext(formatContext); - formatContextForCell.setShowType(b instanceof K.KBaseVector); - Util.copyTextToClipboard(b.toString(formatContextForCell)); + + int type = b.getType(); + if ( (type >= -19 && type <= -1) || + (type >= 101 && type <= 103 ) || + type == 10 ) { + + //@TODO: we shouldn't duplicate the logic here. + KFormatContext formatContextForCell = new KFormatContext(formatContext); + formatContextForCell.setShowType(b instanceof K.KBaseVector); + Util.copyTextToClipboard(b.toString(formatContextForCell)); + } else { + showSeparateAction.actionPerformed(null); + } } }); @@ -316,25 +330,45 @@ private JPopupMenu getPopupMenu(Point point) { int col = table.columnAtPoint(point); if (row == -1 || col == -1) return popupMenu; - row = table.convertRowIndexToModel(row); - col = table.convertColumnIndexToModel(col); + int rowModel = table.convertRowIndexToModel(row); + int colModel = table.convertColumnIndexToModel(col); + + String[] connections = Config.getInstance().getTableConnExtractor().getConnections(table.getModel(), rowModel, colModel); - String[] connections = Config.getInstance().getTableConnExtractor().getConnections(table.getModel(), row, col); - if (connections.length == 0) return popupMenu; + JPopupMenu newPopupMenu; + + if (connections.length == 0) newPopupMenu = popupMenu; + else { + newPopupMenu = new JPopupMenu(); + for (String connection : connections) { + Server server = Config.getInstance().getServerByConnectionString(connection); + String name = server.getName().length() == 0 ? connection : server.getName(); + Action action = UserAction.create("Open " + connection, + "Open " + name + " in a new tab", 0, + e -> studioWindow.addTab(server, null)); + newPopupMenu.add(action); + } + newPopupMenu.add(new JSeparator()); - JPopupMenu popupMenu = new JPopupMenu(); - for (String connection: connections) { - Server server = Config.getInstance().getServerByConnectionString(connection); - String name = server.getName().length() == 0 ? connection : server.getName(); - Action action = UserAction.create("Open " + connection, - "Open " + name + " in a new tab", 0, - e -> studioWindow.addTab(server, null) ); - popupMenu.add(action); + for (Component component: popupMenu.getComponents()) { + if (component instanceof JSeparator) newPopupMenu.addSeparator(); + if (component instanceof JMenuItem) { + Action action = ((JMenuItem) component).getAction(); + if (action != null) newPopupMenu.add(action); + } + } } - popupMenu.add(new JSeparator()); - popupMenu.add(copyExcelFormatAction); - popupMenu.add(copyHtmlFormatAction); - return popupMenu; + + for (Component component: popupMenu.getComponents()) { + if (component instanceof JMenuItem) { + Action action = ((JMenuItem) component).getAction(); + if (action instanceof TableUserAction) { + ((TableUserAction)action).setLocation(row, col); + } + } + } + + return newPopupMenu; } private boolean isSearchContinue(SearchContext context) { diff --git a/src/studio/ui/TabPanel.java b/src/studio/ui/TabPanel.java index c642cc36..71e51c0f 100755 --- a/src/studio/ui/TabPanel.java +++ b/src/studio/ui/TabPanel.java @@ -1,5 +1,7 @@ package studio.ui; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import studio.kdb.ListModel; import studio.kdb.*; import studio.ui.action.QueryResult; @@ -26,6 +28,8 @@ public class TabPanel extends JPanel { private ResultType type; private boolean pinned = false; + private final static Logger log = LogManager.getLogger(); + public TabPanel(StudioWindow studioWindow, QueryResult queryResult) { this.studioWindow = studioWindow; this.queryResult = queryResult; diff --git a/src/studio/ui/action/ConnectionStats.java b/src/studio/ui/action/ConnectionStats.java index 76735efd..296dce42 100644 --- a/src/studio/ui/action/ConnectionStats.java +++ b/src/studio/ui/action/ConnectionStats.java @@ -1,7 +1,6 @@ package studio.ui.action; import kx.KConnectionStats; -import kx.KMessage; import studio.kdb.K; import studio.kdb.Session; import studio.ui.StudioWindow; @@ -12,9 +11,7 @@ public class ConnectionStats { public static void getStats(StudioWindow studioWindow) { - QueryResult queryResult = new QueryResult(null, ""); - queryResult.setResult(new KMessage(getTable())); - studioWindow.addResultTab(queryResult, "Connection statistics"); + studioWindow.addResultTab(new QueryResult(getTable()), "Connection statistics"); } private static K.Flip getTable() { diff --git a/src/studio/ui/action/QueryResult.java b/src/studio/ui/action/QueryResult.java index 593b75f6..ff2c24d4 100644 --- a/src/studio/ui/action/QueryResult.java +++ b/src/studio/ui/action/QueryResult.java @@ -13,6 +13,11 @@ public class QueryResult { private Throwable error = null; private boolean complete = false; + public QueryResult(K.KBase kObject) { + this(null, ""); + setResult(new KMessage(kObject)); + } + public QueryResult(Server server, String query) { this.server = server; this.query = query; diff --git a/src/studio/ui/action/TableUserAction.java b/src/studio/ui/action/TableUserAction.java new file mode 100644 index 00000000..12d95c20 --- /dev/null +++ b/src/studio/ui/action/TableUserAction.java @@ -0,0 +1,49 @@ +package studio.ui.action; + +import studio.kdb.K; +import studio.ui.StudioWindow; +import studio.ui.UserAction; +import studio.ui.Util; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; + +public abstract class TableUserAction extends UserAction { + + protected int col = -1; + protected int row = -1; + + public TableUserAction(String text, Icon icon, String desc, Integer mnemonic, KeyStroke key) { + super(text, icon, desc, mnemonic, key); + } + + public void setLocation(int row, int col) { + this.row = row; + this.col = col; + } + + public static class ShowSeparateAction extends TableUserAction { + + private final StudioWindow studioWindow; + private final JTable table; + + public ShowSeparateAction(StudioWindow studioWindow, JTable table) { + super("To separate tab", Util.BLANK_ICON, "Show in a separate tab", + KeyEvent.VK_S, null); + this.studioWindow = studioWindow; + this.table = table; + } + @Override + public void actionPerformed(ActionEvent e) { + int aRow = row; + int aCol = col; + if (aRow == -1 || aCol == -1) { + aRow = table.getSelectedRow(); + aCol = table.getSelectedColumn(); + } + if (aRow == -1 || aCol == -1) return; + studioWindow.addResultTab(new QueryResult((K.KBase)table.getValueAt(aRow, aCol)), "an element from previous result"); + } + } +}