FileDocCategorySizeDatePackage
BufferedTableRow.javaAPI DocAzureus 3.0.3.415652Sat Jun 02 14:43:28 BST 2007org.gudy.azureus2.ui.swt.components

BufferedTableRow

public class BufferedTableRow extends Object
A buffered Table Row.

We buffer certain properties of TableRow to save CPU cycles. For example, foreground_colors is cached because TableItem.getForegroundColor is expensive when there is no color set, and setForegroundColor is always expensive.

Text is not buffered as SWT does a good job of buffering it already.

note
For Virtual tables, we can not set any visual properties until SWT.SetData has been called. getData("SD") is set after SetData call, and the row is invalidated. Thus, there is no need to set any visual properties until the row #isVisible()
author
parg
author
TuxPaper (SWT.Virtual Stuff)

Fields Summary
private static final int
VALUE_SIZE_INC
private static org.eclipse.swt.graphics.Color[]
alternatingColors
public static final int
REQUIRE_TABLEITEM
public static final int
REQUIRE_TABLEITEM_INITIALIZED
public static final int
REQUIRE_VISIBILITY
protected org.eclipse.swt.widgets.Table
table
protected org.eclipse.swt.widgets.TableItem
item
protected org.eclipse.swt.graphics.Image[]
image_values
protected org.eclipse.swt.graphics.Color[]
foreground_colors
protected org.eclipse.swt.graphics.Color
foreground
private org.eclipse.swt.graphics.Point
ptIconSize
Constructors Summary
public BufferedTableRow(org.eclipse.swt.widgets.Table _table)
Default constructor

param
_table

	
	     	 
	  
	
		table = _table;
		item = null;
	
Methods Summary
private boolean_isVisible()

		// Least time consuming checks first
		
		int index = table.indexOf(item);
		if (index == -1)
			return false;

		int iTopIndex = table.getTopIndex();
		if (index < iTopIndex)
			return false;

		int iBottomIndex = Utils.getTableBottomIndex(table, iTopIndex);
		if (index > iBottomIndex)
			return false;

		return true;
	
public booleancheckWidget(int checkFlags)
Checks if the widget is valid

param
checkFlags REQUIRE_* flags (OR'd)
return
True: Ok; False: Not ok

		boolean bWidgetOk = !table.isDisposed() && item != null
				&& !item.isDisposed() && item.getData("TableRow") == this;

		final boolean bCheckVisibility = (checkFlags & REQUIRE_VISIBILITY) > 0;
		final boolean bCheckInitialized = (checkFlags & REQUIRE_TABLEITEM_INITIALIZED) > 0;

		if (bWidgetOk && bCheckInitialized) {
			bWidgetOk = (table.getStyle() & SWT.VIRTUAL) == 0
					|| item.getData("SD") != null;
		}

		if (bWidgetOk && bCheckVisibility) {
			if (_isVisible()) {
				// Caller assumes that a visible item can be modified, so 
				// make sure we initialize it.
				if (!bCheckInitialized && (table.getStyle() & SWT.VIRTUAL) != 0
						&& item.getData("SD") == null) {
					// This is catch is temporary for SWT 3212, because there are cases where
					// it says it isn't disposed, when it really almost is
					try {
						item.setData("SD", "1");
					} catch (NullPointerException badSWT) {
					}

		   		setAlternatingBGColor(true);
		    	setIconSize(ptIconSize);
					invalidate();
				}
			} else {
				bWidgetOk = false;
			}
		}

		return bWidgetOk;
	
private voidcopyToItem(org.eclipse.swt.widgets.TableItem newItem)

    Table table = getTable();
    if (table == null || item == null)
      return;

//    newItem.setText(text_values);
		newItem.setImage(image_values);
		Color colorFG = item.getForeground();
		Color colorBG = item.getBackground();
		newItem.setForeground(colorFG);
		newItem.setBackground(colorBG);
		int numColumns = table.getColumnCount();
		for (int i = 0; i < numColumns; i++) {
      try {
      	newItem.setText(i, item.getText(i));
        Color colorColumnFG = item.getForeground(i);
        Color colorColumnBG = item.getBackground(i);
        if (!colorColumnFG.equals(colorFG))
          newItem.setForeground(i, colorColumnFG);
        if (!colorColumnBG.equals(colorBG))
          newItem.setBackground(i, colorColumnBG);
      } catch (NoSuchMethodError e) {
        /* Ignore for Pre 3.0 SWT.. */
      }
		}
    if (isSelected())
      table.select(table.indexOf(newItem));
    else
      table.deselect(table.indexOf(newItem));

    newItem.setData("TableRow", item.getData("TableRow"));
	
public voidcreateSWTRow()
Create a row in the SWT table

    item = new TableItem(table, SWT.NULL);
		setAlternatingBGColor(true);
	
public voidcreateSWTRow(int index)

    new TableItem(table, SWT.NULL);
    setTableItem(index, false);
	
public voiddispose()
Disposes of underlying SWT TableItem. If no TableItem has been assigned to the row yet, an unused TableItem will be disposed of, if available.

Disposing of fonts, colors and other resources are the responsibilty of the caller.

		if (table != null && !table.isDisposed() && Utils.isThisThreadSWT()) {
			if (!checkWidget(REQUIRE_TABLEITEM)) {
				// No assigned spot yet, or not our spot:
				// find a row with no TableRow data

				TableItem[] items = table.getItems();
				for (int i = items.length - 1; i >= 0; i--) {
					TableItem item = items[i];
					if (!item.isDisposed()) {
						Object itemRow = item.getData("TableRow");
						if (itemRow == null || itemRow == this) {
							this.item = item;
							break;
						}
					}
				}
			}
			
			if (item != null && !item.isDisposed()) 
				item.dispose();
			else if (table.getItemCount() > 0)
				System.err.println("No table row was found to dispose");
		} else {
			if (!Utils.isThisThreadSWT()) {
				System.err.println("Calling BufferedTableRow.dispose on non-SWT thread!");
				System.err.println(Debug.getStackTrace(false, false));
			}
		}
		item = null;
	
public org.eclipse.swt.graphics.ColorgetBackground()

		if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
      return null;
    return item.getBackground();
  
public org.eclipse.swt.graphics.RectanglegetBounds(int index)

		if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
			return null;

		// Some Platforms (OSX) don't handle getBounds properly (3.2M4) when
		// item doesn't exist in table
		if (table.indexOf(item) == -1)
			return null;

		Rectangle r = item.getBounds(index);
		if (r == null || r.width == 0 || r.height == 0)
			return null;

		return r; 
	
public org.eclipse.swt.graphics.ColorgetForeground()

		if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
  	  return null;

		return( item.getForeground());
	
public org.eclipse.swt.graphics.ColorgetForeground(int index)

		if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
  	  return null;
		if (index >= foreground_colors.length)
		  return item.getForeground();

		return foreground_colors[index];
	
public org.eclipse.swt.graphics.ImagegetImage(int index)

		if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
			return null;
		
		return item.getImage(index);
	
public intgetIndex()
The Index is this item's the position in list.

return
Item's Position

		if (!checkWidget(REQUIRE_TABLEITEM))
  		return -1;

    return table.indexOf(item);
  
protected org.eclipse.swt.widgets.TablegetTable()

  	return table;
  
protected java.lang.StringgetText(int index)

		if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
			return "";

		// SWT >= 3041(Win),3014(GTK),3002(Carbon) and returns "" if range check
		// fails
		return item.getText(index);
	
public voidinvalidate()
Overridable function that is called when row needs invalidation.

  	if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED | REQUIRE_VISIBILITY))
  		return;

		Rectangle r = item.getBounds(0);

		table.redraw(0, r.y, table.getClientArea().width, r.height, true);
  
public booleanisSelected()

		if (!checkWidget(REQUIRE_TABLEITEM))
  		return false;

  	// Invalid Indexes are checked/ignored by SWT.
    return table.isSelected(table.indexOf(item));
  
public booleanisVisible()
Whether the row is currently visible to the user

return
visibility

  	return checkWidget(REQUIRE_VISIBILITY);
  
public voidsetAlternatingBGColor(boolean bEvenIfNotVisible)

		if (Utils.TABLE_GRIDLINE_IS_ALTERNATING_COLOR)
			return;
			
		if ((table.getStyle() & SWT.VIRTUAL) != 0 && !bEvenIfNotVisible
				&& !isVisible()) {
			return;
		} else if (item == null || item.isDisposed()) {
			return;
		}

		int index = table.indexOf(item);
		if (index == -1) {
			return;
		}

		if (alternatingColors == null || alternatingColors[1].isDisposed()) {
			alternatingColors = new Color[] {
					table.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND),
					Colors.colorAltRow };
		}

		Color newColor = alternatingColors[index % alternatingColors.length];
		if (!newColor.equals(getBackground()))
			item.setBackground(newColor);
	
public voidsetForeground(org.eclipse.swt.graphics.Color c)

		if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
			return;

		if (foreground != null && foreground.equals(c))
		  return;
		
		foreground = c;
		
		item.setForeground(foreground);
	
public booleansetForeground(int index, org.eclipse.swt.graphics.Color new_color)

		if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
			return false;
				
		if ( index >= foreground_colors.length ){
			
			int	new_size = Math.max( index+1, foreground_colors.length+VALUE_SIZE_INC );
			
			Color[]	new_colors = new Color[new_size];
			
			System.arraycopy( foreground_colors, 0, new_colors, 0, foreground_colors.length );
			
			foreground_colors = new_colors;
		}

		Color value = foreground_colors[index];
		
		if ( new_color == value ){
			
			return false;
		}
		
		if (	new_color != null && 
				value != null &&
				new_color.equals( value )){
					
			return false;
		}
		
		foreground_colors[index] = new_color;

    try {
      item.setForeground(index, new_color);
    } catch (NoSuchMethodError e) {
      /* Ignore for Pre 3.0 SWT.. */
    }
    
    return true;
	
public booleansetHeight(int iHeight)

  	return setIconSize(new Point(1, iHeight));
  
public booleansetIconSize(org.eclipse.swt.graphics.Point pt)

    ptIconSize = pt;

    if (pt == null)
      return false;
    
		if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
			return false;
		
    Image oldImage = item.getImage(0);
    if (oldImage != null) {
    	Rectangle r = oldImage.getBounds();
    	if (r.width == pt.x && r.height == pt.y)
    		return false;
    }
		
    // set row height by setting image
    Image image = new Image(item.getDisplay(), pt.x, pt.y);
    item.setImage(0, image);
    item.setImage(0, null);
    image.dispose();
    
    return true;
  
public voidsetImage(int index, org.eclipse.swt.graphics.Image new_image)
Sets the receiver's image at a column.

param
index the column index
param
new_image the new image

		if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
			return;

		if ( index >= image_values.length ){
			
			int	new_size = Math.max( index+1, image_values.length+VALUE_SIZE_INC );
			
			Image[]	new_images = new Image[new_size];
			
			System.arraycopy( image_values, 0, new_images, 0, image_values.length );
			
			image_values = new_images;
		}
		
		Image	image = image_values[index];
		
		if ( new_image == image ){
			
			return;
		}
		
		image_values[index] = new_image;
		
		item.setImage( index, new_image );	
	
public voidsetSelected(boolean bSelected)

		if (!checkWidget(REQUIRE_TABLEITEM))
  		return;

    if (bSelected)
      table.select(getIndex());
    else
      table.deselect(getIndex());
  
public booleansetTableItem(int newIndex, boolean bCopyFromOld)
Set the TableItem associated with this row to the TableItem at the specified index.

param
newIndex Index of TableItem that will be associated with this row
param
bCopyFromOld True: Copy the visuals from the old TableItem to the new TableItem
return
success level

  	TableItem newRow;
  	try {
  		newRow = table.getItem(newIndex);
  	} catch (IllegalArgumentException er) {
  		if (item == null || item.isDisposed()) {
  			return false;
  		}
  		item = null;
  		return true;
  	} catch (Throwable e) {
  		System.out.println("setTableItem(" + newIndex + ", " + bCopyFromOld + ")");
  		e.printStackTrace();
  		return false;
  	}
  	
  	if (newRow.isDisposed()) {
  		Debug.out("newRow disposed from " + Debug.getCompressedStackTrace());
  		return false;
  	}

  	if (newRow == item) {
  		if (newRow == null || newRow.getData("TableRow") == this) {
     		setAlternatingBGColor(false);
  			return false;
  		}
  	}

  	if (newRow != null) {
  		if (newRow.getParent() != table)
  			return false;

	    if (bCopyFromOld) {
	      copyToItem(newRow);
	    } else if (newRow.getData("SD") != null) {
	    	// clear causes too much flicker
	    	//table.clear(table.indexOf(newRow));
	  		newRow.setForeground(null);
	  		//newRow.setBackground(null);

	  		int numColumns = table.getColumnCount();
	  		for (int i = 0; i < numColumns; i++) {
	        try {
        		newRow.setImage(i, null);
        		newRow.setForeground(i, null);
	        } catch (NoSuchMethodError e) {
	          /* Ignore for Pre 3.0 SWT.. */
	        }
	  		}
	 		} else {
	 			newRow.setData("SD", "1");
	 			setIconSize(ptIconSize);
	 		}

   		setAlternatingBGColor(false);

	    try {
	    	newRow.setData("TableRow", this);
	    } catch (Exception e) {
	    	e.printStackTrace();
	    	System.out.println("Disposed? " + newRow.isDisposed());
	    	if (!newRow.isDisposed()) {
		    	System.out.println("TR? " + newRow.getData("TableRow"));
		    	System.out.println("SD? " + newRow.getData("SD"));
	    	}
	    }
  	}
	  image_values	= new Image[0];
	  foreground_colors	= new Color[0];
    foreground = null;

    // unlink old item from tablerow
    if (item != null && !item.isDisposed() && item.getData("TableRow") == this && newRow != item) {
    	item.setData("TableRow", null);
  		int numColumns = table.getColumnCount();
  		for (int i = 0; i < numColumns; i++) {
        try {
        	item.setImage(i, null);
        	item.setForeground(i, null);
        } catch (NoSuchMethodError e) {
          /* Ignore for Pre 3.0 SWT.. */
        }
  		}
    }

    item = newRow;
 		invalidate();

    return true;
  
public booleansetText(int index, java.lang.String new_value)

param
index
param
new_value
return
true if the item has been updated

		if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
			return false;
		
		if (index < 0 || index >= table.getColumnCount())
			return false;
		
		if (new_value == null)
			new_value = "";

		if (item.getText(index).equals(new_value))
			return false;

		item.setText( index, new_value );
    
    return true;