Package org.gudy.azureus2.ui.swt.components

Source Code of org.gudy.azureus2.ui.swt.components.BufferedTableRow

/*
* File    : BufferedTableItem.java
* Created : 24-Nov-2003
* By      : parg
*
* Azureus - a Java Bittorrent client
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details ( see the LICENSE file ).
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

package org.gudy.azureus2.ui.swt.components;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.*;

import org.gudy.azureus2.core3.util.AERunnable;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.views.table.TableItemOrTreeItem;
import org.gudy.azureus2.ui.swt.views.table.TableOrTreeSWT;

/**
* A buffered Table Row.
*<p>
* 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.
*<p>
* Text is not buffered as SWT does a good job of buffering it already.
*<p>
*
* @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<br>
* @author TuxPaper (SWT.Virtual Stuff)
*/
public class
BufferedTableRow
{
  private static final int VALUE_SIZE_INC  = 8;

  // for checkWidget(int)
  public final static int REQUIRE_TABLEITEM = 0;
  public final static int REQUIRE_TABLEITEM_INITIALIZED = 1;
  public final static int REQUIRE_VISIBILITY = 2;
 
  protected TableOrTreeSWT table;
  protected TableItemOrTreeItem  item;
 
  protected Image[]  image_values  = new Image[0];
  protected Color[]  foreground_colors  = new Color[0];
 
  protected Color    foreground;
  protected Color     ourForeground;
 
  private Point ptIconSize = null;

  private Image imageBG;

  private int numSubItems;

  private boolean expanded;
 
 
  /**
   * Default constructor
   *
   * @param _table
   */
  public BufferedTableRow(TableOrTreeSWT _table)
  {
    table = _table;
    item = null;
  }
 
  /**
   * Disposes of underlying SWT TableItem. If no TableItem has been
   * assigned to the row yet, an unused TableItem will be disposed of, if
   * available.
   * <p>
   * Disposing of fonts, colors and other resources are the responsibilty of
   * the caller.
   */
  public void
  dispose()
  {
    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

        TableItemOrTreeItem[] items = table.getItems();
        for (int i = items.length - 1; i >= 0; i--) {
          TableItemOrTreeItem item = items[i];
          if (!item.isDisposed()) {
            Object itemRow = item.getData("TableRow");
            if (itemRow == null || itemRow == this) {
              this.item = item;
              break;
            }
          }
        }
      }

      boolean itemNeedsDisposal = item != null && !item.isDisposed();
     
      if (this.ourForeground != null && !this.ourForeground.isDisposed()) {
        // Even though we are going to dispose soon, set foreground to null
        // in case for some reason the OS gets a paint event in between
        // the color disposal and the item disposal
        if (itemNeedsDisposal) {
          item.setForeground(null);
        }
        this.ourForeground.dispose();
      }

      if (itemNeedsDisposal) {
        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;
  }
 
  /**
   * Sets the receiver's image at a column.
   *
   * @param index the column index
   * @param new_image the new image
   */
  public void
  setImage(
       int   index,
    Image  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 Image getImage(int index) {
    if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
      return null;
   
    return item.getImage(index);
  }

  /**
   * Checks if the widget is valid
   *
   * @param checkFlags REQUIRE_* flags (OR'd)
   *
   * @return True: Ok; False: Not ok
   */
  public boolean checkWidget(int checkFlags) {
    boolean bWidgetOk = 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) {
          }

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

    return bWidgetOk;
  }
 
  private boolean _isVisible() {
    // Least time consuming checks first

    if (inPaintItem()) {
      return true;
    }

    if (!table.isVisible()) {
      return false;
    }
   
    //if (table.getData("inPaintItem") != null) {
    //  System.out.println(table.indexOf((Widget) table.getData("inPaintItem")) + ";" + table.indexOf(item));
    //  System.out.println(Debug.getCompressedStackTrace());
    //}
   
    Rectangle bounds = getBounds(0);
    if (bounds == null) {
      return false;
    }
    return table.getClientArea().contains(bounds.x, bounds.y);

    /*
    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;

    //System.out.println("i-" + index + ";top=" + iTopIndex + ";b=" + iBottomIndex);
   
    return true;
    */
  }
 
 
  public Color
  getForeground()
  {
    if (foreground != null) {
      return foreground;
    }

    if (ourForeground == null && isSelected()) {
      return table.getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT);
    }

    if (!checkWidget(REQUIRE_TABLEITEM)) {
      return null;
    }

    return( item.getForeground());
  }
 
  public void
  setForeground(
    Color  c )
  {
    if (foreground == null && c == null) {return;}
   
    if (foreground != null && foreground.equals(c))
      return;
   
    foreground = c;
    if (this.ourForeground != null) {
      if (!this.ourForeground.isDisposed()) {
        this.ourForeground.dispose();
      }
      this.ourForeground = null;
    }
   
    if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
      return;

    item.setForeground(foreground);
  }
 
  public void setForeground(int red, int green, int blue) {
    if (red == -1 && green == -1 && blue == -1) {
      this.setForeground(null);
      return;
    }
   
    RGB newRGB = new RGB(red, green, blue);
    if (this.foreground != null && this.foreground.getRGB().equals(newRGB)) {
      return;
    }
   
    // Hopefully it is OK to just assume it is safe to dispose of the colour,
    // since we're expecting it to match this.foreground.
    Color newColor = new Color(getTable().getDisplay(), newRGB);
    if (checkWidget(REQUIRE_TABLEITEM_INITIALIZED)) {
      item.setForeground(newColor);
    }
    if (ourForeground != null && !ourForeground.isDisposed()) {
      ourForeground.dispose();
    }
    this.foreground = newColor;
    this.ourForeground = newColor;
  }
 
  public boolean
  setForeground(
    int index,
    Color  new_color )
  {
       
    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;

    if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED)) {
      return true;
    }

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

  public Color getForeground(int index)
  {
    if (index >= foreground_colors.length) {
      return getForeground();
    }

    if (foreground_colors[index] == null) {
      if (isSelected()) {
        Color systemColor = table.getDisplay().getSystemColor(
            table.isFocusControl() ? SWT.COLOR_LIST_SELECTION_TEXT
                : SWT.COLOR_WIDGET_FOREGROUND);
        return systemColor;
      }
      return getForeground();
    }

    return foreground_colors[index];
  }
 
  protected String
  getText(
    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);
  }

  /**
   * @param index
   * @param new_value
   * @return true if the item has been updated
   */
  public boolean
  setText(
    int      index,
    String    new_value )
  {
    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;
  }
 
  public Rectangle getBounds(int index) {
    if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
      return null;

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

    return r;
  }

  protected TableOrTreeSWT getTable() {
    return table;
  }
 
  public Color getBackground() {
    if (!checkWidget(REQUIRE_TABLEITEM_INITIALIZED))
      return null;
   
    if (isSelected()) {
      // XXX This isn't the right color on Cocoa when in focus
      return table.getDisplay().getSystemColor(
          table.isFocusControl() ? SWT.COLOR_LIST_SELECTION
              : SWT.COLOR_WIDGET_BACKGROUND);
    }
    return item.getBackground();
  }

  /**
   * The Index is this item's the position in list.
   *
   * @return Item's Position
   */
  public int getIndex() {
    if (!checkWidget(REQUIRE_TABLEITEM))
      return -1;

    return table.indexOf(item);
  }
 
  public boolean isSelected() {
    if (!checkWidget(REQUIRE_TABLEITEM))
      return false;

    return table.isSelected(item);
  }

  public void setSelected(final boolean bSelected) {
    Utils.execSWTThread(new AERunnable() {
      public void runSupport() {
        swt_setSelected(bSelected);
      }
    });
  }
 
  private void swt_setSelected(boolean bSelected) {
    if (!checkWidget(REQUIRE_TABLEITEM))
      return;

    if (bSelected)
      table.select(item);
    else
      table.deselect(item);
  }

  public boolean setTableItem(int newIndex, boolean isVisible) {
    TableItemOrTreeItem 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 + ", " + isVisible + ")");
      e.printStackTrace();
      return false;
    }
   
    return setTableItem(newRow, isVisible);
  }

  public boolean setTableItem(TableItemOrTreeItem newRow, boolean isVisible) {
    if (newRow.isDisposed()) {
      Debug.out("newRow disposed from " + Debug.getCompressedStackTrace());
      return false;
    }

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

    //if (!newRow.getParent().equalsTableOrTree(table))
    //  return false;

    if (!isVisible) {
      // Q&D, clear out.. we'll fill it correctly when it's visible
      if (newRow.getData("TableRow") != null) {
        newRow.setData("TableRow", null);
        table.deselect(newRow);
        return true;
      }
      //System.out.println("quickclear " + table.indexOf(newRow));
      return false;
    }
    //System.out.println("slowset " + table.indexOf(newRow));

    boolean lastItemExisted = item != null && !item.isDisposed();
    // can't base newRowHadItem on "TableRow" as we clear it in "unlinking" stage
    //boolean newRowHadItem = newRow.getData("TableRow") != null;

    if (newRow.getData("SD") != null) {
    } else {
      newRow.setData("SD", "1");
      setIconSize(ptIconSize);
    }

    newRow.setForeground(foreground);

    int numColumns = table.getColumnCount();
    for (int i = 0; i < numColumns; i++) {
      try {
        //newRow.setImage(i, null);
        newRow.setForeground(i, i < foreground_colors.length
            ? foreground_colors[i] : null);
      } catch (NoSuchMethodError e) {
        /* Ignore for Pre 3.0 SWT.. */
      }
    }

    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 (lastItemExisted && item.getData("TableRow") == this && !newRow.equals(item)) {
      item.setData("TableRow", null);
      table.deselect(item);
      /*
      int numColumns = table.getColumnCount();
      for (int i = 0; i < numColumns; i++) {
        try {
          //item.setImage(i, null);
          item.setForeground(i, null);
        } catch (NoSuchMethodError e) {
        }
      }
      */
    }

    item = newRow;

    setSubItemCount(numSubItems);
    item.setExpanded(expanded);
    // Need to execute (de)select later, because if we are in a paint event
    // that paint event may be reporting a row selected before the selection
    // event fired (Cocoa 3650 fires paint before select yet the row is marked
    // selected)
    Utils.execSWTThreadLater(0, new AERunnable() {
      public void runSupport() {
        if (table.isDisposed() || item == null) {
          return;
        }
        if (item.isDisposed()
            || item.getData("TableRow") != BufferedTableRow.this) {
          return;
        }
        // select/deselect takes less time than a table.isSelected (tree)
        if (isSelected()) {
          table.select(item);
        } else {
          table.deselect(item);
        }
      }
    });
    if (isVisible && !inPaintItem()) {
    //if (newRowHadItem && isVisible && !inPaintItem()) {
      //invalidate();
      // skip the visibility check and SWT thread wrapping of invalidate
      Rectangle r = item.getBounds(0);
      table.redraw(0, r.y, table.getClientArea().width, r.height, true);
    }

    return true;
  }

  public boolean setHeight(int iHeight) {
    return setIconSize(new Point(1, iHeight));
  }
 
  public boolean setIconSize(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;
  }

  /**
   * Whether the row is currently visible to the user
   *
   * @return visibility
   */
  public boolean isVisible() {
    return checkWidget(REQUIRE_VISIBILITY);
  }
 
  /**
   * Overridable function that is called when row needs invalidation.
   *
   */
  public void invalidate() {
    Utils.execSWTThread(new AERunnable() {
   
      public void runSupport() {
        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 void setBackgroundImage(Image image) {
    if (imageBG != null && !imageBG.isDisposed()) {
      imageBG.dispose();
    }
    imageBG = image;
  }
 
  public Image getBackgroundImage() {
    return imageBG;
  }

  public void setSubItemCount(int i) {
    numSubItems = i;
    if (item != null) {
      Utils.execSWTThread(new AERunnable() {
        public void runSupport() {
          if (item.isDisposed()) {
            return;
          }
          if (item.getItemCount() != numSubItems) {
            item.setItemCount(numSubItems);
            Rectangle r = item.getBounds(0);
            if (r != null) {
              table.redraw(0, r.y, table.getClientArea().width, r.height, true);
            }
          }
          TableItemOrTreeItem[] items = item.getItems();
          for (TableItemOrTreeItem subItem : items) {
            subItem.setData("TableRow", null);
          }
        }
      });
    }
  }
 
  public int getSubItemCount() {
    return numSubItems;
  }
 
  public TableItemOrTreeItem[] getSubItems() {
    return table.getItems();
  }

  public void setExpanded(boolean b) {
    expanded = b;
    if (item != null) {
      item.setExpanded(b);
    }
  }
 
  public boolean isExpanded() {
    return expanded;
  }

  /**
   * @return
   *
   * @since 4.4.0.5
   */
  public boolean inPaintItem() {
    if (item != null && !item.isDisposed()) {
      InPaintInfo info = (InPaintInfo) table.getData("inPaintInfo");
      if (info != null && item.equals(info.item)) {
        return true;
      }
    }
    return false;
  }

  public boolean isVisibleNoSWT() {
    return true// assume the worst
  }
 
  public TableItemOrTreeItem getItem() {
    return item;
  }
}
TOP

Related Classes of org.gudy.azureus2.ui.swt.components.BufferedTableRow

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.