/**
* Copyright (C) 2001-2017 by RapidMiner and the contributors
*
* Complete list of developers available at our web site:
*
* http://rapidminer.com
*
* This program is free software: you can redistribute it and/or modify it under the terms of the
* GNU Affero General Public License as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see http://www.gnu.org/licenses/.
*/
package com.rapidminer.operator.nio;
import java.awt.BorderLayout;
import java.io.IOException;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import com.rapidminer.gui.tools.ExtendedJScrollPane;
import com.rapidminer.gui.tools.ExtendedJTabbedPane;
import com.rapidminer.gui.tools.ExtendedJTable;
import com.rapidminer.gui.tools.ProgressThread;
import com.rapidminer.gui.tools.ResourceLabel;
import com.rapidminer.operator.OperatorException;
import com.rapidminer.operator.nio.model.ExcelResultSetConfiguration;
import com.rapidminer.operator.nio.model.ParseException;
import com.rapidminer.operator.nio.model.xlsx.XlsxResultSet.XlsxReadMode;
import jxl.read.biff.BiffException;
/**
* This is a pane, showing the contents of a complete excel workbook. There's one tab per sheet.
*
* @author Tobias Malbrecht, Sebastian Land, Simon Fischer
*/
public class ExcelWorkbookPane extends JPanel {
public static class ExcelWorkbookSelection {
/** Numbering starts at 0. */
private int sheetIndex;
private int columnIndexStart;
private int rowIndexStart;
private int columnIndexEnd;
private int rowIndexEnd;
public ExcelWorkbookSelection(int sheetIndex, int columnIndexStart, int rowIndexStart, int columnIndexEnd,
int rowIndexEnd) {
this.sheetIndex = sheetIndex;
this.columnIndexStart = columnIndexStart;
this.rowIndexStart = rowIndexStart;
this.columnIndexEnd = columnIndexEnd;
this.rowIndexEnd = rowIndexEnd;
}
@Override
public String toString() {
return sheetIndex + ": " + columnIndexStart + ":" + rowIndexStart + " - " + columnIndexEnd + ":" + rowIndexEnd;
}
public int getSheetIndex() {
return sheetIndex;
}
public int getColumnIndexEnd() {
return columnIndexEnd;
}
public int getColumnIndexStart() {
return columnIndexStart;
}
public int getRowIndexEnd() {
return rowIndexEnd;
}
public int getRowIndexStart() {
return rowIndexStart;
}
public int getSelectionWidth() {
return columnIndexEnd - columnIndexStart + 1;
}
public int getSelectionHeight() {
return rowIndexEnd - rowIndexStart + 1;
}
}
private static final long serialVersionUID = 9179757216097316344L;
private ExcelResultSetConfiguration configuration;
private ExtendedJTabbedPane sheetsPane;
private ExtendedJTable[] tables;
public ExcelWorkbookPane(ExcelResultSetConfiguration configuration) {
super();
this.configuration = configuration;
// creating gui
sheetsPane = new ExtendedJTabbedPane();
sheetsPane.setBorder(null);
this.setLayout(new BorderLayout());
this.add(sheetsPane);
}
public void loadWorkbook() {
if (configuration.hasWorkbook()) {
// nothing to do
return;
}
// add dummy
sheetsPane.removeAll();
JPanel dummy = new JPanel();
dummy.add(new ResourceLabel("loading_excel_sheets"));
sheetsPane.addTab("Pending...", dummy);
new ProgressThread("load_workbook", false) {
@Override
public void run() {
// initializing progress
getProgressListener().setTotal(100);
getProgressListener().setCompleted(10);
// now add everything to gui
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
tables = new ExtendedJTable[configuration.getNumberOfSheets()];
String[] sheetNames = configuration.getSheetNames();
for (int sheetIndex = 0; sheetIndex < configuration.getNumberOfSheets(); sheetIndex++) {
tables[sheetIndex] = new ExtendedJTable(configuration.createExcelTableModel(sheetIndex,
XlsxReadMode.WIZARD_WORKPANE, getProgressListener()), false, false);
tables[sheetIndex].setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
tables[sheetIndex].setBorder(null);
// momentary disable selection in tables
tables[sheetIndex].setRowSelectionAllowed(false);
tables[sheetIndex].setColumnSelectionAllowed(false);
tables[sheetIndex].setCellSelectionEnabled(true);
// add table to gui
ExtendedJScrollPane pane = new ExtendedJScrollPane(tables[sheetIndex]);
pane.setBorder(null);
if (sheetIndex == 0) {
sheetsPane.removeAll();
}
sheetsPane.addTab(sheetNames[sheetIndex], pane);
}
ExcelWorkbookSelection selection = new ExcelWorkbookSelection(configuration.getSheet(),
configuration.getColumnOffset(), configuration.getRowOffset(),
configuration.getColumnLast(), configuration.getRowLast());
setSelection(selection);
} catch (InvalidFormatException | BiffException | IOException | OperatorException
| ParseException e) {
ImportWizardUtils.showErrorMessage(configuration.getResourceName(), e.toString(), e);
} finally {
getProgressListener().complete();
}
}
});
}
}.start();
}
public void setSelection(ExcelWorkbookSelection selection) {
final int sheetIndex = selection.getSheetIndex();
if (sheetIndex < sheetsPane.getTabCount()) {
sheetsPane.setSelectedIndex(sheetIndex);
if (tables.length > sheetIndex) {
tables[sheetIndex].clearSelection();
boolean noColumns = tables[sheetIndex].getColumnCount() == 0;
boolean noRows = tables[sheetIndex].getRowCount() == 0;
if (!noRows && !noColumns) {
tables[sheetIndex].setColumnSelectionInterval(Math.max(selection.getColumnIndexStart(), 0), Math
.min(selection.getColumnIndexEnd(), noColumns ? 0 : tables[sheetIndex].getColumnCount() - 1));
tables[sheetIndex].setRowSelectionInterval(Math.max(selection.getRowIndexStart(), 0),
Math.min(selection.getRowIndexEnd(), noRows ? 0 : tables[sheetIndex].getRowCount() - 1));
}
}
}
}
/**
* @return the user selection of the range to be imported. Can be <code>null</code> in case no
* table was selected yet
*/
public ExcelWorkbookSelection getSelection() {
ExtendedJTable selectedTable = getSelectedTable();
if (selectedTable == null) {
return null;
}
int columnIndexStart = selectedTable.getSelectedColumn();
int rowIndexStart = selectedTable.getSelectedRow();
int columnIndexEnd = columnIndexStart + selectedTable.getSelectedColumnCount() - 1;
int rowIndexEnd = rowIndexStart + selectedTable.getSelectedRowCount() - 1;
if (columnIndexStart == -1) {
// then use complete selected table
int rowCount = selectedTable.getRowCount();
int columnCount = selectedTable.getColumnCount();
return new ExcelWorkbookSelection(sheetsPane.getSelectedIndex(), 0, 0, columnCount - 1, rowCount - 1);
} else {
return new ExcelWorkbookSelection(sheetsPane.getSelectedIndex(), columnIndexStart, rowIndexStart, columnIndexEnd,
rowIndexEnd);
}
}
/**
* @return the selected table or null
*/
ExtendedJTable getSelectedTable() {
int sheetIndex = sheetsPane.getSelectedIndex();
if (tables == null || sheetIndex >= tables.length || sheetIndex < 0) {
return null;
}
return tables[sheetIndex];
}
/**
* @return whether the wizard step can proceed. It cannot proceed if the selected table does not
* contain any columns.
*/
boolean canProceed() {
ExtendedJTable selectedTable = getSelectedTable();
return selectedTable != null ? selectedTable.getModel().getColumnCount() > 0 : false;
}
/**
* @return the tabbed sheet pane
*/
public JTabbedPane getSheetTabbedPane() {
return sheetsPane;
}
}