package edu.ualberta.med.biobank.widgets.grids; import java.util.Map; import org.eclipse.core.runtime.Assert; import org.eclipse.swt.SWT; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import edu.ualberta.med.biobank.common.util.RowColPos; import edu.ualberta.med.biobank.model.ContainerType; import edu.ualberta.med.biobank.widgets.grids.cell.AbstractUICell; import edu.ualberta.med.biobank.widgets.grids.cell.UICellStatus; /** * Draw a grid according to specific parameters : total number of rows, total * number of columns, width and height of the cells */ public abstract class AbstractGridDisplay extends AbstractContainerDisplay { private int cellWidth = 60; private int cellHeight = 60; protected int gridWidth; protected int gridHeight; private int rows; private int columns; /** * Height used when legend in under the grid */ public static final int LEGEND_HEIGHT = 20; /** * width calculated when legend in under the grid */ protected int legendWidth; /** * Width used when legend is on the side of the grid */ public static final int LEGEND_WIDTH = 70; public boolean legendOnSide = false; @Override protected void paintGrid(PaintEvent e, ContainerDisplayWidget displayWidget) { for (int indexRow = 0; indexRow < rows; indexRow++) { for (int indexCol = 0; indexCol < columns; indexCol++) { int xPosition = cellWidth * indexCol; int yPosition = cellHeight * indexRow; Rectangle rectangle = new Rectangle(xPosition, yPosition, cellWidth, cellHeight); Color defaultColor = getDefaultBackgroundColor(e, displayWidget, rectangle, indexRow, indexCol); drawRectangle(e, displayWidget, rectangle, indexRow, indexCol, defaultColor); String topText = getTopTextForBox(displayWidget.getCells(), indexRow, indexCol); if (topText != null) { drawText(e, topText, rectangle, SWT.TOP); } String middleText = getMiddleTextForBox( displayWidget.getCells(), indexRow, indexCol); if (middleText != null) { drawText(e, middleText, rectangle, SWT.CENTER); } String bottomText = getBottomTextForBox( displayWidget.getCells(), indexRow, indexCol); if (bottomText != null) { drawText(e, bottomText, rectangle, SWT.BOTTOM); } } } if (legendStatus != null) { legendWidth = gridWidth / legendStatus.size(); for (int i = 0; i < legendStatus.size(); i++) { UICellStatus status = legendStatus.get(i); drawLegend(e, status.getColor(), i, status.getLegend()); } } } @Override public Point computeSize(int wHint, int hHint, boolean changed) { if (maxWidth != -1 && maxHeight != -1) { cellWidth = maxWidth / columns; cellHeight = maxHeight / rows; gridWidth = maxWidth; gridHeight = maxHeight; } else { gridWidth = cellWidth * columns; gridHeight = cellHeight * rows; } int width = gridWidth + 10; int height = gridHeight + 10; if (legendStatus != null) { if (legendOnSide) { width = width + LEGEND_WIDTH + 4; } else { height = height + LEGEND_HEIGHT + 4; } } return new Point(width, height); } // @Override // public void initLegend(List<UICellStatus> status) { // super.initLegend(status); // hasLegend = status != null && status.size() > 0; // } protected void drawRectangle(PaintEvent e, ContainerDisplayWidget displayWidget, Rectangle rectangle, int indexRow, int indexCol, Color defaultBackgroundColor) { Color backgroundColor = defaultBackgroundColor; if (displayWidget.getSelection() != null && displayWidget.getSelection().getRow() != null && displayWidget.getSelection().getRow() == indexRow && displayWidget.getSelection().getCol() != null && displayWidget.getSelection().getCol() == indexCol) { backgroundColor = e.display.getSystemColor(SWT.COLOR_YELLOW); } e.gc.setBackground(backgroundColor); e.gc.fillRectangle(rectangle); e.gc.setForeground(e.display.getSystemColor(SWT.COLOR_BLACK)); e.gc.drawRectangle(rectangle); if (displayWidget.getCells() != null) { if (displayWidget.getMultiSelectionManager().isEnabled()) { AbstractUICell cell = displayWidget.getCells().get( new RowColPos(indexRow, indexCol)); if (cell != null && cell.isSelected()) { Rectangle rect = new Rectangle(rectangle.x + 5, rectangle.y + 5, rectangle.width - 10, rectangle.height - 10); Color color = e.display.getSystemColor(SWT.COLOR_BLUE); e.gc.setForeground(color); e.gc.drawRectangle(rect); } } } e.gc.setForeground(e.display.getSystemColor(SWT.COLOR_BLACK)); } @SuppressWarnings("unused") protected Color getDefaultBackgroundColor(PaintEvent e, ContainerDisplayWidget displayWidget, Rectangle rectangle, int indexRow, int indexCol) { return UICellStatus.EMPTY.getColor(); } @SuppressWarnings("unused") protected String getTopTextForBox( Map<RowColPos, ? extends AbstractUICell> cells, int indexRow, int indexCol) { return null; } protected String getMiddleTextForBox( Map<RowColPos, ? extends AbstractUICell> cells, int indexRow, int indexCol) { return getDefaultTextForBox(cells, indexRow, indexCol); } @SuppressWarnings("unused") protected String getBottomTextForBox( Map<RowColPos, ? extends AbstractUICell> cells, int indexRow, int indexCol) { return null; } @Override public void setContainerType(ContainerType type) { super.setContainerType(type); Integer rowCap = containerType.getRowCapacity(); Integer colCap = containerType.getColCapacity(); Assert.isNotNull(rowCap, "row capacity is null"); //$NON-NLS-1$ Assert.isNotNull(colCap, "column capacity is null"); //$NON-NLS-1$ setStorageSize(rowCap, colCap); if (colCap <= 1) { // single dimension size setCellWidth(120); setCellHeight(20); setLegendOnSide(true); } } /** * Draw the text on the horizontal middle of the rectangle. Vertical * alignment depend on the verticalPosition parameter. */ private void drawText(PaintEvent e, String text, Rectangle rectangle, int verticalPosition) { Font oldFont = e.gc.getFont(); Font tmpFont = null; Point textSize = e.gc.textExtent(text); if (textSize.x > rectangle.width) { // Try to find a smallest font to see the whole text FontData fd = oldFont.getFontData()[0]; int height = fd.getHeight(); Point currentTextSize = textSize; while (currentTextSize.x > rectangle.width && height > 3) { if (tmpFont != null) { tmpFont.dispose(); } height--; FontData fd2 = new FontData(fd.getName(), height, fd.getStyle()); tmpFont = new Font(e.display, fd2); e.gc.setFont(tmpFont); currentTextSize = e.gc.textExtent(text); } if (height > 3) { textSize = currentTextSize; } else { e.gc.setFont(oldFont); } } int xTextPosition = (rectangle.width - textSize.x) / 2 + rectangle.x; int yTextPosition = 0; switch (verticalPosition) { case SWT.CENTER: yTextPosition = (rectangle.height - textSize.y) / 2 + rectangle.y; break; case SWT.TOP: yTextPosition = rectangle.y + 3; break; case SWT.BOTTOM: yTextPosition = rectangle.y + rectangle.height - textSize.y - 3; } e.gc.drawText(text, xTextPosition, yTextPosition, true); e.gc.setFont(oldFont); if (tmpFont != null) { tmpFont.dispose(); } } protected void drawLegend(PaintEvent e, Color color, int index, String text) { e.gc.setBackground(color); int width = legendWidth; int startx = legendWidth * index; int starty = gridHeight + 4; if (legendOnSide) { width = LEGEND_WIDTH; startx = gridWidth + 4; starty = LEGEND_HEIGHT * index; } Rectangle rectangle = new Rectangle(startx, starty, width, LEGEND_HEIGHT); e.gc.fillRectangle(rectangle); e.gc.drawRectangle(rectangle); drawText(e, text, rectangle, SWT.CENTER); } /** * Modify only the number of rows and columns of the grid. If no max width * and max height has been given to the grid, the default cell width and * cell height will be used */ @Override public void setStorageSize(int rows, int columns) { this.rows = rows; this.columns = columns; } public int getCellWidth() { return cellWidth; } public void setCellWidth(int cellWidth) { this.cellWidth = cellWidth; } public int getCellHeight() { return cellHeight; } public void setCellHeight(int cellHeight) { this.cellHeight = cellHeight; } public void setLegendOnSide(boolean onSide) { this.legendOnSide = onSide; } public int getRows() { return rows; } public int getCols() { return columns; } @Override public RowColPos getPositionAtCoordinates(int x, int y) { int col = x / getCellWidth(); int row = y / getCellHeight(); if (col >= 0 && col < getCols() && row >= 0 && row < getRows()) { return new RowColPos(row, col); } return null; } }