blob: 8c2409738532702c93ec16dd15e719f8d5a7932c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Michael Scharf (Wind River) - initial API and implementation
* Anton Leherbauer (Wind River) - [294468] Fix scroller and text line rendering
*******************************************************************************/
package org.eclipse.tm.internal.terminal.textcanvas;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ScrollBar;
/**
* A Grid based Canvas. The canvas has rows and columns.
* CellPainting is done with the abstract method drawCell
*/
abstract public class GridCanvas extends VirtualCanvas {
/** width of a cell */
private int fCellWidth;
/** height of a cell */
private int fCellHeight;
public GridCanvas(Composite parent, int style) {
super(parent, style);
addListener(SWT.MouseWheel, new Listener() {
public void handleEvent(Event event) {
if(getVerticalBar().isVisible()) {
int delta=-fCellHeight;
if(event.count<0)
delta=-delta;
scrollYDelta(delta);
}
event.doit=false;
}
});
}
/** template method paint.
* iterates over all cells in the clipping rectangle and paints them.
*/
protected void paint(GC gc) {
Rectangle clipping=gc.getClipping();
if(clipping.width==0 || clipping.height==0)
return;
Rectangle clientArea= getScreenRectInVirtualSpace();
// Beginning coordinates
int xOffset=clientArea.x;
int yOffset=clientArea.y;
int colFirst=virtualXToCell(xOffset+clipping.x);
if(colFirst>getCols())
colFirst=getCols();
else if (colFirst < 0) {
colFirst = 0;
}
int rowFirst=virtualYToCell(yOffset+clipping.y);
// End coordinates
int colLast=virtualXToCell(xOffset+clipping.x+clipping.width+fCellWidth);
if(colLast>getCols())
colLast=getCols();
int rowLast=virtualYToCell(yOffset+clipping.y+clipping.height+fCellHeight);
if(rowLast>getRows())
rowLast=getRows();
// System.out.println(rowFirst+"->"+rowLast+" "+System.currentTimeMillis());
// draw the cells
for(int row=rowFirst;row<=rowLast;row++) {
int cx=colFirst*fCellWidth-xOffset;
int cy=row*fCellHeight-yOffset;
drawLine(gc,row,cx,cy,colFirst,colLast);
}
paintUnoccupiedSpace(gc,clipping);
}
/**
* @param gc
* @param row the line to draw
* @param x coordinate on screen
* @param y coordinate on screen
* @param colFirst first column to draw
* @param colLast last column to draw
*/
abstract void drawLine(GC gc, int row, int x, int y, int colFirst, int colLast);
abstract protected int getRows();
abstract protected int getCols();
protected void setCellWidth(int cellWidth) {
fCellWidth = cellWidth;
getHorizontalBar().setIncrement(fCellWidth);
}
public int getCellWidth() {
return fCellWidth;
}
protected void setCellHeight(int cellHeight) {
fCellHeight = cellHeight;
getVerticalBar().setIncrement(fCellHeight);
}
public int getCellHeight() {
return fCellHeight;
}
int virtualXToCell(int x) {
return x/fCellWidth;
}
int virtualYToCell(int y) {
return y/fCellHeight;
}
protected Point screenPointToCell(int x, int y) {
x=screenXtoVirtual(x)/fCellWidth;
y=screenYtoVirtual(y)/fCellHeight;
return new Point(x,y);
}
Point screenPointToCell(Point point) {
return screenPointToCell(point.x,point.y);
}
protected Point cellToOriginOnScreen(int x, int y) {
x=virtualXtoScreen(fCellWidth*x);
y=virtualYtoScreen(fCellHeight*y);
return new Point(x,y);
}
Point cellToOriginOnScreen(Point cell) {
return cellToOriginOnScreen(cell.x,cell.y);
}
Rectangle getCellScreenRect(Point cell) {
return getCellScreenRect(cell.x,cell.y);
}
Rectangle getCellScreenRect(int x, int y) {
x=fCellWidth*virtualXtoScreen(x);
y=fCellHeight*virtualYtoScreen(y);
return new Rectangle(x,y,fCellWidth,fCellHeight);
}
protected Rectangle getCellVirtualRect(Point cell) {
return getCellVirtualRect(cell.x,cell.y);
}
Rectangle getCellVirtualRect(int x, int y) {
x=fCellWidth*x;
y=fCellHeight*y;
return new Rectangle(x,y,fCellWidth,fCellHeight);
}
protected void viewRectangleChanged(int x, int y, int width, int height) {
int cellX=virtualXToCell(x);
int cellY=virtualYToCell(y);
// End coordinates
int xE=virtualXToCell(x+width);
// if(xE>getCols())
// xE=getCols();
int yE=virtualYToCell(y+height);
// if(yE>getRows())
// yE=getRows();
visibleCellRectangleChanged(cellX,cellY,xE-cellX,yE-cellY);
}
/**
* Called when the viewed part has changed.
* Override when you need this information....
* Is only called if the values change (well, almost)
* @param x origin of visible cells
* @param y origin of visible cells
* @param width number of cells visible in x direction
* @param height number of cells visible in y direction
*/
protected void visibleCellRectangleChanged(int x, int y, int width, int height) {
}
protected void setVirtualExtend(int width, int height) {
int cellHeight = getCellHeight();
if (cellHeight > 0) {
height -= height % cellHeight;
}
super.setVirtualExtend(width, height);
}
protected void setVirtualOrigin(int x, int y) {
int cellHeight = getCellHeight();
if (cellHeight > 0) {
int remainder = y % cellHeight;
if (remainder < 0) {
y -= (cellHeight + remainder);
} else {
y -= remainder;
}
}
super.setVirtualOrigin(x, y);
}
protected void scrollY(ScrollBar vBar) {
int vSelection = vBar.getSelection ();
Rectangle bounds = getVirtualBounds();
int y = -vSelection;
int cellHeight = getCellHeight();
if (cellHeight > 0) {
int remainder = y % cellHeight;
if (remainder < 0) {
y -= (cellHeight + remainder);
} else {
y -= remainder;
}
}
int deltaY = y - bounds.y;
if(deltaY!=0) {
scrollSmart(0,deltaY);
setVirtualOrigin(bounds.x, bounds.y += deltaY);
}
if (-bounds.y + getRows() * getCellHeight() >= bounds.height) {
// scrolled to bottom - need to redraw bottom area
Rectangle clientRect = getClientArea();
redraw(0, clientRect.height - fCellHeight, clientRect.width, fCellHeight, false);
}
}
}