Commit fed318c7 authored by fitermay's avatar fitermay
Browse files

--remove form duplication

--move row headers into model
--cleanup
parent 164416d3
Showing with 285 additions and 417 deletions
+285 -417
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.python.debugger.array;
import com.intellij.openapi.project.Project;
import com.jetbrains.python.debugger.containerview.NumericContainerRendererForm;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import java.awt.*;
import java.awt.event.KeyListener;
/**
* @author amarch
*/
public class ArrayTableForm extends NumericContainerRendererForm {
public ArrayTableForm(@NotNull Project project, KeyListener resliceCallback, KeyListener reformatCallback) {
super(project, resliceCallback, reformatCallback);
}
protected void createUIComponents() {
super.createUIComponents();
myTable = new JBTableWithRowHeaders();
myScrollPane = ((JBTableWithRowHeaders)myTable).getScrollPane();
}
public static class ColumnHeaderRenderer extends DefaultTableHeaderCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean selected, boolean focused, int row, int column) {
super.getTableCellRendererComponent(table, value, selected, focused, row, column);
int selectedColumn = table.getSelectedColumn();
if (selectedColumn == column) {
setFont(getFont().deriveFont(Font.BOLD));
}
return this;
}
}
public static class DefaultTableHeaderCellRenderer extends DefaultTableCellRenderer {
public DefaultTableHeaderCellRenderer() {
setHorizontalAlignment(CENTER);
setHorizontalTextPosition(LEFT);
setVerticalAlignment(BOTTOM);
setOpaque(false);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
JTableHeader tableHeader = table.getTableHeader();
if (tableHeader != null) {
setForeground(tableHeader.getForeground());
}
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
return this;
}
}
}
......@@ -25,8 +25,10 @@ import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.ui.UIUtil;
import com.jetbrains.python.debugger.ArrayChunk;
import com.jetbrains.python.debugger.ArrayChunkBuilder;
import org.jetbrains.annotations.NotNull;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import java.util.concurrent.*;
/**
......@@ -48,16 +50,13 @@ public class AsyncArrayTableModel extends AbstractTableModel {
private LoadingCache<Pair<Integer, Integer>, ListenableFuture<ArrayChunk>> myChunkCache = CacheBuilder.newBuilder().build(
new CacheLoader<Pair<Integer, Integer>, ListenableFuture<ArrayChunk>>() {
@Override
public ListenableFuture<ArrayChunk> load(final Pair<Integer, Integer> key) throws Exception {
public ListenableFuture<ArrayChunk> load(@NotNull final Pair<Integer, Integer> key) throws Exception {
ListenableFutureTask<ArrayChunk> task = ListenableFutureTask.create(new Callable<ArrayChunk>() {
@Override
public ArrayChunk call() throws Exception {
ArrayChunk chunk = myProvider.getChunk(key.first, key.second, Math.min(CHUNK_ROW_SIZE, getRowCount() - key.first),
Math.min(CHUNK_COL_SIZE, getColumnCount() - key.second));
handleChunkAdded(key.first, key.second, chunk);
return chunk;
}
ListenableFutureTask<ArrayChunk> task = ListenableFutureTask.create(() -> {
ArrayChunk chunk = myProvider.getChunk(key.first, key.second, Math.min(CHUNK_ROW_SIZE, getRowCount() - key.first),
Math.min(CHUNK_COL_SIZE, getColumnCount() - key.second));
handleChunkAdded(key.first, key.second, chunk);
return chunk;
});
myExecutorService.execute(task);
......@@ -74,14 +73,6 @@ public class AsyncArrayTableModel extends AbstractTableModel {
@Override
public boolean isCellEditable(int row, int col) {
//Pair<Integer, Integer> key = itemToChunkKey(row, col);
//try {
// return myChunkCache.get(key).isDone();
//}
//catch (ExecutionException e) {
// return false;
//}
//TODO: make it editable
return false;
}
......@@ -161,13 +152,11 @@ public class AsyncArrayTableModel extends AbstractTableModel {
Pair<Integer, Integer> key = itemToChunkKey(roffset * CHUNK_ROW_SIZE, coffset * CHUNK_COL_SIZE);
final Object[][] chunkData = new Object[CHUNK_ROW_SIZE][CHUNK_COL_SIZE];
for (int r = 0; r < CHUNK_ROW_SIZE; r++) {
for (int c = 0; c < CHUNK_COL_SIZE; c++) {
chunkData[r][c] = data[roffset * CHUNK_ROW_SIZE + r][coffset * CHUNK_COL_SIZE + c];
}
System.arraycopy(data[roffset * CHUNK_ROW_SIZE + r], coffset * 30, chunkData[r], 0, CHUNK_COL_SIZE);
}
myChunkCache.put(key, new ListenableFuture<ArrayChunk>() {
@Override
public void addListener(Runnable listener, Executor executor) {
public void addListener(@NotNull Runnable listener, @NotNull Executor executor) {
}
......@@ -206,4 +195,35 @@ public class AsyncArrayTableModel extends AbstractTableModel {
protected void handleChunkAdded(Integer rowOffset, Integer colOffset, ArrayChunk chunk) {
}
public TableModel getRowHeaderModel() {
return new RowNumberHeaderModel();
}
private class RowNumberHeaderModel extends AbstractTableModel {
@Override
public int getRowCount() {
return AsyncArrayTableModel.this.getRowCount();
}
@Override
public int getColumnCount() {
return 1;
}
@Override
public String getColumnName(int column) {
if (column == 0) {
return " ";
}
throw new IllegalArgumentException("Table only has one column");
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
return Integer.toString(rowIndex);
}
}
}
\ No newline at end of file
......@@ -21,12 +21,10 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import java.awt.*;
import java.awt.event.MouseListener;
import java.beans.PropertyChangeEvent;
......@@ -39,59 +37,47 @@ public class JBTableWithRowHeaders extends JBTable {
private final JBScrollPane myScrollPane;
private RowHeaderTable myRowHeaderTable;
public JBScrollPane getScrollPane() {
return myScrollPane;
}
public JBTableWithRowHeaders() {
setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
setRowSelectionAllowed(false);
setMaxItemsForSizeCalculation(50);
setTableHeader(new CustomTableHeader(this));
getTableHeader().setDefaultRenderer(new ArrayTableForm.ColumnHeaderRenderer());
getTableHeader().setDefaultRenderer(new ColumnHeaderRenderer());
getTableHeader().setReorderingAllowed(false);
myScrollPane = new JBScrollPane(this);
JBTableWithRowHeaders.RowHeaderTable rowTable = new JBTableWithRowHeaders.RowHeaderTable(this);
myScrollPane.setRowHeaderView(rowTable);
myRowHeaderTable = new JBTableWithRowHeaders.RowHeaderTable(this);
myScrollPane.setRowHeaderView(myRowHeaderTable);
myScrollPane.setCorner(ScrollPaneConstants.UPPER_LEFT_CORNER,
rowTable.getTableHeader());
myRowHeaderTable.getTableHeader());
}
setRowHeaderTable(rowTable);
public JBScrollPane getScrollPane() {
return myScrollPane;
}
public boolean getScrollableTracksViewportWidth() {
return getPreferredSize().width < getParent().getWidth();
}
public RowHeaderTable getRowHeaderTable() {
return myRowHeaderTable;
}
public void setRowHeaderTable(RowHeaderTable rowHeaderTable) {
myRowHeaderTable = rowHeaderTable;
@Override
public void setModel(@NotNull TableModel model) {
super.setModel(model);
if (model instanceof AsyncArrayTableModel) {
myRowHeaderTable.setModel(((AsyncArrayTableModel)model).getRowHeaderModel());
}
}
public static class RowHeaderTable extends JBTable implements PropertyChangeListener, TableModelListener {
private JTable myMainTable;
private int myRowShift = 0;
public RowHeaderTable(JTable table) {
myMainTable = table;
myMainTable.getModel().addTableModelListener(this);
setFocusable(false);
setAutoCreateColumnsFromModel(false);
setSelectionModel(myMainTable.getSelectionModel());
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
TableColumn column = new TableColumn();
column.setHeaderValue(" ");
addColumn(column);
column.setCellRenderer(new RowNumberRenderer());
getColumnModel().getColumn(0).setPreferredWidth(50);
setPreferredScrollableViewportSize(getPreferredSize());
setRowHeight(myMainTable.getRowHeight());
MouseListener[] listeners = getMouseListeners();
for (MouseListener l : listeners) {
......@@ -105,9 +91,16 @@ public class JBTableWithRowHeaders extends JBTable {
super.paintComponent(g);
}
@Override
public int getRowCount() {
return myMainTable.getRowCount();
public void setModel(@NotNull TableModel model) {
setAutoCreateColumnsFromModel(true);
super.setModel(model);
if (getColumnModel().getColumnCount() > 0) {
getColumnModel().getColumn(0).setPreferredWidth(50);
getColumnModel().getColumn(0).setCellRenderer(new RowNumberRenderer());
setPreferredScrollableViewportSize(getPreferredSize());
}
}
@Override
......@@ -116,14 +109,6 @@ public class JBTableWithRowHeaders extends JBTable {
return super.getRowHeight(row);
}
@Override
public Object getValueAt(int row, int column) {
return Integer.toString(row + myRowShift);
}
public void setRowShift(int shift) {
myRowShift = shift;
}
@Override
public boolean isCellEditable(int row, int column) {
......@@ -131,10 +116,6 @@ public class JBTableWithRowHeaders extends JBTable {
}
@Override
public void setValueAt(Object value, int row, int column) {
}
public void propertyChange(PropertyChangeEvent e) {
if ("selectionModel".equals(e.getPropertyName())) {
setSelectionModel(myMainTable.getSelectionModel());
......@@ -145,17 +126,12 @@ public class JBTableWithRowHeaders extends JBTable {
}
if ("model".equals(e.getPropertyName())) {
myMainTable.getModel().addTableModelListener(this);
revalidate();
}
}
@Override
public void tableChanged(TableModelEvent e) {
revalidate();
}
private class RowNumberRenderer extends DefaultTableCellRenderer {
private static class RowNumberRenderer extends DefaultTableCellRenderer {
public RowNumberRenderer() {
setHorizontalAlignment(SwingConstants.CENTER);
}
......@@ -189,12 +165,7 @@ public class JBTableWithRowHeaders extends JBTable {
public CustomTableHeader(JTable table) {
super();
setColumnModel(table.getColumnModel());
table.getColumnModel().getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
repaint();
}
});
table.getColumnModel().getSelectionModel().addListSelectionListener(e -> repaint());
}
@Override
......@@ -202,4 +173,39 @@ public class JBTableWithRowHeaders extends JBTable {
repaint();
}
}
public static class ColumnHeaderRenderer extends DefaultTableHeaderCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean selected, boolean focused, int row, int column) {
super.getTableCellRendererComponent(table, value, selected, focused, row, column);
int selectedColumn = table.getSelectedColumn();
if (selectedColumn == column) {
setFont(getFont().deriveFont(Font.BOLD));
}
return this;
}
}
public static class DefaultTableHeaderCellRenderer extends DefaultTableCellRenderer {
public DefaultTableHeaderCellRenderer() {
setHorizontalAlignment(CENTER);
setHorizontalTextPosition(LEFT);
setVerticalAlignment(BOTTOM);
setOpaque(false);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
JTableHeader tableHeader = table.getTableHeader();
if (tableHeader != null) {
setForeground(tableHeader.getForeground());
}
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
return this;
}
}
}
......@@ -14,19 +14,14 @@
* limitations under the License.
*/
package com.jetbrains.python.debugger.array;
import com.intellij.openapi.project.Project;
import com.intellij.util.ui.UIUtil;
import com.jetbrains.python.debugger.ArrayChunk;
import com.jetbrains.python.debugger.PyDebugValue;
import com.jetbrains.python.debugger.containerview.ColoredCellRenderer;
import com.jetbrains.python.debugger.containerview.NumericContainerViewTable;
import com.jetbrains.python.debugger.containerview.ViewNumericContainerDialog;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyListener;
/**
* @author amarch
*/
......@@ -34,65 +29,30 @@ public final class NumpyArrayTable extends NumericContainerViewTable {
private ArrayTableCellRenderer myArrayTableCellRenderer;
public NumpyArrayTable(@NotNull Project project,
@NotNull ViewNumericContainerDialog dialog, @NotNull PyDebugValue value) {
super(project, dialog, value);
}
@Override
protected final String getTitlePresentation(String slice) {
return "Array View: " + slice;
protected AsyncArrayTableModel createTableModel(int rowCount, int columnCount) {
return new AsyncArrayTableModel(rowCount, columnCount, this);
}
public void disableColor() {
myArrayTableCellRenderer.setMin(Double.MAX_VALUE);
myArrayTableCellRenderer.setMax(Double.MIN_VALUE);
myTableCellRenderer.setColored(false);
UIUtil.invokeLaterIfNeeded(() -> {
myComponent.getColoredCheckbox().setSelected(false);
myComponent.getColoredCheckbox().setEnabled(false);
if (myTable.getColumnCount() > 0) {
myTable.setDefaultRenderer(myTable.getColumnClass(0), myArrayTableCellRenderer);
}
});
@Override
protected ColoredCellRenderer createCellRenderer(double minValue, double maxValue, ArrayChunk chunk) {
myArrayTableCellRenderer = new ArrayTableCellRenderer(minValue, maxValue, chunk.getType());
fillColorRange(chunk.getMin(), chunk.getMax());
return myArrayTableCellRenderer;
}
@Override
protected final void initUi(@NotNull final ArrayChunk chunk, final boolean inPlace) {
myPagingModel = new AsyncArrayTableModel(Math.min(chunk.getRows(), ROWS_IN_DEFAULT_VIEW),
Math.min(chunk.getColumns(), COLUMNS_IN_DEFAULT_VIEW), this);
myPagingModel.addToCache(chunk);
myDtypeKind = chunk.getType();
UIUtil.invokeLaterIfNeeded(() -> {
myTable.setModel(myPagingModel);
myComponent.getSliceTextField().setText(chunk.getSlicePresentation());
myComponent.getFormatTextField().setText(chunk.getFormat());
myDialog.setTitle(getTitlePresentation(chunk.getSlicePresentation()));
myArrayTableCellRenderer = new ArrayTableCellRenderer(Double.MIN_VALUE, Double.MIN_VALUE, chunk.getType());
myTableCellRenderer = myArrayTableCellRenderer;
fillColorRange(chunk.getMin(), chunk.getMax());
if (!isNumeric()) {
disableColor();
}
else {
myComponent.getColoredCheckbox().setEnabled(true);
}
if (!inPlace) {
myComponent.getScrollPane().getViewport().setViewPosition(new Point(0, 0));
JBTableWithRowHeaders.RowHeaderTable rowTable = ((JBTableWithRowHeaders)myTable).getRowHeaderTable();
rowTable.setRowShift(0);
}
((AsyncArrayTableModel)myTable.getModel()).fireTableDataChanged();
((AsyncArrayTableModel)myTable.getModel()).fireTableCellUpdated(0, 0);
if (myTable.getColumnCount() > 0) {
myTable.setDefaultRenderer(myTable.getColumnClass(0), myArrayTableCellRenderer);
}
});
protected final String getTitlePresentation(String slice) {
return "Array View: " + slice;
}
private void fillColorRange(String minValue, String maxValue) {
double min;
double max;
......@@ -122,29 +82,4 @@ public final class NumpyArrayTable extends NumericContainerViewTable {
}
return false;
}
@Override
protected final void initTableModel(final boolean inPlace) {
myPagingModel = new AsyncArrayTableModel(myPagingModel.getRowCount(), myPagingModel.getColumnCount(), this);
UIUtil.invokeLaterIfNeeded(() -> {
myTable.setModel(myPagingModel);
if (!inPlace) {
myComponent.getScrollPane().getViewport().setViewPosition(new Point(0, 0));
JBTableWithRowHeaders.RowHeaderTable rowTable = ((JBTableWithRowHeaders)myTable).getRowHeaderTable();
rowTable.setRowShift(0);
}
((AsyncArrayTableModel)myTable.getModel()).fireTableDataChanged();
((AsyncArrayTableModel)myTable.getModel()).fireTableCellUpdated(0, 0);
if (myTable.getColumnCount() > 0) {
myTable.setDefaultRenderer(myTable.getColumnClass(0), myArrayTableCellRenderer);
}
});
}
@Override
@NotNull
protected ArrayTableForm createForm(@NotNull Project project, KeyListener resliceCallback, KeyAdapter formatCallback) {
return new ArrayTableForm(project,resliceCallback, formatCallback);
}
}
......@@ -15,10 +15,11 @@
*/
package com.jetbrains.python.debugger.containerview;
import javax.swing.table.TableCellRenderer;
/**
* Created by Yuli Fiterman on 5/10/2016.
*/
public interface ColoredCellRenderer {
public interface ColoredCellRenderer extends TableCellRenderer {
void setColored(boolean colored);
}
......@@ -8,7 +8,7 @@
<properties/>
<border type="none"/>
<children>
<scrollpane id="90774" class="com.intellij.ui.components.JBScrollPane" binding="myScrollPane">
<scrollpane id="90774" class="com.intellij.ui.components.JBScrollPane" binding="myScrollPane" custom-create="true">
<constraints>
<grid row="0" column="0" row-span="1" col-span="5" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
......@@ -18,7 +18,7 @@
</properties>
<border type="none"/>
<children>
<component id="c7f7c" class="com.intellij.ui.table.JBTable" binding="myTable" custom-create="true">
<component id="c7f7c" class="com.jetbrains.python.debugger.array.JBTableWithRowHeaders" binding="myTable" custom-create="true">
<constraints/>
<properties>
<autoResizeMode value="0"/>
......
......@@ -21,9 +21,13 @@ import com.intellij.ui.EditorTextField;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.table.JBTable;
import com.jetbrains.python.PythonFileType;
import com.jetbrains.python.debugger.array.JBTableWithRowHeaders;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import java.awt.*;
import java.awt.event.KeyListener;
/**
......@@ -35,7 +39,7 @@ public class NumericContainerRendererForm {
protected final KeyListener myResliceCallback;
protected JBScrollPane myScrollPane;
protected EditorTextField mySliceTextField;
protected JBTable myTable;
protected JBTableWithRowHeaders myTable;
protected EditorTextField myFormatTextField;
protected JCheckBox myColoredCheckbox;
protected JPanel myFormatPanel;
......@@ -91,5 +95,8 @@ public class NumericContainerRendererForm {
return editor;
}
};
myTable = new JBTableWithRowHeaders();
myScrollPane = myTable.getScrollPane();
}
}
......@@ -19,17 +19,16 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.project.Project;
import com.intellij.util.ui.UIUtil;
import com.jetbrains.python.debugger.ArrayChunk;
import com.jetbrains.python.debugger.PyDebugValue;
import com.jetbrains.python.debugger.PyDebuggerException;
import com.jetbrains.python.debugger.array.AsyncArrayTableModel;
import com.jetbrains.python.debugger.array.TableChunkDatasource;
import com.jetbrains.python.debugger.containerview.ColoredCellRenderer;
import com.jetbrains.python.debugger.containerview.NumericContainerRendererForm;
import com.jetbrains.python.debugger.containerview.ViewNumericContainerDialog;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/**
......@@ -49,17 +48,17 @@ public abstract class NumericContainerViewTable implements TableChunkDatasource
protected AsyncArrayTableModel myPagingModel;
public NumericContainerViewTable(
@NotNull Project project, @NotNull ViewNumericContainerDialog dialog,@NotNull PyDebugValue value) {
@NotNull Project project, @NotNull ViewNumericContainerDialog dialog, @NotNull PyDebugValue value) {
myProject = project;
myDialog = dialog;
myComponent = createForm(project, new KeyAdapter() {
myComponent = createForm(project, new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
doReslice();
}
}
}, new KeyAdapter() {
}, new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
......@@ -71,10 +70,74 @@ public abstract class NumericContainerViewTable implements TableChunkDatasource
myTable = myComponent.getTable();
}
private void initUi(@NotNull final ArrayChunk chunk, final boolean inPlace) {
myPagingModel = createTableModel(Math.min(chunk.getRows(), ROWS_IN_DEFAULT_VIEW),
Math.min(chunk.getColumns(), COLUMNS_IN_DEFAULT_VIEW));
myPagingModel.addToCache(chunk);
myDtypeKind = chunk.getType();
UIUtil.invokeLaterIfNeeded(() -> {
myTable.setModel(myPagingModel);
myComponent.getSliceTextField().setText(chunk.getSlicePresentation());
myComponent.getFormatTextField().setText(chunk.getFormat());
myDialog.setTitle(getTitlePresentation(chunk.getSlicePresentation()));
myTableCellRenderer = createCellRenderer(Double.MIN_VALUE, Double.MIN_VALUE, chunk);
if (!isNumeric()) {
disableColor();
}
else {
myComponent.getColoredCheckbox().setEnabled(true);
}
if (!inPlace) {
myComponent.getScrollPane().getViewport().setViewPosition(new Point(0, 0));
}
((AsyncArrayTableModel)myTable.getModel()).fireTableDataChanged();
((AsyncArrayTableModel)myTable.getModel()).fireTableCellUpdated(0, 0);
if (myTable.getColumnCount() > 0) {
myTable.setDefaultRenderer(myTable.getColumnClass(0), myTableCellRenderer);
}
});
}
private void disableColor() {
myTableCellRenderer.setColored(false);
UIUtil.invokeLaterIfNeeded(() -> {
myComponent.getColoredCheckbox().setSelected(false);
myComponent.getColoredCheckbox().setEnabled(false);
if (myTable.getColumnCount() > 0) {
myTable.setDefaultRenderer(myTable.getColumnClass(0), myTableCellRenderer);
}
});
}
protected abstract AsyncArrayTableModel createTableModel(int rowCount, int columnCount);
protected abstract ColoredCellRenderer createCellRenderer(double minValue, double maxValue, ArrayChunk chunk);
private void initTableModel(final boolean inPlace) {
myPagingModel = createTableModel(myPagingModel.getRowCount(), myPagingModel.getColumnCount());
UIUtil.invokeLaterIfNeeded(() -> {
myTable.setModel(myPagingModel);
if (!inPlace) {
myComponent.getScrollPane().getViewport().setViewPosition(new Point(0, 0));
}
((AsyncArrayTableModel)myTable.getModel()).fireTableDataChanged();
((AsyncArrayTableModel)myTable.getModel()).fireTableCellUpdated(0, 0);
if (myTable.getColumnCount() > 0) {
myTable.setDefaultRenderer(myTable.getColumnClass(0), myTableCellRenderer);
}
});
}
@NotNull
protected abstract NumericContainerRendererForm createForm(@NotNull Project project, KeyListener resliceCallback, KeyAdapter formatCallback);
private static NumericContainerRendererForm createForm(@NotNull Project project, KeyListener resliceCallback, KeyAdapter formatCallback) {
return new NumericContainerRendererForm(project, resliceCallback, formatCallback);
}
protected abstract String getTitlePresentation(String slice) ;
protected abstract String getTitlePresentation(String slice);
public final NumericContainerRendererForm getComponent() {
......@@ -97,9 +160,8 @@ public abstract class NumericContainerViewTable implements TableChunkDatasource
renderer.setColored(false);
}
}
if (myTableCellRenderer != null)
{
myTableCellRenderer.setColored(myComponent.getColoredCheckbox().isSelected());
if (myTableCellRenderer != null) {
myTableCellRenderer.setColored(myComponent.getColoredCheckbox().isSelected());
}
myComponent.getScrollPane().repaint();
}
......@@ -132,12 +194,13 @@ public abstract class NumericContainerViewTable implements TableChunkDatasource
public void init(final String slice, final boolean inPlace) {
initComponent();
myComponent.getSliceTextField().setText(slice);
ApplicationManager.getApplication().executeOnPooledThread(() -> {
final PyDebugValue value = getDebugValue();
PyDebugValue parent = value.getParent();
final PyDebugValue slicedValue =
new PyDebugValue(slice, value.getType(), null, value.getValue(), value.isContainer(), value.isErrorOnEval(),
new PyDebugValue(slice, value.getType(), null, value.getValue(), value.isContainer(), value.isReturnedVal(), value.isErrorOnEval(),
parent, value.getFrameAccessor());
final String format = getFormat().isEmpty() ? "%" : getFormat();
......@@ -152,7 +215,6 @@ public abstract class NumericContainerViewTable implements TableChunkDatasource
});
}
protected abstract void initUi(@NotNull ArrayChunk chunk, boolean inPlace);
public String getSliceText() {
return myComponent.getSliceTextField().getText();
......@@ -162,7 +224,7 @@ public abstract class NumericContainerViewTable implements TableChunkDatasource
public ArrayChunk getChunk(int rowOffset, int colOffset, int rows, int cols) throws PyDebuggerException {
final PyDebugValue slicedValue =
new PyDebugValue(getSliceText(), myValue.getType(), myValue.getTypeQualifier(), myValue.getValue(), myValue.isContainer(),
myValue.isErrorOnEval(),
myValue.isErrorOnEval(), myValue.isReturnedVal(),
myValue.getParent(), myValue.getFrameAccessor());
return myValue.getFrameAccessor().getArrayItems(slicedValue, rowOffset, colOffset, rows, cols, getFormat());
......@@ -170,7 +232,6 @@ public abstract class NumericContainerViewTable implements TableChunkDatasource
public abstract boolean isNumeric();
protected abstract void initTableModel(boolean inPlace);
@Override
public final String correctStringValue(@NotNull Object value) {
......@@ -194,7 +255,7 @@ public abstract class NumericContainerViewTable implements TableChunkDatasource
myDialog.setError(message);
}
protected final void doReslice() {
protected final void doReslice() {
clearErrorMessage();
init(getSliceText(), false);
}
......
......@@ -19,6 +19,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.util.ui.UIUtil;
import com.jetbrains.python.debugger.*;
import com.jetbrains.python.debugger.array.AsyncArrayTableModel;
import com.jetbrains.python.debugger.containerview.ColoredCellRenderer;
import com.jetbrains.python.debugger.containerview.NumericContainerViewTable;
import com.jetbrains.python.debugger.array.TableChunkDatasource;
import com.jetbrains.python.debugger.containerview.NumericContainerRendererForm;
......@@ -36,66 +37,28 @@ import java.awt.event.*;
public class DataFrameTable extends NumericContainerViewTable implements TableChunkDatasource {
private Project myProject;
private DataFrameTableCellRenderer myDataFrameCellRenderer;
public DataFrameTable(@NotNull Project project,
@NotNull ViewNumericContainerDialog dialog, @NotNull PyDebugValue value) {
super(project, dialog, value);
}
@NotNull
@Override
protected NumericContainerRendererForm createForm(@NotNull Project project, KeyListener resliceCallback, KeyAdapter formatCallback) {
return new DataFrameTableForm(project,resliceCallback,formatCallback);
protected AsyncArrayTableModel createTableModel(int rowCount, int columnCount) {
return new DataFrameTableModel(rowCount, columnCount, this);
}
protected final void initUi(@NotNull final ArrayChunk chunk, final boolean inPlace) {
myPagingModel = new DataFrameTableModel(Math.min(chunk.getRows(), ROWS_IN_DEFAULT_VIEW),
Math.min(chunk.getColumns(), COLUMNS_IN_DEFAULT_VIEW), this);
myPagingModel.addToCache(chunk);
UIUtil.invokeLaterIfNeeded(() -> {
myTable.setModel(myPagingModel);
myComponent.getSliceTextField().setText(chunk.getSlicePresentation());
myComponent.getFormatTextField().setText(chunk.getFormat());
myDialog.setTitle(getTitlePresentation(chunk.getSlicePresentation()));
myDataFrameCellRenderer = new DataFrameTableCellRenderer();
myTableCellRenderer = myDataFrameCellRenderer;
myComponent.getColoredCheckbox().setEnabled(true);
if (!inPlace) {
myComponent.getScrollPane().getViewport().setViewPosition(new Point(0, 0));
}
((AsyncArrayTableModel)myTable.getModel()).fireTableDataChanged();
((AsyncArrayTableModel)myTable.getModel()).fireTableCellUpdated(0, 0);
myTable.setDefaultRenderer(TableValueDescriptor.class, myDataFrameCellRenderer);
});
@Override
protected ColoredCellRenderer createCellRenderer(double minValue, double maxValue, ArrayChunk chunk) {
return new DataFrameTableCellRenderer();
}
@Override
public boolean isNumeric() {
return false;
return true;
}
protected final String getTitlePresentation(String slice) {
return "DataFrame View: " + slice;
}
protected final void initTableModel(final boolean inPlace) {
myPagingModel = new DataFrameTableModel(myPagingModel.getRowCount(), myPagingModel.getColumnCount() - 1, this);
UIUtil.invokeLaterIfNeeded(() -> {
myTable.setModel(myPagingModel);
if (!inPlace) {
myComponent.getScrollPane().getViewport().setViewPosition(new Point(0, 0));
}
((AsyncArrayTableModel)myTable.getModel()).fireTableDataChanged();
((AsyncArrayTableModel)myTable.getModel()).fireTableCellUpdated(0, 0);
myTable.setDefaultRenderer(TableValueDescriptor.class, myDataFrameCellRenderer);
});
}
}
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.python.debugger.dataframe;
import com.intellij.openapi.project.Project;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.table.JBTable;
import com.jetbrains.python.debugger.containerview.NumericContainerRendererForm;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.event.KeyListener;
/**
* Created by Yuli Fiterman on 4/26/2016.
*/
public class DataFrameTableForm extends NumericContainerRendererForm {
public DataFrameTableForm(@NotNull Project project, KeyListener resliceCallback, KeyListener reformatCallback) {
super(project, resliceCallback, reformatCallback);
}
protected void createUIComponents() {
super.createUIComponents();
myTable = new JBTable();
myTable.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
myTable.setRowSelectionAllowed(false);
myTable.setMaxItemsForSizeCalculation(50);
myTable.getTableHeader().setReorderingAllowed(false);
myScrollPane = new JBScrollPane();
}
}
......@@ -21,6 +21,8 @@ import com.jetbrains.python.debugger.ArrayChunk;
import com.jetbrains.python.debugger.array.AsyncArrayTableModel;
import com.jetbrains.python.debugger.array.TableChunkDatasource;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import java.util.List;
import java.util.Map;
......@@ -28,117 +30,119 @@ import java.util.Map;
* Created by Yuli Fiterman on 4/26/2016.
*/
public class DataFrameTableModel extends AsyncArrayTableModel {
private final Map<Integer, String> myRowLabels = Maps.newConcurrentMap();
private final Map<Integer, ArrayChunk.ColHeader> myColHeaders = Maps.newConcurrentMap();
private final RowHeaderModel myRowHeaderModel;
public DataFrameTableModel(int rows, int columns, TableChunkDatasource provider) {
super(rows, columns, provider);
myRowHeaderModel = new RowHeaderModel();
}
/* we use labels for the first column so we need to offset columns by one everywhere */
@Override
public int getColumnCount() {
return super.getColumnCount() +1;
}
@Override
public Object getValueAt(int row, int col) {
if (col == 0) {
return getRowHeader(row);
}
else
{
int frameCol = col - 1;
Object value = super.getValueAt(row, frameCol);
if ( value == AsyncArrayTableModel.EMPTY_CELL_VALUE)
{
return value;
}
TableValueDescriptor descriptor = createValueWithDescriptor(frameCol, value);
return descriptor != null ? descriptor : AsyncArrayTableModel.EMPTY_CELL_VALUE;
Object value = super.getValueAt(row, col);
if (value == AsyncArrayTableModel.EMPTY_CELL_VALUE) {
return value;
}
TableValueDescriptor descriptor = createValueWithDescriptor(col, value);
return descriptor != null ? descriptor : AsyncArrayTableModel.EMPTY_CELL_VALUE;
}
private TableValueDescriptor createValueWithDescriptor(int frameCol, Object value) {
ArrayChunk.ColHeader header = myColHeaders.get(frameCol);
if (header == null)
{
return null;
if (header == null) {
return null;
}
return new TableValueDescriptor(value.toString(), header);
}
private String getRowHeader(int row)
{
String s = myRowLabels.get(row);
return s == null ? String.valueOf(row) : s;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return columnIndex == 0 ? String.class : TableValueDescriptor.class;
return TableValueDescriptor.class;
}
@Override
public String getColumnName(int col) {
if (col == 0)
{
return " ";
}
else
{
int frameColumn = col - 1;
ArrayChunk.ColHeader header = myColHeaders.get(frameColumn);
if (header != null && header.getLabel() != null)
{
return header.getLabel();
}
else
{
return super.getColumnName(frameColumn);
}
ArrayChunk.ColHeader header = myColHeaders.get(col);
if (header != null && header.getLabel() != null) {
return header.getLabel();
}
else {
return super.getColumnName(col);
}
}
@Override
protected void handleChunkAdded(Integer rowOffset, Integer colOffset, ArrayChunk chunk) {
List<String> chunkRowLabels = chunk.getRowLabels();
if (chunkRowLabels != null)
{
for (int i = 0; i < chunkRowLabels.size(); i++) {
String label = chunkRowLabels.get(i);
String oldValue = myRowLabels.put(i + rowOffset, label);
if (oldValue == null)
{
final int updatedRow = i + rowOffset;
UIUtil.invokeLaterIfNeeded(()->
super.fireTableCellUpdated(updatedRow, 0));
}
}
}
myRowHeaderModel.handleChunkAdded(rowOffset, chunk);
boolean hasNewCols = false;
List<ArrayChunk.ColHeader> chunkColHeaders = chunk.getColHeaders();
if (chunkColHeaders != null)
{
if (chunkColHeaders != null) {
for (int i = 0; i < chunkColHeaders.size(); i++) {
ArrayChunk.ColHeader header = chunkColHeaders.get(i);
hasNewCols |= (myColHeaders.put(i + colOffset, header) == null);
}
}
if (hasNewCols)
{
UIUtil.invokeLaterIfNeeded(super::fireTableStructureChanged);
if (hasNewCols) {
UIUtil.invokeLaterIfNeeded(super::fireTableStructureChanged);
}
}
@Override
public void fireTableCellUpdated(int row, int column) {
super.fireTableCellUpdated(row, column + 1);
public TableModel getRowHeaderModel() {
return myRowHeaderModel;
}
private class RowHeaderModel extends AbstractTableModel {
private final Map<Integer, String> myRowLabels = Maps.newConcurrentMap();
@Override
public int getRowCount() {
return DataFrameTableModel.this.getRowCount();
}
@Override
public int getColumnCount() {
return 1;
}
@Override
public String getColumnName(int column) {
if (column == 0) {
return " ";
}
throw new IllegalArgumentException("Table only has one column");
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
String s = myRowLabels.get(rowIndex);
return s == null ? String.valueOf(rowIndex) : s;
}
public void handleChunkAdded(Integer rowOffset, ArrayChunk chunk) {
List<String> chunkRowLabels = chunk.getRowLabels();
if (chunkRowLabels != null) {
for (int i = 0; i < chunkRowLabels.size(); i++) {
String label = chunkRowLabels.get(i);
String oldValue = myRowLabels.put(i + rowOffset, label);
if (oldValue == null) {
final int updatedRow = i + rowOffset;
UIUtil.invokeLaterIfNeeded(() ->
super.fireTableCellUpdated(updatedRow, 0));
}
}
}
}
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment