package org.eclipse.iee.editor.core.pad.table.ui; import java.awt.Rectangle; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.List; import org.eclipse.draw2d.AbstractBorder; import org.eclipse.draw2d.Figure; import org.eclipse.draw2d.Graphics; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.MouseEvent; import org.eclipse.draw2d.MouseMotionListener; import org.eclipse.draw2d.RectangleFigure; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Insets; import org.eclipse.iee.editor.core.bindings.DefaultObservableValue; import org.eclipse.iee.editor.core.container.ITextEditor; import org.eclipse.iee.editor.core.pad.FigurePad; import org.eclipse.iee.editor.core.pad.common.text.IEditorLocation; import org.eclipse.iee.editor.core.pad.common.text.TextPartEditor; import org.eclipse.iee.editor.core.pad.table.TableCell; import org.eclipse.iee.editor.core.pad.table.TableColumn; import org.eclipse.iee.editor.core.pad.table.TablePart; import org.eclipse.swt.graphics.Color; import com.google.common.base.Optional; import com.google.common.collect.Lists; public class TablePad extends FigurePad<TablePart, IFigure> { private GridLayout fManager; private Figure fTable; private RectangleFigure fColumnHighlighter; private RectangleFigure fRowHighlighter; private List<TextPartEditor> cells = Lists.newArrayList(); private PropertyChangeListener fListener; public TablePad() { fListener = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if ("cells".equals(evt.getPropertyName()) || "columns".equals(evt.getPropertyName()) || "rows".equals(evt.getPropertyName())) { updateTable(fTable); getContainer().updateDocument(); } } }; } @Override public IFigure createFigure() { fTable = new Figure(); fTable.setMinimumSize(new Dimension(20, 20)); fManager = new GridLayout(); fManager.horizontalSpacing = 0; fManager.verticalSpacing = 0; fManager.marginHeight = 0; fManager.marginWidth = 0; fTable.setLayoutManager(fManager); fTable.setBorder(new TableFigureBorder()); fColumnHighlighter = new RectangleFigure(); fColumnHighlighter.setForegroundColor(new Color(null, 0, 255, 0)); fColumnHighlighter.setBounds(new org.eclipse.draw2d.geometry.Rectangle(10, 10, 10, 10)); fColumnHighlighter.setOpaque(false); fColumnHighlighter.setFill(false); fRowHighlighter = new RectangleFigure(); fRowHighlighter.setForegroundColor(new Color(null, 0, 255, 0)); fRowHighlighter.setBounds(new org.eclipse.draw2d.geometry.Rectangle(10, 10, 10, 10)); fRowHighlighter.setOpaque(false); fRowHighlighter.setFill(false); fTable.addMouseMotionListener(new MouseMotionListener.Stub() { @Override public void mouseMoved(MouseEvent me) { int column = getColumn(me.x); int row = getRow(me.y); if (column != -1 && row != -1) { enableHighlight(); org.eclipse.draw2d.geometry.Rectangle bounds = fTable.getBounds(); fColumnHighlighter.setBounds(new org.eclipse.draw2d.geometry.Rectangle(getColumnOffset(column), bounds.y, getColumnWidth(column), bounds.height)); fRowHighlighter.setBounds(new org.eclipse.draw2d.geometry.Rectangle(bounds.x, getRowOffset(row), bounds.width, getRowWidth(row))); } else { disableHighlight(); } } @Override public void mouseExited(MouseEvent me) { disableHighlight(); } private int getColumn(int x) { int[] columnWidths = fManager.getColumnWidths(); int offset = fTable.getLocation().x; for (int i = 0; i < columnWidths.length; i++) { int width = getColumnWidth(i); if (x >= offset && x < (offset + width)) { return i; } offset = offset + width; } return -1; } private int getColumnOffset(int column) { int offset = fTable.getLocation().x; for (int i = 0; i < column; i++) { offset += getColumnWidth(column); } return offset; } private int getColumnWidth(int column) { int columnWidth = fManager.getColumnWidths()[column]; return calcFullColumnWidth(fManager, columnWidth); } private int calcFullColumnWidth(final GridLayout manager, int columnWidth) { return columnWidth + manager.horizontalSpacing; } private int getRow(int y) { int[] rowHeights = fManager.getRowHeights(); int offset = fTable.getLocation().y; for (int i = 0; i < rowHeights.length; i++) { int height = getRowWidth(i); if (y >= offset && y < (offset + height)) { return i; } offset = offset + height; } return -1; } private int getRowOffset(int row) { int offset = fTable.getLocation().y; for (int i = 0; i < row; i++) { offset += getRowWidth(row); } return offset; } private int getRowWidth(int row) { int rowWidth = fManager.getRowHeights()[row]; return calcFullRowHeight(fManager, rowWidth); } private int calcFullRowHeight(final GridLayout manager, int rowWidth) { return rowWidth + manager.verticalSpacing; } }); updateTable(fTable); return fTable; } private void updateTable(final Figure table) { table.removeAll(); createHeader(table); createContent(table); } private void createContent(Figure table) { TablePart documentPart = getDocumentPart(); for (int i = 0; i < documentPart.getRowCount(); i++) { for (int j = 0; j < documentPart.getColumnCount(); j++) { TableCell cell = documentPart.getCell(i, j); TableCellEditor tableCellEditor = new TableCellEditor(); tableCellEditor.setValue(Optional.of(DefaultObservableValue.fromValue(cell))); addCellEditor(tableCellEditor); } } } private void addColumnEditor(TableColumnEditor tableColumnEditor) { addEditor(tableColumnEditor); IFigure figure = tableColumnEditor.getFigure(); fTable.add(figure, new GridData(GridData.FILL, GridData.FILL, true, true)); } private void addCellEditor(TableCellEditor tableCellEditor) { addEditor(tableCellEditor); IFigure figure = tableCellEditor.getFigure(); fTable.add(figure, new GridData(GridData.FILL, GridData.FILL, true, true)); } private void createHeader(Figure table) { TablePart documentPart = getDocumentPart(); List<TableColumn> columns = documentPart.getColumns(); fManager.numColumns = columns.size(); for (TableColumn column : columns) { createColumn(table, column); } if (columns.size() == 0) { createColumn(table, new TableColumn("TBD")); } } private void createColumn(Figure table, TableColumn column) { TableColumnEditor tableCellEditor = new TableColumnEditor(); tableCellEditor.setValue(Optional.of(DefaultObservableValue.fromValue(column))); addColumnEditor(tableCellEditor); } @Override public void activate() { // TODO Auto-generated method stub } @Override public void save() { } @Override public String getType() { return "TableInput"; } @Override public String getTex() { return ""; } public Rectangle getBounds() { org.eclipse.draw2d.geometry.Rectangle bounds = fTable.getBounds(); return new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height); } @Override public void setBounds(Rectangle bounds) { org.eclipse.draw2d.geometry.Rectangle d2dBounds = new org.eclipse.draw2d.geometry.Rectangle(bounds.x, bounds.y, bounds.width, bounds.height); fTable.setBounds(d2dBounds); getContainer().getMainFigure().setConstraint(fTable, new org.eclipse.draw2d.geometry.Rectangle(bounds.x, bounds.y, -1, -1)); updateSelectionBounds(bounds); } @Override public void setVisible(boolean isVisible) { fTable.setVisible(isVisible); } private void enableHighlight() { getFeedbackLayer().add(fColumnHighlighter); getFeedbackLayer().add(fRowHighlighter); } private void disableHighlight() { if (fColumnHighlighter.getParent() != null) { getFeedbackLayer().remove(fColumnHighlighter); } if (fRowHighlighter.getParent() != null) { getFeedbackLayer().remove(fRowHighlighter); } } private IFigure getFeedbackLayer() { return getContainer().getFeedbackFigure(); } public static class TableFigureBorder extends AbstractBorder { public Insets getInsets(IFigure figure) { return new Insets(1, 1, 0, 0); } public void paint(IFigure figure, Graphics graphics, Insets insets) { org.eclipse.draw2d.geometry.Rectangle paintRectangle = getPaintRectangle(figure, insets); graphics.drawLine(paintRectangle.getTopLeft(), paintRectangle.getBottomLeft()); graphics.drawLine(paintRectangle.getTopLeft(), paintRectangle.getTopRight()); } } public static class CellFigureBorder extends AbstractBorder { public Insets getInsets(IFigure figure) { return new Insets(0, 0, 1, 1); } public void paint(IFigure figure, Graphics graphics, Insets insets) { org.eclipse.draw2d.geometry.Rectangle paintRectangle = getPaintRectangle(figure, insets); graphics.drawLine(paintRectangle.getTopRight().getTranslated(-1, 0), paintRectangle.getBottomRight().getTranslated(-1, 0)); graphics.drawLine(paintRectangle.getBottomLeft().getTranslated(0, -1), paintRectangle.getBottomRight().getTranslated(0, -1)); } } // public TextLocation getStart() { // return cells.get(0).getStart(); // } // // public TextLocation getEnd() { // return cells.get(cells.size() - 1).getEnd(); // } @Override public Optional<IEditorLocation> getPrevious(ITextEditor<?> textPart) { int indexOf = cells.indexOf(textPart); return indexOf > 0 ? cells.get(indexOf - 1).getEnd() : Optional.<IEditorLocation> absent(); } @Override public Optional<IEditorLocation> getNext(ITextEditor<?> textPart) { int indexOf = cells.indexOf(textPart); return indexOf < cells.size() - 1 ? cells.get(indexOf + 1).getStart() : Optional.<IEditorLocation> absent(); } @Override public void dispose() { disableHighlight(); getModel().removePropertyChangeListener(fListener); getContainer().getMainFigure().remove(fTable); } @Override protected void doBindValue(TablePart value) { value.addPropertyChangeListener(fListener); } @Override protected void doUnbindValue(TablePart oldValue) { oldValue.removePropertyChangeListener(fListener); } }