package org.geogebra.desktop.gui.view.spreadsheet;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map.Entry;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.ScrollPaneConstants;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import org.geogebra.common.awt.GPoint;
import org.geogebra.common.gui.view.spreadsheet.CellRange;
import org.geogebra.common.gui.view.spreadsheet.MyTableInterface;
import org.geogebra.common.gui.view.spreadsheet.SpreadsheetViewInterface;
import org.geogebra.common.kernel.Kernel;
import org.geogebra.common.kernel.ModeSetter;
import org.geogebra.common.kernel.geos.GProperty;
import org.geogebra.common.kernel.geos.GeoElement;
import org.geogebra.common.kernel.geos.GeoElementSpreadsheet;
import org.geogebra.common.main.App;
import org.geogebra.common.main.settings.AbstractSettings;
import org.geogebra.common.main.settings.SettingListener;
import org.geogebra.common.main.settings.SpreadsheetSettings;
import org.geogebra.desktop.awt.GDimensionD;
import org.geogebra.desktop.gui.inputfield.MyTextFieldD;
import org.geogebra.desktop.gui.layout.LayoutD;
import org.geogebra.desktop.gui.view.Gridable;
import org.geogebra.desktop.main.AppD;
import org.geogebra.desktop.main.SpreadsheetTableModelD;
import org.geogebra.desktop.util.GuiResourcesD;
public class SpreadsheetViewD implements SpreadsheetViewInterface,
ComponentListener, FocusListener, Gridable, SettingListener {
// ggb fields
protected AppD app;
private Kernel kernel;
// spreadsheet gui components
private JPanel spreadsheetWrapper;
private MyTableD table;
protected SpreadsheetTableModelD tableModel;
private SpreadsheetRowHeaderD rowHeader;
private JTableHeader tableHeader;
// moved to kernel
// if these are increased above 32000, you need to change traceRow to an
// int[]
// public static int MAX_COLUMNS = 9999; // TODO make sure this is actually
// used
// public static int MAX_ROWS = 9999; // TODO make sure this is actually
// used
public static final int ROW_HEADER_WIDTH = 35; // wide enough for "9999"
// TODO: should traceDialog belong to the SpreadsheetTraceManager?
private TraceDialog traceDialog;
// button to launch trace dialog from upper left corner
private JButton btnTraceDialog;
// fields for split panel, stylebar
private JScrollPane spreadsheet;
private SpreadsheetStyleBar styleBar;
// toolbar manager
SpreadsheetToolbarManager toolbarManager;
// current toolbar mode
private int mode = -1;
private FormulaBar formulaBar;
private JPanel spreadsheetPanel;
/******************************************************
* Construct spreadsheet view.
*/
public SpreadsheetViewD(AppD app) {
this.app = app;
kernel = app.getKernel();
// Initialize settings and register listener
app.getSettings().getSpreadsheet().addListener(this);
createGUI();
spreadsheetWrapper.addFocusListener(this);
updateFonts();
attachView();
// Create tool bar manager to handle tool bar mode changes
toolbarManager = new SpreadsheetToolbarManager(app, this);
SpreadsheetViewDnD.get(app, this);
settingsChanged(settings());
}
private void createGUI() {
spreadsheetWrapper = new JPanel();
// Build the spreadsheet table and enclosing scrollpane
buildSpreadsheet();
// Build the spreadsheet panel: formulaBar above, spreadsheet in Center
spreadsheetPanel = new JPanel(new BorderLayout());
spreadsheetPanel.add(spreadsheet, BorderLayout.CENTER);
spreadsheetWrapper.setLayout(new BorderLayout());
spreadsheetWrapper.add(spreadsheetPanel, BorderLayout.CENTER);
spreadsheetWrapper.setBorder(BorderFactory.createEmptyBorder());
}
private void buildSpreadsheet() {
// Create the spreadsheet table model and the table
tableModel = (SpreadsheetTableModelD) app.getSpreadsheetTableModel();
table = new MyTableD(this, tableModel.getDefaultTableModel());
// Create row header
rowHeader = new SpreadsheetRowHeaderD(app, table);
// Set column width
table.headerRenderer
.setPreferredSize(new Dimension((table.preferredColumnWidth),
(SpreadsheetSettings.TABLE_CELL_HEIGHT)));
// Put the table and the row header into a scroll plane
// The scrollPane is named as spreadsheet
spreadsheet = new JScrollPane();
spreadsheet.setBorder(BorderFactory.createEmptyBorder());
spreadsheet.setRowHeaderView(rowHeader);
spreadsheet.setViewportView(table);
// save the table header
tableHeader = table.getTableHeader();
// Create and set the scrollpane corners
spreadsheet.setCorner(ScrollPaneConstants.UPPER_LEFT_CORNER,
newUpperLeftCorner());
spreadsheet.setCorner(ScrollPaneConstants.LOWER_LEFT_CORNER,
new Corner());
spreadsheet.setCorner(ScrollPaneConstants.UPPER_RIGHT_CORNER,
new Corner());
// Add a resize listener to the table so it can auto-enlarge if needed
table.addComponentListener(this);
}
// ===============================================================
// Corners
// ===============================================================
private static class Corner extends JComponent {
private static final long serialVersionUID = -4426785169061557674L;
@Override
protected void paintComponent(Graphics g) {
g.setColor(MyTableD.BACKGROUND_COLOR_HEADER);
g.fillRect(0, 0, getWidth(), getHeight());
}
}
@SuppressWarnings("serial")
private Corner newUpperLeftCorner() {
Corner upperLeftCorner = new Corner(); // use FlowLayout
upperLeftCorner.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createMatteBorder(0, 0, 1, 1,
MyTableD.HEADER_GRID_COLOR),
BorderFactory.createEmptyBorder(0, 5, 0, 0)));
upperLeftCorner.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
table.selectAll();
}
});
// add trace dialog button
btnTraceDialog = new JButton(
app.getScaledIcon(GuiResourcesD.SPREADSHEETTRACE_BUTTON));
btnTraceDialog.setBorderPainted(false);
btnTraceDialog.setPreferredSize(new Dimension(18, 18));
btnTraceDialog.setContentAreaFilled(false);
// invisible button unless a trace is set
btnTraceDialog.setVisible(false);
btnTraceDialog.setToolTipText(
app.getLocalization().getMenuTooltip("TraceToSpreadsheet"));
btnTraceDialog.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
showTraceDialog(null, table.selectedCellRanges.get(0));
}
});
upperLeftCorner.setLayout(new BorderLayout());
upperLeftCorner.add(btnTraceDialog, BorderLayout.WEST);
return upperLeftCorner;
}
// ===============================================================
// Defaults
// ===============================================================
public void setDefaultSelection() {
setSpreadsheetScrollPosition(0, 0);
table.setInitialCellSelection(0, 0);
}
// ===============================================================
// getters/setters
// ===============================================================
@Override
public AppD getApplication() {
return app;
}
@Override
public MyTableInterface getSpreadsheetTable() {
return table;
}
public JViewport getRowHeader() {
return spreadsheet.getRowHeader();
}
@Override
public void rowHeaderRevalidate() {
spreadsheet.getRowHeader().revalidate();
}
public JViewport getColumnHeader() {
return spreadsheet.getColumnHeader();
}
@Override
public void columnHeaderRevalidate() {
spreadsheet.getColumnHeader().revalidate();
}
public JTableHeader getTableHeader() {
return tableHeader;
}
@Override
public int getMode() {
return mode;
}
/**
* get spreadsheet styleBar
*/
public SpreadsheetStyleBar getSpreadsheetStyleBar() {
if (styleBar == null) {
styleBar = new SpreadsheetStyleBar(this);
}
return styleBar;
}
/**
* @return panel that contains the entire spreadsheet GUI
*/
public JComponent getContainerPanel() {
return spreadsheetWrapper;
}
// ===============================================================
// VIEW Implementation
// ===============================================================
public void attachView() {
// clearView();
kernel.notifyAddAll(this);
kernel.attach(this);
}
public void detachView() {
kernel.detach(this);
// clearView();
// kernel.notifyRemoveAll(this);
}
@Override
public void add(GeoElement geo) {
// Application.debug(new Date() + " ADD: " + geo);
update(geo);
scrollIfNeeded(geo, null);
}
@Override
public void scrollIfNeeded(GeoElement geo, String labelNew) {
GPoint location = geo.getSpreadsheetCoords();
if (labelNew != null && location == null) {
location = GeoElementSpreadsheet.spreadsheetIndices(labelNew);
}
if (location == null || (location.x == -1 && location.y == -1)) {
return;
}
// autoscroll to new cell's location
if (scrollToShow) {
table.scrollRectToVisible(
table.getCellRect(location.y, location.x, true));
}
}
@Override
public void remove(GeoElement geo) {
// Application.debug(new Date() + " REMOVE: " + geo);
if (app.getTraceManager().isTraceGeo(geo)) {
app.getTraceManager().removeSpreadsheetTraceGeo(geo);
if (isTraceDialogVisible()) {
traceDialog.updateTraceDialog();
}
}
GPoint location = geo.getSpreadsheetCoords();
switch (geo.getGeoClassType()) {
default:
// do nothing
break;
case BOOLEAN:
case BUTTON:
case LIST:
table.oneClickEditMap.remove(location);
}
}
@Override
public void rename(GeoElement geo) {
/*
* if(app.getTraceManager().isTraceGeo(geo))
* app.getTraceManager().updateTraceSettings(geo);
*/
if (isTraceDialogVisible()) {
traceDialog.updateTraceDialog();
}
}
@Override
public void updateAuxiliaryObject(GeoElement geo) {
// ignore
}
@Override
public void repaintView() {
btnTraceDialog.setVisible(app.hasGeoTraced());
spreadsheetWrapper.repaint();
}
@Override
public void clearView() {
// moved to restart to fix GGB-1038
// // restore defaults;
// app.getSettings().restoreDefaultSpreadsheetSettings();
setDefaultSelection();
table.oneClickEditMap.clear();
tableModel.clearView();
}
/** Respond to changes in mode sent by GUI manager */
@Override
public void setMode(int mode, ModeSetter m) {
this.mode = mode;
if (isTraceDialogVisible()) {
traceDialog.toolbarModeChanged(mode);
}
// String command = kernel.getModeText(mode); // e.g. "Derivative"
toolbarManager.handleModeChange(mode);
}
/**
* Clear table and set to default layout. This method is called on startup
* or when new window is called
*/
public void restart() {
// moved here because of GGB-1038
app.getSettings().restoreDefaultSpreadsheetSettings();
clearView();
tableModel.clearView();
updateColumnWidths();
updateFonts();
app.getTraceManager().loadTraceGeoCollection();
table.oneClickEditMap.clear();
// clear the formats and call settingsChanged
settings().setCellFormat(null);
}
/** Resets spreadsheet after undo/redo call. */
@Override
public void reset() {
if (app.getTraceManager() != null) {
app.getTraceManager().loadTraceGeoCollection();
}
}
@Override
public void update(GeoElement geo) {
GPoint location = geo.getSpreadsheetCoords();
if (location != null
&& location.x < app.getMaxSpreadsheetColumnsVisible()
&& location.y < app.getMaxSpreadsheetRowsVisible()) {
// TODO: rowHeader and column
// changes should be handled by a table model listener
if (location.y >= tableModel.getRowCount()) {
// tableModel.setRowCount(location.y + 1);
spreadsheet.getRowHeader().revalidate();
}
if (location.x >= tableModel.getColumnCount()) {
tableModel.setColumnCount(location.x + 1);
JViewport cH = spreadsheet.getColumnHeader();
// bugfix: double-click to load ggb file gives cH = null
if (cH != null) {
cH.revalidate();
}
}
// Mark this cell to be resized by height
table.cellResizeHeightSet.add(new GPoint(location.x, location.y));
// put geos with special editors in the oneClickEditMap
if (geo.isGeoBoolean() || geo.isGeoButton() || geo.isGeoList()) {
table.oneClickEditMap.put(location, geo);
}
}
}
@Override
final public void updateVisualStyle(GeoElement geo, GProperty prop) {
update(geo);
}
@Override
public void updatePreviewFromInputBar(GeoElement[] geos) {
// TODO
}
@Override
public boolean isShowing() {
return spreadsheetWrapper.isShowing();
}
private boolean scrollToShow = false;
public void setScrollToShow(boolean scrollToShow) {
this.scrollToShow = scrollToShow;
}
// =====================================================
// Formula Bar
// =====================================================
public FormulaBar getFormulaBar() {
if (formulaBar == null) {
// Build the formula bar
formulaBar = new FormulaBar(app, this);
formulaBar.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createMatteBorder(0, 0, 1, 0,
SystemColor.controlShadow),
BorderFactory.createEmptyBorder(4, 4, 4, 4)));
}
return formulaBar;
}
public void updateFormulaBar() {
if (formulaBar != null && settings().showFormulaBar()) {
formulaBar.update();
}
}
// =====================================================
// Tracing
// =====================================================
@Override
public void showTraceDialog(GeoElement geo, CellRange traceCell) {
if (traceDialog == null) {
traceDialog = new TraceDialog(app, geo, traceCell);
} else {
traceDialog.setTraceDialogSelection(geo, traceCell);
}
traceDialog.setVisible(true);
}
public boolean isTraceDialogVisible() {
return (traceDialog != null && traceDialog.isVisible());
}
public CellRange getTraceSelectionRange(int anchorColumn, int anchorRow) {
if (traceDialog == null) {
return null;
}
return traceDialog.getTraceSelectionRange(anchorColumn, anchorRow);
}
public void setTraceDialogMode(boolean enableMode) {
if (enableMode) {
table.setSelectionRectangleColor(Color.GRAY);
// table.setFocusable(false);
} else {
table.setSelectionRectangleColor(MyTableD.SELECTED_RECTANGLE_COLOR);
// table.setFocusable(true);
}
}
// ===============================================================
// XML
// ===============================================================
// ===============================================================
// Update
// ===============================================================
public void setLabels() {
if (traceDialog != null) {
traceDialog.setLabels();
}
if (table != null) {
table.setLabels();
}
if (formulaBar != null) {
formulaBar.setLabels();
}
btnTraceDialog.setToolTipText(
app.getLocalization().getMenuTooltip("TraceToSpreadsheet"));
}
public void updateFonts() {
Font font = app.getPlainFont();
MyTextFieldD dummy = new MyTextFieldD(app);
dummy.setFont(font);
dummy.setText("9999"); // for row header width
int h = dummy.getPreferredSize().height;
int w = dummy.getPreferredSize().width;
rowHeader.setFixedCellWidth(w);
// TODO: column widths are not set from here
// need to revise updateColumnWidths() to do this correctly
dummy.setText("MMMMMMMMMM"); // for column width
h = dummy.getPreferredSize().height;
w = dummy.getPreferredSize().width;
table.setRowHeight(h);
table.setPreferredColumnWidth(w);
table.headerRenderer.setPreferredSize(new Dimension(w, h));
table.setFont(app.getPlainFont());
table.headerRenderer.setFont(font);
// Adjust row heights for tall LaTeX images
table.fitAll(true, false);
if (formulaBar != null) {
formulaBar.updateFonts(font);
}
if (styleBar != null) {
styleBar.reinit();
}
}
public void setColumnWidth(int col, int width) {
// Application.debug("col = "+col+" width = "+width);
TableColumn column = table.getColumnModel().getColumn(col);
column.setPreferredWidth(width);
// column.
}
public void setRowHeight(int row, int height) {
table.setRowHeight(row, height);
}
public void updateColumnWidths() {
Font font = app.getPlainFont();
int size = font.getSize();
if (size < 12) {
size = 12; // minimum size
}
double multiplier = (size) / 12.0;
table.setPreferredColumnWidth(
(int) (SpreadsheetSettings.TABLE_CELL_WIDTH * multiplier));
for (int i = 0; i < table.getColumnCount(); ++i) {
table.getColumnModel().getColumn(i)
.setPreferredWidth(table.preferredColumnWidth());
}
}
public void setColumnWidthsFromSettings() {
table.setPreferredColumnWidth(settings().preferredColumnWidth());
HashMap<Integer, Integer> widthMap = settings().getWidthMap();
for (int i = 0; i < table.getColumnCount(); ++i) {
if (widthMap.containsKey(i)) {
table.getColumnModel().getColumn(i)
.setPreferredWidth(widthMap.get(i));
} else {
table.getColumnModel().getColumn(i)
.setPreferredWidth(table.preferredColumnWidth());
}
}
}
public void setRowHeightsFromSettings() {
HashMap<Integer, Integer> heightMap = app.getSettings().getSpreadsheet()
.getHeightMap();
table.setRowHeight(
app.getSettings().getSpreadsheet().preferredRowHeight());
if (!heightMap.isEmpty()) {
for (Entry<Integer, Integer> entry : heightMap.entrySet()) {
Integer r = entry.getKey();
table.setRowHeight(r, entry.getValue());
}
}
}
public void updateRowHeader() {
if (rowHeader != null) {
rowHeader.updateRowHeader();
}
}
public void setSpreadsheetScrollPosition(int hScroll, int vScroll) {
spreadsheet.getHorizontalScrollBar().setValue(hScroll);
spreadsheet.getVerticalScrollBar().setValue(vScroll);
settings().setHScrollBalValue(hScroll);
settings().setVScrollBalValue(vScroll);
}
// ==========================================================
// Handle spreadsheet resize.
//
// Adds extra rows and columns to fill the enclosing scrollpane.
// This is sometimes needed when rows or columns are resized
// or the application window is enlarged.
/**
* Tests if the spreadsheet fits the enclosing scrollpane viewport. Adds
* rows or columns if needed to fill the viewport.
*/
public void expandSpreadsheetToViewport() {
if (table.getWidth() < spreadsheet.getWidth()) {
int newColumns = (spreadsheet.getWidth() - table.getWidth())
/ table.preferredColumnWidth();
table.removeComponentListener(this);
tableModel.setColumnCount(table.getColumnCount() + newColumns);
table.addComponentListener(this);
}
if (table.getHeight() < spreadsheet.getHeight()) {
int newRows = (spreadsheet.getHeight() - table.getHeight())
/ table.getRowHeight();
table.removeComponentListener(this);
tableModel.setRowCount(table.getRowCount() + newRows);
table.addComponentListener(this);
}
// if table has grown after resizing all rows or columns, then select
// all again
// TODO --- why doesn't this work:
/*
* if(table.isSelectAll()){ table.selectAll(); }
*/
}
// Listener for a resized column or row
@Override
public void componentResized(ComponentEvent e) {
expandSpreadsheetToViewport();
}
@Override
public void componentHidden(ComponentEvent e) {
// only resize
}
@Override
public void componentMoved(ComponentEvent e) {
// only resize
}
@Override
public void componentShown(ComponentEvent e) {
// only resize
}
// ===============================================================
// Data Import
// ===============================================================
public boolean loadSpreadsheetFromURL(File f) {
boolean succ = false;
URL url = null;
try {
url = f.toURI().toURL();
succ = loadSpreadsheetFromURL(url);
}
catch (IOException ex) {
ex.printStackTrace();
}
return succ;
}
public boolean loadSpreadsheetFromURL(URL url) {
boolean succ = table.copyPasteCut.pasteFromURL(url);
if (succ) {
app.storeUndoInfo();
}
return succ;
}
// ================================================
// Spreadsheet Settings
// ================================================
public void setEnableAutoComplete(boolean enableAutoComplete) {
table.setEnableAutoComplete(enableAutoComplete);
}
public void setShowRowHeader(boolean showRowHeader) {
if (showRowHeader) {
spreadsheet.setRowHeaderView(rowHeader);
} else {
spreadsheet.setRowHeaderView(null);
}
}
public void setShowColumnHeader(boolean showColumnHeader) {
if (showColumnHeader) {
table.setTableHeader(tableHeader);
spreadsheet.setColumnHeaderView(tableHeader);
} else {
table.setTableHeader(null);
spreadsheet.setColumnHeaderView(null);
}
}
public void setShowVScrollBar(boolean showVScrollBar) {
if (showVScrollBar) {
spreadsheet.setVerticalScrollBarPolicy(
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
} else {
spreadsheet.setVerticalScrollBarPolicy(
ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
}
}
public void setShowHScrollBar(boolean showHScrollBar) {
if (showHScrollBar) {
spreadsheet.setHorizontalScrollBarPolicy(
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
} else {
spreadsheet.setHorizontalScrollBarPolicy(
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
}
}
public void setShowGrid(boolean showGrid) {
table.setShowGrid(showGrid);
if (showGrid) {
table.setIntercellSpacing(new Dimension(1, 1));
} else {
table.setIntercellSpacing(new Dimension(0, 0));
}
getSpreadsheetStyleBar().updateStyleBar();
}
public boolean getAllowToolTips() {
return settings().allowToolTips();
}
public void setAllowToolTips(boolean allowToolTips) {
// do nothing yet
}
public void setShowFormulaBar(boolean showFormulaBar) {
if (showFormulaBar) {
spreadsheetPanel.add(getFormulaBar(), BorderLayout.NORTH);
} else if (formulaBar != null) {
spreadsheetPanel.remove(formulaBar);
}
if (formulaBar != null) {
formulaBar.update();
}
spreadsheetWrapper.revalidate();
spreadsheetWrapper.repaint();
getSpreadsheetStyleBar().updateStyleBar();
}
public boolean getShowFormulaBar() {
return settings().showFormulaBar();
}
public boolean isVisibleStyleBar() {
return styleBar == null || styleBar.isVisible();
}
public void setColumnSelect(boolean isColumnSelect) {
// do nothing yet
}
public boolean isColumnSelect() {
return settings().isColumnSelect();
}
public void setAllowSpecialEditor(boolean allowSpecialEditor) {
spreadsheetWrapper.repaint();
}
public boolean allowSpecialEditor() {
return settings().allowSpecialEditor();
}
/**
* sets requirement that commands entered into cells must start with "="
*/
public void setEqualsRequired(boolean isEqualsRequired) {
table.setEqualsRequired(isEqualsRequired);
}
/**
* gets requirement that commands entered into cells must start with "="
*/
public boolean isEqualsRequired() {
return settings().equalsRequired();
}
boolean allowSettingUpdate = true;
@Override
public void updateCellFormat(String cellFormat) {
if (!allowSettingUpdate) {
return;
}
settings().removeListener(this);
settings().setCellFormat(cellFormat);
settings().addListener(this);
}
protected void updateAllRowSettings() {
if (!allowSettingUpdate) {
return;
}
settings().removeListener(this);
settings().setPreferredRowHeight(table.getRowHeight());
settings().getHeightMap().clear();
for (int row = 0; row < table.getRowCount(); row++) {
int rowHeight = table.getRowHeight(row);
if (rowHeight != table.getRowHeight()) {
settings().getHeightMap().put(row, rowHeight);
}
}
settings().addListener(this);
}
protected void updateRowHeightSetting(int row, int height) {
if (!allowSettingUpdate) {
return;
}
settings().removeListener(this);
settings().getHeightMap().put(row, height);
settings().addListener(this);
}
protected void updatePreferredRowHeight(int preferredRowHeight) {
if (!allowSettingUpdate) {
return;
}
settings().removeListener(this);
settings().getHeightMap().clear();
settings().setPreferredRowHeight(preferredRowHeight);
settings().addListener(this);
}
protected void updateColumnWidth(int col, int colWidth) {
if (!allowSettingUpdate) {
return;
}
settings().removeListener(this);
settings().getWidthMap().put(col, colWidth);
settings().addListener(this);
}
protected void updatePreferredColumnWidth(int colWidth) {
if (!allowSettingUpdate) {
return;
}
settings().removeListener(this);
settings().getWidthMap().clear();
settings().setPreferredColumnWidth(table.preferredColumnWidth);
settings().addListener(this);
}
protected void updateAllColumnWidthSettings() {
if (!allowSettingUpdate) {
return;
}
settings().removeListener(this);
settings().setPreferredColumnWidth(table.preferredColumnWidth);
settings().getWidthMap().clear();
for (int col = 0; col < table.getColumnCount(); col++) {
TableColumn column = table.getColumnModel().getColumn(col);
int colWidth = column.getWidth();
if (colWidth != table.preferredColumnWidth) {
settings().getWidthMap().put(col, colWidth);
}
}
settings().addListener(this);
}
protected SpreadsheetSettings settings() {
return app.getSettings().getSpreadsheet();
}
@Override
public void settingsChanged(AbstractSettings settings0) {
allowSettingUpdate = false;
// layout
setShowColumnHeader(settings().showColumnHeader());
setShowRowHeader(settings().showRowHeader());
setShowVScrollBar(settings().showVScrollBar());
setShowHScrollBar(settings().showHScrollBar());
setShowGrid(settings().showGrid());
setAllowToolTips(settings().allowToolTips());
setShowFormulaBar(settings().showFormulaBar());
setColumnSelect(settings().isColumnSelect());
setAllowSpecialEditor(settings().allowSpecialEditor());
setEqualsRequired(settings().equalsRequired());
setEnableAutoComplete(settings().isEnableAutoComplete());
// row height and column widths
setColumnWidthsFromSettings();
setRowHeightsFromSettings();
// cell format
getSpreadsheetTable().getCellFormatHandler()
.processXMLString(settings().cellFormat());
// preferredSize
spreadsheetWrapper.setPreferredSize(
GDimensionD.getAWTDimension(settings().preferredSize()));
// initial position
// TODO not working yet ...
// setSpreadsheetScrollPosition(settings.scrollPosition().x,
// settings.scrollPosition().y);
// getTable().setInitialCellSelection(settings.selectedCell().x,
// settings.selectedCell().y);
allowSettingUpdate = true;
}
// ================================================
// Focus
// ================================================
protected boolean hasViewFocus() {
boolean hasFocus = false;
try {
if (((LayoutD) app.getGuiManager().getLayout()).getDockManager()
.getFocusedPanel() != null) {
hasFocus = ((LayoutD) app.getGuiManager().getLayout())
.getDockManager().getFocusedPanel()
.isAncestorOf(spreadsheetWrapper);
}
} catch (Exception e) {
e.printStackTrace();
}
return hasFocus;
}
// transfer focus to the table
public void requestFocus() {
if (table != null) {
table.requestFocus();
}
}
// test all components of SpreadsheetView for hasFocus
@Override
public boolean hasFocus() {
if (table == null) {
return false;
}
return table.hasFocus() || rowHeader.hasFocus()
|| (table.getTableHeader() != null
&& table.getTableHeader().hasFocus())
|| spreadsheet.getCorner(ScrollPaneConstants.UPPER_LEFT_CORNER)
.hasFocus()
|| (formulaBar != null && formulaBar.hasFocus());
}
@Override
public void focusGained(FocusEvent arg0) {
// only handle focus lost
}
@Override
public void focusLost(FocusEvent arg0) {
getSpreadsheetTable().repaint();
}
@Override
public int getViewID() {
return App.VIEW_SPREADSHEET;
}
@Override
public int[] getGridColwidths() {
int[] colWidths = new int[2 + tableModel.getHighestUsedColumn()];
colWidths[0] = rowHeader.getWidth();
for (int c = 0; c <= tableModel.getHighestUsedColumn(); c++) {
colWidths[c + 1] = table.getColumnModel().getColumn(c).getWidth();
}
return colWidths;
}
@Override
public int[] getGridRowHeights() {
int[] rowHeights = new int[2 + tableModel.getHighestUsedRow()];
if (table.getTableHeader() == null) {
rowHeights[0] = 0;
} else {
rowHeights[0] = table.getTableHeader().getHeight();
}
for (int r = 0; r <= tableModel.getHighestUsedRow(); r++) {
rowHeights[r + 1] = table.getRowHeight(r);
}
return rowHeights;
}
@Override
public Component[][] getPrintComponents() {
return new Component[][] {
{ spreadsheet.getCorner(ScrollPaneConstants.UPPER_LEFT_CORNER),
spreadsheet.getColumnHeader() },
{ spreadsheet.getRowHeader(), table } };
}
@Override
public void startBatchUpdate() {
// TODO Auto-generated method stub
}
@Override
public void endBatchUpdate() {
// TODO Auto-generated method stub
}
public JComponent getViewContainer() {
return spreadsheetWrapper;
}
@Override
public boolean suggestRepaint() {
return false;
// only for web
}
@Override
public void setKeyboardEnabled(boolean enable) {
// only for web
}
}