FileDocCategorySizeDatePackage
BufferedGraphicTableItem2.javaAPI DocAzureus 3.0.3.411880Mon Jun 12 20:38:24 BST 2006org.gudy.azureus2.ui.swt.components

BufferedGraphicTableItem2

public abstract class BufferedGraphicTableItem2 extends BufferedTableItemImpl implements BufferedGraphicTableItem
Draws an image at a column in a row of a table using a Canvas. In comparison to BufferedGraphicTable, which uses direct paints to table, Pros: - Skip the table redrawing and overdrawing bugs in 3.0M8 (or greater?) Cons: - Lag - A lot more control is needed to do the same thing
see
BufferedGraphicTable
author
TuxPaper

Fields Summary
private int
marginHeight
private int
marginWidth
private int
orientation
org.eclipse.swt.widgets.Canvas
cBlockView
Canvas that image is drawn on
private org.eclipse.swt.graphics.Image
image
private org.eclipse.swt.graphics.Color
lastBackColor
Used for !fillCell
Constructors Summary
public BufferedGraphicTableItem2(org.gudy.azureus2.ui.swt.components.BufferedTableRow row, int position)

  
  
      
    super(row, position);
  
Methods Summary
private voidcreateBlockView()

    // For !fillCell, we draw the background manually, because some OSes
    // send a paint listener after setBackground() (causing another doPaint),
    // and some do not.
    int iStyle = SWT.NO_FOCUS | SWT.NO_BACKGROUND;
    if (orientation == SWT.FILL) {
      iStyle |= SWT.NO_REDRAW_RESIZE;
    }
    cBlockView = new Canvas(getTable(), iStyle);
    cBlockView.setBackground(null);
    cBlockView.addPaintListener(new PaintListener() {
    	public void paintControl(PaintEvent event) {
        if (event.width == 0 || event.height == 0)
          return;
    		doPaint(event.gc.getClipping());
    	}
    });
    //cBlockView.moveAbove(null);

    cBlockView.addMouseListener(new MouseAdapter() {
        public void mouseDown(MouseEvent e) {
          Table table = getTable();
          Rectangle r = cBlockView.getBounds();
          TableItem[] item = { table.getItem(new Point(r.x, r.y)) };
          if (item[0] != null) {
            table.setSelection(item);
          }
          table.setFocus();
        }
        public void mouseUp(MouseEvent e) {
          getTable().setFocus();
        }
      }
    );
  
public voiddispose()
Don't forget to call super.dispose()!

    super.dispose();
    image = null;
    if (cBlockView != null) {
      if (!cBlockView.isDisposed())
        cBlockView.dispose();
      cBlockView = null;
    }
  
public voiddoPaint(org.eclipse.swt.graphics.GC gc)
Inherited doPaint(GC) call. This is called when the Table needs repainting. Since we capture the Canvas' paint, most of the Table repainting can be ignored. Cases where the cell bounds or background color changed, however, require action.

    if (cBlockView == null || cBlockView.isDisposed())
      return;

    //Compute bounds ...
    Rectangle bounds = getBoundsForCanvas();
    //In case item isn't displayed bounds is null
    if (bounds == null || image == null || image.isDisposed()) {
      return;
    }
    Rectangle canvasBounds = cBlockView.getBounds();
    if (canvasBounds.x != bounds.x || canvasBounds.y != bounds.y) {
      //cBlockView.moveAbove(null);
      cBlockView.setLocation(bounds.x, bounds.y);
      canvasBounds = cBlockView.getBounds();
      //debugOut("doPaint(GC): move cBlockView to " + bounds.x + "x" + bounds.y, false);
    }

    Table table = getTable();
    Rectangle tableBounds = table.getClientArea();
    if (tableBounds.y < table.getHeaderHeight()) {
      tableBounds.y = table.getHeaderHeight();
    }
    Rectangle rNewCanvas = bounds.intersection(tableBounds);
    //debugOut("doPaint(gc) rNewCanvas="+rNewCanvas+";canvasBounds="+canvasBounds+";tableBounds="+tableBounds, false);
    if (rNewCanvas.width <= 0 || rNewCanvas.height <= 0) {
      return;
    }
    if (!rNewCanvas.equals(canvasBounds) ||
        (orientation != SWT.FILL && !getRowBackground(table).equals(lastBackColor))) {
      rNewCanvas.x -= canvasBounds.x;
      rNewCanvas.y -= canvasBounds.y;
      doPaint(rNewCanvas);
    }
  
public voiddoPaint(org.eclipse.swt.graphics.Rectangle clipping)
Paint the bar without updating it's data. Unless the size changed.

    //debugOut("doPaint() clipping="+clipping, false);
    if (cBlockView == null || cBlockView.isDisposed())
      return;

    Table table = getTable();
    //Compute bounds ...
    Rectangle bounds = getBoundsForCanvas();
    //In case item isn't displayed bounds is null
    if (bounds == null || image == null || image.isDisposed()) {
      return;
    }
    
    Rectangle canvasBounds = cBlockView.getBounds();
    //debugOut("Block:"+canvasBounds+";cell:"+bounds,false);
    if (canvasBounds.x != bounds.x || canvasBounds.y != bounds.y) {
      //cBlockView.moveAbove(null);
      cBlockView.setLocation(bounds.x, bounds.y);
      canvasBounds = cBlockView.getBounds();
      //debugOut("doPaint(clipping): move cBlockView to " + bounds.x + "x" + bounds.y, false);
    }
    if (bounds.width != canvasBounds.width ||
        bounds.height != canvasBounds.height) {
      cBlockView.setSize(bounds.width, bounds.height);
      canvasBounds = cBlockView.getBounds();
    }
    //debugOut("doPaint()" + ((gc == null) ? "GC NULL" : String.valueOf(gc.getClipping())) + 
    //         "ta="+table.getClientArea()+";bounds="+bounds, false);
    
    if (orientation == SWT.FILL) {
      Rectangle imageBounds = image.getBounds();
      if (imageBounds.width != bounds.width ||
          imageBounds.height != bounds.height) {
        // Enable this for semi-fast visual update with some flicker
        cBlockView.setSize(bounds.width, bounds.height);
        GC gc = new GC(cBlockView);
        if (gc == null) {
          return;
        }
        gc.drawImage(image, 0, 0, imageBounds.width, imageBounds.height, 
                     0, 0, bounds.width, bounds.height);
        gc.dispose();
/*
        // _OR_ enable refresh() for slower visual update with lots of flicker
        //refresh();
        
        // OR, disable both and image will be updated on next graphic bar update
        
        // TODO: make config option to choose
*/
        invalidate();
        return;
      }
    }
    
    if (clipping == null) {
      clipping = new Rectangle(0, 0, bounds.width, bounds.height);
    }
    Rectangle tableBounds = table.getClientArea();
    if (tableBounds.y < table.getHeaderHeight()) {
      tableBounds.y = table.getHeaderHeight();
    }
    //debugOut("doPaint() tableBounds="+tableBounds+";canvasBounds="+canvasBounds+";clipping="+clipping, false);
    tableBounds.x -= canvasBounds.x;
    tableBounds.y -= canvasBounds.y;
    clipping = clipping.intersection(tableBounds);
    //debugOut("doPaint() clipping="+clipping, false);

    if (clipping.x + clipping.width <= 0 && clipping.y + clipping.height <= 0) {
      return;
    }
    

    GC gc = new GC(cBlockView);
    if (gc == null) {
      return;
    }
    if (orientation == SWT.FILL) {
      gc.setClipping(clipping);
      gc.drawImage(image, 0, 0);
    } else {
/*
      // Grab a pixel beside the cell and draw that as our background
      // Advantage: paints correct color when hilighted and not in focus
      // Disadvatage: doesn't always work!
      GC gc2 = new GC(table);
      Image i = new Image(table.getDisplay(), 1, 1);
      gc2.copyArea(i, bounds.x + bounds.width + 1, bounds.y + (bounds.width / 2));
      gc2.dispose();
      
      gc.drawImage(i, 0, 0, 1, 1, 
                   0,0, rBlockViewBounds.width, rBlockViewBounds.height);
*/      

      lastBackColor = getRowBackground(table);
      gc.setBackground(lastBackColor);
      gc.fillRectangle(clipping);
/*      
      Rectangle imageBounds = image.getBounds();
      Rectangle r = canvasBounds.intersection(tableBounds);
      int x = (r.width - imageBounds.width) / 2;
      if (x <= 0)
        x = 0;
      clipping.x += x;
*/
      int x = 0;
      gc.setClipping(clipping);
      gc.drawImage(image, x, 0);
    }
    gc.dispose();
  
public org.eclipse.swt.graphics.RectanglegetBoundsForCanvas()
Calculate the bounds of the receiver should be drawing in

return
what size/position the canvas should be

    Rectangle bounds = getBounds();
    if(bounds == null)
      return null;
    bounds.y += marginHeight;
    bounds.height -= (marginHeight * 2);
    bounds.x += marginWidth;
    bounds.width -= (marginWidth * 2);
    
    if (bounds.width <= 0 || bounds.height <= 0)
      return null;

    return bounds;
  
public org.eclipse.swt.graphics.ImagegetGraphic()
Retrieve the graphic related to this table item.

return
the Image that is draw in the cell, or null if there is none.

    return image;
  
public intgetMarginHeight()

		return marginHeight;
	
public intgetMarginWidth()

		return marginWidth;
	
public intgetOrientation()

		return orientation;
	
private org.eclipse.swt.graphics.ColorgetRowBackground(org.eclipse.swt.widgets.Table table)

    if (row.isSelected() && false) {
      if (table.isFocusControl())
        return table.getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION);
      else
        return table.getDisplay().getSystemColor(SWT.COLOR_GRAY);
    } else {
      return getBackground();
    }
  
public org.eclipse.swt.graphics.PointgetSize()

    Rectangle bounds = getBounds();
    if(bounds == null)
      return new Point(0, 0);
    return new Point(bounds.width - (marginWidth * 2), 
                     bounds.height - (marginHeight * 2));
  
public voidinvalidate()

  
public voidlocationChanged()

    if (cBlockView == null || cBlockView.isDisposed())
      return;

    Rectangle bounds = getBoundsForCanvas();
    //In case item isn't displayed bounds is null
    if (bounds == null || image == null || image.isDisposed()) {
      return;
    }
    // moveAbove reduces the # redraws
    //cBlockView.moveAbove(null);
    cBlockView.setLocation(bounds.x, bounds.y);
  
public booleanneedsPainting()

  	return true;
  
public booleansetGraphic(org.eclipse.swt.graphics.Image img)

    boolean bImageSet = (image != img);

    if (bImageSet) {
      if (cBlockView == null) {
        createBlockView();
      }
      image = img;
    }
    if (img != null) {
      doPaint((Rectangle)null);
    }

    return bImageSet;
  
public voidsetMargin(int width, int height)

  	if (width >= 0) {
  		marginWidth = width;
  	}
  	
  	if (height >= 0) {
  		marginHeight = height;
  	}
  
public voidsetOrientation(int orientation)

  	this.orientation = orientation;