diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index 49b40f376cee..1816acca4b38 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -990,7 +990,7 @@ action.Debugger.AddToWatch.text=Add to Watches action.Debugger.EvaluateInConsole.text=Evaluate in Console action.Debugger.UnmuteOnStop.text=Unmute breakpoints on session finish action.Debugger.AutoRenderer.text=Auto -action.PyDebugger.ViewArray.text = View as array +action.PyDebugger.ViewArray.text = View as Array group.EditorPopupMenu.text=Editor Popup Menu group.EditorPopupMenu.description=Editor Popup Menu action.Add\ to\ migration\ roots.text=_Add to migration roots diff --git a/python/src/com/jetbrains/python/debugger/array/NumpyArraySlice.java b/python/src/com/jetbrains/python/debugger/array/NumpyArraySlice.java index 3ff8a1ef40d1..5158f74f59bc 100644 --- a/python/src/com/jetbrains/python/debugger/array/NumpyArraySlice.java +++ b/python/src/com/jetbrains/python/debugger/array/NumpyArraySlice.java @@ -17,7 +17,7 @@ import java.util.List; * @author amarch */ -class NumpyArraySlice extends ComparableArrayChunk { +public class NumpyArraySlice extends ComparableArrayChunk { private NumpyArrayValueProvider myValueProvider; private DataEvaluator myDataEvaluator; private String myFormat; @@ -54,7 +54,7 @@ class NumpyArraySlice extends ComparableArrayChunk { } @Override - void fillData(Runnable callback) { + public void fillData(Runnable callback) { myDataEvaluator.evaluateData(callback); } @@ -111,11 +111,11 @@ class NumpyArraySlice extends ComparableArrayChunk { } String fullName = ((XValueNodeImpl)node).getName(); - if (!fullName.contains(getPresentation())) { + if (fullName == null || !fullName.contains(getPresentation())) { return; } - int row = -1; + int row; if (isOneRow()) { row = 0; } @@ -136,6 +136,9 @@ class NumpyArraySlice extends ComparableArrayChunk { if (row != -1 && myData[row][0] == null) { for (int i = 0; i < node.getChildCount() - 1; i++) { String rawValue = ((XValueNodeImpl)node.getChildAt(i + 1)).getRawValue(); + if (rawValue == null) { + return; + } if (myValueProvider.isNumeric()) { //remove str quotes in case of numeric rawValue = rawValue.substring(1, rawValue.length() - 1); @@ -144,6 +147,9 @@ class NumpyArraySlice extends ComparableArrayChunk { } if (node.getChildCount() == 0) { String rawValue = ((XValueNodeImpl)node).getRawValue(); + if (rawValue == null) { + return; + } if (myValueProvider.isNumeric()) { //remove str quotes in case of numeric rawValue = rawValue.substring(1, rawValue.length() - 1); diff --git a/python/src/com/jetbrains/python/debugger/array/NumpyArrayValueProvider.java b/python/src/com/jetbrains/python/debugger/array/NumpyArrayValueProvider.java index 58abc6b9b81b..18f23ef1c7b7 100644 --- a/python/src/com/jetbrains/python/debugger/array/NumpyArrayValueProvider.java +++ b/python/src/com/jetbrains/python/debugger/array/NumpyArrayValueProvider.java @@ -45,7 +45,7 @@ import java.util.List; /** * @author amarch */ -class NumpyArrayValueProvider extends ArrayValueProvider { +public class NumpyArrayValueProvider extends ArrayValueProvider { private PyViewArrayAction.MyDialog myDialog; private ArrayTableForm myComponent; private JBTable myTable; @@ -69,12 +69,14 @@ class NumpyArrayValueProvider extends ArrayValueProvider { private final static String DISABLE_COLOR_FOR_HUGE_ARRAY = "Disable color because array too big and calculating min and max would slow down debugging."; - public NumpyArrayValueProvider(@NotNull XValueNode node, @NotNull PyViewArrayAction.MyDialog dialog, @NotNull Project project) { + public NumpyArrayValueProvider(@NotNull XValueNode node, PyViewArrayAction.MyDialog dialog, @NotNull Project project) { super(node); myDialog = dialog; - myComponent = dialog.getComponent(); + if (dialog != null) { + myComponent = dialog.getComponent(); + myTable = myComponent.getTable(); + } myProject = project; - myTable = myComponent.getTable(); myEvaluator = new PyDebuggerEvaluator(project, getValueContainer().getFrameAccessor()); } @@ -120,12 +122,13 @@ class NumpyArrayValueProvider extends ArrayValueProvider { getPendingSet().remove(chunk); notifyNextThread(); fireTableCellUpdated(chunk.rOffset, chunk.cOffset); - SwingUtilities.invokeLater(new Runnable() { + DebuggerUIUtil.invokeLater(new Runnable() { public void run() { addDataInCache(arraySlice.rOffset, arraySlice.cOffset, arraySlice.getData()); myTable.setDefaultEditor(myTable.getColumnClass(0), getArrayTableCellEditor()); myTable.setDefaultRenderer(myTable.getColumnClass(0), myTableCellRenderer); + myDialog.setTitle(getTitlePresentation(getSliceText())); } }); } @@ -272,6 +275,7 @@ class NumpyArrayValueProvider extends ArrayValueProvider { public void run() { myComponent.getSliceTextField().setText(getDefaultPresentation()); myComponent.getFormatTextField().setText(getDefaultFormat()); + myDialog.setTitle(getTitlePresentation(getDefaultPresentation())); } }); startFillTable(new NumpyArraySlice(getDefaultPresentation(), Math.min(getMaxRow(myShape), ROWS_IN_DEFAULT_VIEW), @@ -279,6 +283,10 @@ class NumpyArrayValueProvider extends ArrayValueProvider { false, false); } + private static String getTitlePresentation(String slice) { + return "Array View: " + slice; + } + private void fillColorRange(@NotNull final Runnable returnToMain) { XDebuggerEvaluator.XEvaluationCallback callback = new XDebuggerEvaluator.XEvaluationCallback() { @Override @@ -630,7 +638,7 @@ class NumpyArrayValueProvider extends ArrayValueProvider { } public void showInfoHint(final String message) { - SwingUtilities.invokeLater(new Runnable() { + DebuggerUIUtil.invokeLater(new Runnable() { @Override public void run() { if (myComponent.getSliceTextField().getEditor() != null) { @@ -701,7 +709,7 @@ class NumpyArrayValueProvider extends ArrayValueProvider { startRefillTable(false); } - private String getEvalShapeCommand(@NotNull String slice) { + private static String getEvalShapeCommand(@NotNull String slice) { //add information about memory, see #parseShape comments return "str(" + slice + ".shape)+'#'+str(" + slice + ".flags['C_CONTIGUOUS'])"; } @@ -764,7 +772,7 @@ class NumpyArrayValueProvider extends ArrayValueProvider { } public void setBusy(final boolean busy) { - SwingUtilities.invokeLater(new Runnable() { + DebuggerUIUtil.invokeLater(new Runnable() { @Override public void run() { myComponent.setBusy(busy); diff --git a/python/src/com/jetbrains/python/debugger/array/PagingTableModel.java b/python/src/com/jetbrains/python/debugger/array/PagingTableModel.java index 103f00f1a07e..e0f70b7d6d1e 100644 --- a/python/src/com/jetbrains/python/debugger/array/PagingTableModel.java +++ b/python/src/com/jetbrains/python/debugger/array/PagingTableModel.java @@ -27,8 +27,8 @@ import java.util.SortedSet; import java.util.TreeSet; public abstract class PagingTableModel extends AbstractTableModel { - private static final int CHUNK_COL_SIZE = 10; - private static final int CHUNK_ROW_SIZE = 10; + private static final int CHUNK_COL_SIZE = 50; + private static final int CHUNK_ROW_SIZE = 50; private static final int DEFAULT_MAX_CACHED_SIZE = 100; public static final String EMPTY_CELL_VALUE = "..."; @@ -79,11 +79,10 @@ public abstract class PagingTableModel extends AbstractTableModel { return EMPTY_CELL_VALUE; } - Object rowObject = myCachedData.get(key)[row % CHUNK_ROW_SIZE][col % CHUNK_COL_SIZE]; - return rowObject; + return myCachedData.get(key)[row % CHUNK_ROW_SIZE][col % CHUNK_COL_SIZE]; } - private String formMapKey(int row, int col) { + private static String formMapKey(int row, int col) { return "[" + getPageRowStart(row) + "," + getPageColStart(col) + "]"; } diff --git a/python/src/com/jetbrains/python/debugger/array/PyViewArrayAction.java b/python/src/com/jetbrains/python/debugger/array/PyViewArrayAction.java index 7d61e1526ed2..a34cf20b7ca5 100644 --- a/python/src/com/jetbrains/python/debugger/array/PyViewArrayAction.java +++ b/python/src/com/jetbrains/python/debugger/array/PyViewArrayAction.java @@ -16,14 +16,18 @@ package com.jetbrains.python.debugger.array; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase; import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; import com.jetbrains.python.debugger.PyDebugValue; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.tree.TreePath; /** * @author amarch @@ -34,11 +38,37 @@ public class PyViewArrayAction extends XDebuggerTreeActionBase { @Override protected void perform(XValueNodeImpl node, @NotNull String nodeName, AnActionEvent e) { final MyDialog dialog = new MyDialog(e.getProject()); - dialog.setTitle("View Array"); dialog.setValue(node); dialog.show(); } + @Nullable + private static TreePath[] getSelectedNodes(DataContext dataContext) { + XDebuggerTree tree = XDebuggerTree.getTree(dataContext); + return tree == null ? null : tree.getSelectionPaths(); + } + + @Override + public void update(AnActionEvent e) { + TreePath[] paths = getSelectedNodes(e.getDataContext()); + if (paths != null) { + if(paths.length > 1) { + e.getPresentation().setVisible(false); + return; + } + + XValueNodeImpl node = getSelectedNode(e.getDataContext()); + if (node != null && node.getValueContainer() instanceof PyDebugValue && node.isComputed()) { + String nodeType = ((PyDebugValue) node.getValueContainer()).getType(); + if ("ndarray".equals(nodeType)) { + e.getPresentation().setVisible(true); + return; + } + } + } + e.getPresentation().setVisible(false); + } + protected class MyDialog extends DialogWrapper { private Project myProject; private ArrayTableForm myComponent;