This appendix contains the source code for
the TableTree and TableTreeItem classes.
package org.eclipse.swt.custom;
/*
�* (c) Copyright IBM Corp. 2000, 2001.
�* All Rights Reserved
�*/
import java.util.Enumeration;
import java.util.Vector;
import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
/**
�* A TableTree is a selectable user interface object
�* that displays a hierarchy of items, and issues
�* notification when an item is selected.
�* A TableTree may be single or multi select.
�* <p>
�*
The item children that may be added to instances of this class
�* must be of type <code>TableTreeItem</code>.
�* </p><p>
�*
Note that although this class is a subclass of <code>Composite</code>,
�* it does not make sense to add <code>Control</code> children to it,
�* or set a layout on it.
�* </p><p>
�* <dl>
�*��� <dt><b>Styles:</b> <dd> SINGLE, MULTI, CHECK, FULL_SELECTION
�*��� <dt><b>Events:</b> <dd> Selection, DefaultSelection,
Collapse, Expand
�* </dl>
�*/
public class TableTree extends Composite {
����� Table
table;
����� TableTreeItem[]
items = EMPTY_ITEMS;
����� Image
plusImage, minusImage, sizeImage;
����� /*
����� *
TableTreeItems are not treated as children but rather as items.
����� *
When the TableTree is disposed, all children are disposed because
����� *
TableTree inherits this behaviour from Composite.� The items
����� *
must be disposed separately.� Because
TableTree is not part of
����� *
the org.eclipse.swt.widgets package, the method releaseWidget can
����� *
not be overriden (this is how items are disposed of in Table and Tree).
����� *
Instead, the items are disposed of in response to the dispose event on the
����� *
TableTree.� The "inDispose"
flag is used to distinguish between disposing
����� *
one TableTreeItem (e.g. when removing an entry from the TableTree) and
����� *
disposing the entire TableTree.
����� */
����� boolean
inDispose = false;
�����
����� static final TableTreeItem[] EMPTY_ITEMS = new TableTreeItem [0];
����� static final String[] EMPTY_TEXTS = new String [0];��
����� static final Image[] EMPTY_IMAGES = new Image [0];���
/**
�* Creates a new instance of the widget.
�*
�* @param
parent a
composite widget
�* @param
style the bitwise
OR'ing of widget styles
�*/
public TableTree(Composite parent, int style) {
����� super(parent, SWT.NONE);
����� table
= new Table(this, style);
����� setBackground(table.getBackground());
����� setForeground(table.getForeground());
����� setFont(table.getFont());
����� table.addListener(SWT.MouseDown,
new Listener() {
����������� public void handleEvent(Event e) {
����������������� onMouseDown(e);
����������� }
����� });
����� table.addListener(SWT.Selection,
new Listener() {
����������� public void handleEvent(Event e) {
����������������� onSelection(e);
����������� }
����� });
����� table.addListener(SWT.DefaultSelection,
new Listener() {
����������� public void handleEvent(Event e) {
����������������� onSelection(e);
����������� }
����� });
����� addListener(SWT.Dispose,
new Listener() {
����������� public void handleEvent(Event e) {
����������������� onDispose();
����������� }
����� });
����� addListener(SWT.Resize,
new Listener() {
����������� public void handleEvent(Event e) {
����������������� onResize();
����������� }
����� });
����� addListener(SWT.FocusIn,
new Listener() {
����������� public void handleEvent(Event e) {
����������������� onFocusIn();
����������� }
����� });
}
int addItem(TableTreeItem item, int index) {
����� if (index < 0 || index > items.length) throw new SWTError(SWT.ERROR_INVALID_ARGUMENT);
����� TableTreeItem[]
newItems = new TableTreeItem[items.length + 1];
����� System.arraycopy(items,
0, newItems, 0, index);
����� newItems[index]
= item;
����� System.arraycopy(items,
index, newItems, index + 1, items.length - index);
����� items
= newItems;
����� /* Return the index in the table
where this table should be inserted */
����� if
(index ==
items.length - 1 )
����������� return table.getItemCount();
����� else
����������� return
table.indexOf(items[index+1].tableItem);
}
/**��
�* Adds the listener to receive selection events.
�* <p>
�*
�* @param
listener the
selection listener
�*
�* @exception
SWTError <ul>
�*��� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread
�*��� <li>ERROR_WIDGET_DISPOSED when the
widget has been disposed
�*��� <li>ERROR_NULL_ARGUMENT when listener
is null
�* </ul>
�*/
public void addSelectionListener(SelectionListener
listener) {
����� if (listener == null) throw new SWTError
(SWT.ERROR_NULL_ARGUMENT);
����� TypedListener
typedListener = new
TypedListener
(listener);
����� addListener
(SWT.Selection,typedListener);
����� addListener
(SWT.DefaultSelection,typedListener);
}
/**��
�* Adds the listener to receive tree events.
�* <p>
�*
�* @param
listener the tree
listener
�*
�* @exception
SWTError <ul>
�*��� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread
�*��� <li>ERROR_WIDGET_DISPOSED when the
widget has been disposed
�*��� <li>ERROR_NULL_ARGUMENT when listener
is null
�* </ul>
�*/
public void addTreeListener(TreeListener
listener) {
����� if (listener == null) throw new SWTError
(SWT.ERROR_NULL_ARGUMENT);
����� TypedListener
typedListener = new
TypedListener
(listener);
����� addListener
(SWT.Expand, typedListener);
����� addListener
(SWT.Collapse, typedListener);
}�
/**
�* Computes the preferred size of the widget.
�* <p>
�*
Calculate the preferred size of the widget based
�* on the current contents. The hint arguments allow
�* a specific client area width and/or height to be
�* requested. The hints may be honored depending on
�* the platform and the layout.
�*
�* @param
wHint the width
hint (can be SWT.DEFAULT)
�* @param
hHint the height
hint (can be SWT.DEFAULT)
�* @return
a point
containing the preferred size of the widget including trim
�*
�* @exception
SWTError <ul>
�*��������� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread</li>
�*��������� <li>ERROR_WIDGET_DISPOSED when the widget has been
disposed</li>
�*��� </ul>
�*/
public Point computeSize (int wHint, int hHint) {
����� return table.computeSize (wHint, hHint, true);
}
/**
�* Computes the widget trim.
�* <p>
�*
Trim is widget specific and may include scroll
�* bars and menu bar in addition to other trimmings
�* that are outside of the widget's client area.
�*
�* @param
x the x location
of the client area
�* @param
y the y location
of the client area
�* @param
width the width
of the client area
�* @param
height the height
of the client area
�* @return
a rectangle
containing the trim of the widget.
�*
�* @exception
SWTError <ul>
�*��������� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread</li>
�*��������� <li>ERROR_WIDGET_DISPOSED when the widget has been
disposed</li>
�*��� </ul>
�*/
public Rectangle computeTrim (int x, int y, int width, int height) {
����� return table.computeTrim(x, y, width,
height);
}
/**
�* Deselects all items.
�* <p>
�*
If an item is selected, it is deselected.
�* If an item is not selected, it remains unselected.
�*
�* @exception
SWTError <ul>
�*��� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread
�*��� <li>ERROR_WIDGET_DISPOSED when the
widget has been disposed
�* </ul>
�*/
public void deselectAll () {
����� table.deselectAll();
}
/* Expand upward from the
specified leaf item. */
void expandItem (TableTreeItem item) {
����� if (item == null || item.getExpanded()) return;
����� expandItem(item.parentItem);
����� item.setExpanded(true);
����� Event
event = new Event();
����� event.item
= item;
����� notifyListeners(SWT.Expand,
event);
}
/**
�* Gets the number of items.
�* <p>
�* @return the number of items in the widget
�*/
public int getItemCount () {
����� return items.length;
}
/**
�* Gets the height of one item.
�* <p>
�*
This operation will fail if the height of
�* one item could not be queried from the OS.
�*
�* @return
the height of one
item in the widget
�*
�* @exception
SWTError <ul>
�*��� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread
�*��� <li>ERROR_WIDGET_DISPOSED when the
widget has been disposed
�*��� <li>ERROR_CANNOT_GET_ITEM_HEIGHT when
the operation fails
�* </ul>
�*/
public int getItemHeight () {
����� return table.getItemHeight();
}
/**
�* Gets the items.
�* <p>
�* @return the items in the widget
�*
�*/
public TableTreeItem [] getItems () {
����� TableTreeItem[]
newItems = new TableTreeItem[items.length];
����� System.arraycopy(items,
0, newItems, 0, items.length);
����� return newItems;
}
/**
�* Gets the selected items.
�* <p>
�*
This operation will fail if the selected
�* items cannot be queried from the OS.
�*
�* @return
the selected
items in the widget
�*
�* @exception
SWTError <ul>
�*��������� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread</li>
�*��������� <li>ERROR_WIDGET_DISPOSED when the widget has been
disposed</li>
�* �������� <li>ERROR_CANNOT_GET_SELECTION when the operation fails</li>
�*��� </ul>
�*/
public TableTreeItem [] getSelection () {
����� TableItem[]
selection = table.getSelection();
����� TableTreeItem
[] result = new
TableTreeItem[selection.length];
����� for (int i = 0; i <
selection.length; i++){
����������� result[i]
= (TableTreeItem) selection[i].getData();
����� }
����� return result;
}
/**
�* Gets the number of selected items.
�* <p>
�*
This operation will fail if the number of selected
�* items cannot be queried from the OS.
�*
�* @return
the number of
selected items in the widget
�*
�* @exception
SWTError <ul>
�*��������� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread</li>
�*��������� <li>ERROR_WIDGET_DISPOSED when the widget has been
disposed</li>
�* �������� <li>ERROR_CANNOT_GET_COUNT when the operation fails</li>
�*��� </ul>
�*/
public int getSelectionCount () {
����� return table.getSelectionCount();
}
/**
�* Returns the underlying Table control.
�*
�* @return
the underlying
Table control
�*/
public Table getTable () {
����� return table;
}
void createImages () {
�����
����� int itemHeight = sizeImage.getBounds().height;
����� // Calculate border around image.
����� //
At least 9 pixels are needed to draw the image
����� //
Leave at least a 6 pixel border.
����� int indent = Math.min(6, (itemHeight - 9) / 2);
����� indent
= Math.max(0, indent);
����� int size = Math.max (10, itemHeight - 2 * indent);
����� size
= ((size + 1) / 2) * 2; //
size must be an even number
����� int midpoint = indent + size / 2;
�����
����� Color
foreground = getForeground();
����� Color
plusMinus = getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
����� Color
background = getBackground();
�����
����� /* Plus image */
����� PaletteData
palette = new PaletteData(new RGB[]{foreground.getRGB(), background.getRGB(),
plusMinus.getRGB()});
����� ImageData
imageData = new
ImageData(itemHeight,
itemHeight, 4, palette);
����� imageData.transparentPixel
= 1;
����� plusImage
= new Image(getDisplay(), imageData);
����� GC
gc = new GC(plusImage);
����� gc.setBackground(background);
����� gc.fillRectangle(0,
0, itemHeight, itemHeight);
����� gc.setForeground(plusMinus);
����� gc.drawRectangle(indent,
indent, size, size);
����� gc.setForeground(foreground);
����� gc.drawLine(midpoint,
indent + 2, midpoint, indent + size - 2);
����� gc.drawLine(indent
+ 2, midpoint, indent + size - 2, midpoint);
����� gc.dispose();
�����
����� /* Minus image */
����� palette
= new PaletteData(new RGB[]{foreground.getRGB(), background.getRGB(),
plusMinus.getRGB()});
����� imageData
= new ImageData(itemHeight, itemHeight,
4, palette);
����� imageData.transparentPixel
= 1;
����� minusImage
= new Image(getDisplay(), imageData);
����� gc
= new GC(minusImage);
����� gc.setBackground(background);
����� gc.fillRectangle(0,
0, itemHeight, itemHeight);
����� gc.setForeground(plusMinus);
����� gc.drawRectangle(indent,
indent, size, size);
����� gc.setForeground(foreground);
����� gc.drawLine(indent
+ 2, midpoint, indent + size - 2, midpoint);
����� gc.dispose();
}
Image getPlusImage() {
����� if (plusImage == null) createImages();
����� return plusImage;
}
Image getMinusImage() {
����� if (minusImage == null) createImages();
����� return minusImage;
}
/**
�* Gets the index of an item.
�*
�* <p>The widget is searched starting at
0 until an
�* item is found that is equal to the search item.
�* If no item is found, -1 is returned.� Indexing
�* is zero based.� This
index is relative to the parent only.
�*
�* @param
item the search
item
�* @return
the index of the
item or -1
�*
�*/
public int indexOf (TableTreeItem item) {
����� for (int i = 0; i < items.length;
i++) {
����������� if (item == items[i]) return i;
����� }
����� return -1;
}
void onDispose() {
����� inDispose
= true;
����� for (int i = 0; i <
items.length; i++) {
����������� items[i].dispose();
����� }
����� inDispose
= false;
����� if (plusImage != null) plusImage.dispose();
����� if (minusImage != null) minusImage.dispose();
����� if (sizeImage != null) sizeImage.dispose();
����� plusImage
= minusImage = sizeImage = null;
}
void onResize () {
����� Rectangle
area = getClientArea();
����� table.setBounds(0,
0, area.width, area.height);
}
void onSelection (Event e) {
����� Event
event = new Event();
����� TableItem
tableItem = (TableItem)e.item;
��� � TableTreeItem item =
getItem(tableItem);
��� � event.item = item;
����� if (e.type == SWT.Selection
����� ��� && e.detail == SWT.CHECK
����� ��� && item != null) {
����� ��� � event.detail
= SWT.CHECK;
����������� item.checked
= tableItem.getChecked();
����� }
����� notifyListeners(e.type,
event);
}
public TableTreeItem getItem(Point point)
{
����� TableItem
item = table.getItem(point);
����� if (item == null) return null;
����� return getItem(item);
�����
}
TableTreeItem getItem(TableItem
tableItem) {
����� if (tableItem == null) return null;
����� for (int i = 0; i <
items.length; i++) {
����� ��� � TableTreeItem
item = items[i].getItem(tableItem);
����� ��� � if (item != null) return item;
����� }
����� return null;
}
void onFocusIn () {
����� table.setFocus();
}
void onMouseDown(Event event) {
����� /* If user clicked on the [+] or
[-], expand or collapse the tree. */
����� TableItem[]
items = table.getItems();
����� for (int i = 0; i <
items.length; i++) {
����������� Rectangle
rect = items[i].getImageBounds(0);
����������� if (rect.contains(event.x, event.y)) {
����������������� TableTreeItem
item = (TableTreeItem) items[i].getData();
����������������� event
= new Event();
����������������� event.item
= item;
����������������� item.setExpanded(!item.getExpanded());
����������������� if (item.getExpanded()) {
����������������������� notifyListeners(SWT.Expand,
event);
����������������� }
else {
����������������������� notifyListeners(SWT.Collapse,
event);
����������������� }
����������������� return;
����������� }
����� }
}
/**
�* Removes all items.
�* <p>
�*
This operation will fail when an item
�* could not be removed in the OS.
�*
�* @exception
SWTError <ul>
�*��� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread
�* �� <li>ERROR_WIDGET_DISPOSED when the
widget has been disposed
�* �� <li>ERROR_ITEM_NOT_REMOVED when the
operation fails
�* </ul>
�*/
public void removeAll () {
����� setRedraw(false);
����� for (int i = items.length
- 1; i >= 0; i--) {
����������� items[i].dispose();
����� }
����� items
= EMPTY_ITEMS;
����� setRedraw(true);
}
void removeItem(TableTreeItem item) {
����� int index = 0;
����� while (index < items.length
&& items[index] != item) index++;
����� if (index == items.length) return;
����� TableTreeItem[]
newItems = new TableTreeItem[items.length - 1];
����� System.arraycopy(items,
0, newItems, 0, index);
����� System.arraycopy(items,
index + 1, newItems, index, items.length - index - 1);
����� items
= newItems;
}
/**��
�* Removes the listener.
�* <p>
�*
�* @param
listener the
listener
�*
�* @exception
SWTError <ul>
�*��� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread
�* �� <li>ERROR_WIDGET_DISPOSED when the
widget has been disposed
�*��� <li>ERROR_NULL_ARGUMENT when listener
is null
�* </ul>
�*/
public void removeSelectionListener
(SelectionListener listener) {
����� if (listener == null) throw new SWTError
(SWT.ERROR_NULL_ARGUMENT);
����� removeListener(SWT.Selection,
listener);
����� removeListener(SWT.DefaultSelection,
listener);
}
/**��
�* Removes the listener.
�*
�* @param
listener the
listener
�*
�* @exception
SWTError <ul>
�*��� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread
�*��� <li>ERROR_WIDGET_DISPOSED when the
widget has been disposed
�*��� <li>ERROR_NULL_ARGUMENT when listener
is null
�* </ul>
�*/
public void removeTreeListener (TreeListener
listener) {
����� if (listener == null) throw new SWTError
(SWT.ERROR_NULL_ARGUMENT);
����� removeListener(SWT.Expand,
listener);
����� removeListener(SWT.Collapse,
listener);
}
/**
�* Selects all items.
�* <p>
�*
If an item is not selected, it is selected.
�* If an item is selected, it remains selected.
�*
�* @exception
SWTError <ul>
�*��� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread
�*��� <li>ERROR_WIDGET_DISPOSED when the
widget has been disposed
�* </ul>
�*/
public void selectAll () {
����� table.selectAll();
}
/**
�* Sets the widget background color.
�* <p>
�*
When new color is null, the background reverts
�* to the default system color for the widget.
�*
�* @param
color the new
color (or null)
�*
�* @exception
SWTError <ul>
�*��������� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread</li>
�*��������� <li>ERROR_WIDGET_DISPOSED when the widget has been
disposed</li>
�*��� </ul>
�*/
public void setBackground (Color color) {
����� super.setBackground(color);
����� table.setBackground(color);
����� if (sizeImage != null) {
����������� GC
gc = new GC (sizeImage);
����������� gc.setBackground(getBackground());
����������� Rectangle
size = sizeImage.getBounds();
����������� gc.fillRectangle(size);
����������� gc.dispose();
����� }
}
/**
�* Sets the enabled state.
�* <p>
�* A
disabled widget is typically not selectable from
�* the user interface and draws with an inactive or
�* grayed look.
�*
�* @param
enabled the new
enabled state
�*
�* @exception
SWTError <ul>
�*��������� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread</li>
�*��������� <li>ERROR_WIDGET_DISPOSED when the widget has been
disposed</li>
�*��� </ul>
�*/
public void setEnabled (boolean enabled) {
����� super.setEnabled(enabled);
����� table.setEnabled(enabled);
}
/**
�* Sets the widget font.
�* <p>
�*
When new font is null, the font reverts
�* to the default system font for the widget.
�*
�* @param
font the new font
(or null)
�*
�* @exception
SWTError <ul>
�*��������� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread</li>
�*��������� <li>ERROR_WIDGET_DISPOSED when the widget has been
disposed</li>
�*��� </ul>
�*/
public void setFont (Font font) {
����� super.setFont(font);
����� table.setFont(font);
}
/**
�* Gets the widget foreground color.
�* <p>
�* @return the widget foreground color
�*
�* @exception
SWTError <ul>
�*��������� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread</li>
�*��������� <li>ERROR_WIDGET_DISPOSED when the widget has been
disposed</li>
�*��� </ul>
�*/
public void setForeground (Color color) {
����� super.setForeground(color);
����� table.setForeground(color);
}
/**
�* Sets the pop up menu.
�* <p>
�*
Every control has an optional pop up menu that is
�* displayed when the user requests a popup menu for
�* the control.� The
sequence of key strokes/button
�* presses/button releases that is used to request
�* a pop up menu is platform specific.
�*
�* @param
menu the new pop
up menu
�*
�* @exception
SWTError <ul>
�*��������� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread</li>
�*��������� <li>ERROR_WIDGET_DISPOSED when the widget has been
disposed</li>
�*��������� <li>ERROR_MENU_NOT_POP_UP when the menu is not a POP_UP</li>
�*��������� <li>ERROR_NO_COMMON_PARENT when the menu is not in the
same widget tree</li>
�*��� </ul>
�*/
public void setMenu (Menu menu) {
����� super.setMenu(menu);
����� table.setMenu(menu);
}
/**
�* Sets the selection.
�* <p>
�* @param items new selection
�*
�* @exception
SWTError <ul>
�*��� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread
�*��� <li>ERROR_WIDGET_DISPOSED when the
widget has been disposed
�*��� <li>ERROR_NULL_ARGUMENT when items is
null
�* </ul>
�*/
public void setSelection (TableTreeItem[]
items) {
����� TableItem[]
tableItems = new
TableItem[items.length];
����� for (int i = 0; i <
items.length; i++) {
����������� if (items[i] == null) throw new SWTError(SWT.ERROR_NULL_ARGUMENT);
����������� if (!items[i].getVisible()) expandItem (items[i]);
����������� tableItems[i]
= items[i].tableItem;
����� }
����� table.setSelection(tableItems);
}
/**
�* Sets the tool tip text.
�* <p>
�* @param string the new tool tip text (or
null)
�*
�* @exception
SWTError <ul>
�*��������� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread</li>
�*��������� <li>ERROR_WIDGET_DISPOSED when the widget has been
disposed</li>
�*��� </ul>
�*/
public void setToolTipText (String string) {
����� super.setToolTipText(string);
����� table.setToolTipText(string);
}
/**
�* Shows the item.
�* <p>
�* @param item the item to be shown
�*
�* @exception
SWTError <ul>
�*��� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread
�*��� <li>ERROR_WIDGET_DISPOSED when the
widget has been disposed
�*��� <li>ERROR_NULL_ARGUMENT when item is
null
�* </ul>
�*/
public void showItem (TableTreeItem item) {
����� if (item == null) throw new SWTError
(SWT.ERROR_NULL_ARGUMENT);
����� if (!item.getVisible()) expandItem (item);
����� TableItem
tableItem = item.tableItem;
����� table.showItem(tableItem);
}
/**
�* Shows the selection.
�* <p>
�*
If there is no selection or the selection
�* is already visible, this method does nothing.
�* If the selection is scrolled out of view,
�* the top index of the widget is changed such
�* that selection becomes visible.
�*
�* @exception
SWTError <ul>
�*��� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread
�*��� <li>ERROR_WIDGET_DISPOSED when the
widget has been disposed
�* </ul>
�*/
public void showSelection () {
����� table.showSelection();
}
}
package org.eclipse.swt.custom;
/*
�* (c) Copyright IBM Corp. 2000, 2001.
�* All Rights Reserved
�*/
import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
/**
�* A TableTreeItem is a selectable user interface object
�* that represents an item in a heirarchy of items in a
�* TableTree.
�*/
public class TableTreeItem extends Item {
����� TableItem
tableItem;
����� TableTree
parent;
����� TableTreeItem
parentItem;
����� TableTreeItem
[] items = TableTree.EMPTY_ITEMS;
����� String[]
texts = TableTree.EMPTY_TEXTS;
����� Image[]
images = TableTree.EMPTY_IMAGES;
����� boolean expanded;
����� boolean checked;
/**
�* Create a new instance of a root item.
�*
�* @param
parent the
TableTree that contains this root item
�* @param
style the bitwise
OR'ing of widget styles
�*/
public TableTreeItem(TableTree parent, int style) {
����� this (parent, style,
parent.getItemCount());
}
/**
�* Create a new instance of a root item in the position
�* indicated by the specified index.
�*
�* @param
parent the
TableTree that contains this root item
�* @param
style the bitwise
OR'ing of widget styles
�* @param
index specifies
the position of this item in the TableTree
�* �� relative to other root
items
�*/
public TableTreeItem(TableTree parent, int style, int index) {
����� this (parent, null, style, index);
}
/**
�* Create a new instance of a sub item.
�*
�* @param
parent this
item's parent in the hierarchy of TableTree items
�* @param
style the bitwise
OR'ing of widget styles
�*/
public TableTreeItem(TableTreeItem
parent, int style) {
����� this (parent, style,
parent.getItemCount());
}
/**
�* Create a new instance of a sub item in the position
�* indicated by the specified index.
�*
�* @param
parent this
item's parent in the hierarchy of TableTree items
�* @param
style the bitwise
OR'ing of widget styles
�* @param
index specifies
the position of this item in the TableTree
�* �� relative to other
children of the same parent
�*/
public TableTreeItem(TableTreeItem
parent, int style, int index) {
����� this (parent.getParent(), parent,
style, index);
}
TableTreeItem(TableTree parent,
TableTreeItem parentItem, int style, int index) {
����� super(parent, style);
����� this.parent = parent;
����� this.parentItem = parentItem;
����� if (parentItem == null) {
�����������
����������� /* Root items are visible
immediately */
����������� int
tableIndex =
parent.addItem(this, index);
����������� tableItem
= new TableItem(parent.getTable(),
style, tableIndex);
����������� tableItem.setData(this);
����������� addCheck();
����������� /*
����������� *
Feature in the Table.� The table uses
the first image that
����������� *
is inserted into the table to size the table rows.� If the
����������� *
user is allowed to insert the first image, this will cause
����������� *
the +/- images to be scaled.� The fix is
to insert a dummy
����������� *
image to force the size.
����������� */
����������� if
(parent.sizeImage
== null) {
����������������� int itemHeight = parent.getItemHeight();
����������������� parent.sizeImage
= new Image(null, itemHeight, itemHeight);
����������������� GC
gc = new GC (parent.sizeImage);
����������������� gc.setBackground(parent.getBackground());
����������������� gc.fillRectangle(0,
0, itemHeight, itemHeight);
����������������� gc.dispose();
����������������� tableItem.setImage(0,
parent.sizeImage);
����������� }
����� }
else {
����������� parentItem.addItem(this, index);
����� }
}
void addCheck() {
����� Table
table = parent.getTable();
����� if ((table.getStyle() & SWT.CHECK) == 0) return;
����� tableItem.setChecked(checked);
}
void addItem(TableTreeItem item, int index) {
����� if (item == null) throw new SWTError(SWT.ERROR_NULL_ARGUMENT);
����� if (index < 0 || index > items.length) throw new SWTError(SWT.ERROR_INVALID_ARGUMENT);
�����������
����� /* Now that item has a sub-node it
must indicate that it can be expanded */
����� if
(items.length ==
0 && index == 0) {
����������� if (tableItem != null) {
����������������� Image
image = expanded ? parent.getMinusImage() : parent.getPlusImage();
����������������� tableItem.setImage(0,
image);
����������� }
����� }
�����
����� /* Put the item in the items list
*/
����� TableTreeItem[]
newItems = new TableTreeItem[items.length + 1];
����� System.arraycopy(items,
0, newItems, 0, index);
����� newItems[index]
= item;
����� System.arraycopy(items,
index, newItems, index + 1, items.length - index);
����� items
= newItems;
����� if (expanded) item.setVisible(true);
}
/**
�* Gets the widget bounds at the specified index.
�* <p>
�* @return the widget bounds at the specified
index
�*
�* @exception
SWTError <ul>
�*��������� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread</li>
�*��������� <li>ERROR_WIDGET_DISPOSED when the widget has been
disposed</li>
�*��� </ul>
�*/
public Rectangle getBounds (int index) {
����� if (tableItem != null) {
����������� return tableItem.getBounds(index);
����� }
else {
����������� return new Rectangle(0, 0, 0, 0);
����� }
}
/**
* Gets the checked state.
* <p>
* @return the item checked state.
*
* @exception SWTError <ul>
*���������� <li>ERROR_THREAD_INVALID_ACCESS when
called from the wrong thread</li>
*���������� <li>ERROR_WIDGET_DISPOSED when the
widget has been disposed</li>
*���� </ul>
*/
public boolean getChecked () {
����� if (tableItem == null) {
����������� return checked;
����� }
����� return tableItem.getChecked();
}
/**
�* Gets the Display.
�* <p>
�*
This method gets the Display that is associated
�* with the widget.
�*
�* @return
the widget data
�*
�* @exception
SWTError <ul>
�*��������� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread</li>
�*��������� <li>ERROR_WIDGET_DISPOSED when the widget has been
disposed</li>
�*��� </ul>
�*/
public Display getDisplay () {
����� TableTree
parent = this.parent;
����� if (parent == null) throw new SWTError
(SWT.ERROR_WIDGET_DISPOSED);
����� return parent.getDisplay ();
}
/**
�* Gets the expanded state of the widget.
�* <p>
�* @return a boolean that is the expanded
state of the widget
�*/
public boolean getExpanded () {
����� return expanded;
}
/**
�* Gets the first image.
�* <p>
�*
The image in column 0 is reserved for the [+] and [-]
�* images of the tree, therefore getImage(0) will return null.
�*
�* @return
the image at
index 0
�*/
public Image getImage () {
����� return getImage(0);
}
/**
�* Gets the image at the specified index.
�* <p>
�*
Indexing is zero based. The image can be null.
�* The image in column 0 is reserved for the [+] and [-]
�* images of the tree, therefore getImage(0) will return null.
�* Return null if the index is out of range.
�*
�* @param
index the index
of the image
�* @return
the image at the
specified index or null
�*/
public Image getImage (int index) {
����� if (0 < index && index < images.length) return images[index];
����� return null;
}
int getIndent() {
����� if (parentItem == null) return 0;
����� return parentItem.getIndent() + 1;
}
/**
�* Gets the number of sub items.
�* <p>
�* @return the number of sub items
�*/
public int getItemCount () {
����� return items.length;
}
/**
�* Gets the sub items.
�* <p>
�* @return the sub items
�*/
public TableTreeItem[] getItems () {
����� TableTreeItem[]
newItems = new TableTreeItem[items.length];
����� System.arraycopy(items,
0, newItems, 0, items.length);
����� return newItems;
}
TableTreeItem getItem(TableItem
tableItem) {
����� if (tableItem == null) return null;
����� if (this.tableItem ==
tableItem) return this;
����� for (int i = 0; i <
items.length; i++) {
����������� TableTreeItem
item =� items[i].getItem(tableItem);
����� ��� � if (item != null) return item;
����� }
����� return null;
}
/**
�* Gets the parent.
�* <p>
�* @return the parent
�*/
public TableTree getParent () {
����� return parent;
}
/**
�* Gets the parent item.
�* <p>
�* @return the parent item.
�*/
public TableTreeItem getParentItem () {
����� return parentItem;
}
/**
�* Gets the first item text.
�* <p>
�* @return the item text at index 0, which
can be null
�*
�* @exception
SWTError <ul>
�*��������� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread</li>
�*��������� <li>ERROR_WIDGET_DISPOSED when the widget has been
disposed</li>
�* �������� <li>ERROR_CANNOT_GET_TEXT when the operation fails</li>
�*��� </ul>
�*/
public String getText () {
����� return getText(0);
}
/**
�* Gets the item text at the specified index.
�* <p>
�*
Indexing is zero based.
�*
�* This operation will fail when the index is out
�* of range or an item could not be queried from
�* the OS.
�*
�* @param
index the index
of the item
�* @return
the item text at
the specified index, which can be null
�*/
public String getText(int index) {
����� if (0 <= index && index < texts.length) return texts[index];
����� return null;
}
boolean getVisible () {
����� return tableItem != null;
}
/**
�* Gets the index of the specified item.
�*
�* <p>The widget is searched starting at
0 until an
�* item is found that is equal to the search item.
�* If no item is found, -1 is returned.� Indexing
�* is zero based.� This
index is relative to the parent only.
�*
�* @param
item the search
item
�* @return
the index of the
item or -1 if the item is not found
�*
�*/
public int indexOf (TableTreeItem item) {
����� for (int i = 0; i <
items.length; i++) {
����������� if (items[i] == item) return i;
����� }
����� return -1;
}
int expandedIndexOf (TableTreeItem item) {�����
����� int index = 0;
����� for (int i = 0; i <
items.length; i++) {
����������� if (items[i] == item) return index;
����������� if (items[i].expanded) index +=
items[i].visibleChildrenCount ();
����������� index++;
����� }
����� return -1;
}
int visibleChildrenCount () {
����� int count = 0;
����� for (int i = 0; i <
items.length; i++) {
����������� if (items[i].getVisible ()) {
����������������� count
+= 1 + items[i].visibleChildrenCount ();
����������� }
����� }
����� return count;
}
public void dispose () {
����� for (int i = items.length
- 1; i >= 0; i--) {
����������� items[i].dispose();
����� }
����� super.dispose();
����� if (!parent.inDispose) {
����������� if (parentItem != null) {
����������������� parentItem.removeItem(this);
����������� }
else {
����������������� parent.removeItem(this);
����������� }
����������� if (tableItem != null) tableItem.dispose();
����� }
����� items
= null;
����� parentItem
= null;
����� parent
= null;
����� images
= null;
����� texts
= null;
����� tableItem
= null;
}
void removeItem(TableTreeItem item) {
����� int index = 0;
����� while (index < items.length
&& items[index] != item) index++;
����� if (index == items.length) return;
����� TableTreeItem[]
newItems = new TableTreeItem[items.length - 1];
����� System.arraycopy(items,
0, newItems, 0, index);
����� System.arraycopy(items,
index + 1, newItems, index, items.length - index - 1);
����� items
= newItems;
����� if (items.length == 0) {
����������� if (tableItem != null) tableItem.setImage(0, null);
����� }
}
/**
* Sets the checked state.
* <p>
* @param checked the new checked state.
*
* @exception SWTError <ul>
*���������� <li>ERROR_THREAD_INVALID_ACCESS when
called from the wrong thread</li>
*���������� <li>ERROR_WIDGET_DISPOSED when the
widget has been disposed</li>
*���� </ul>
*/
public void setChecked (boolean checked) {
����� if (tableItem != null) {
����������� tableItem.setChecked(checked);
����� }
����� this.checked = checked;
}
/**
�* Sets the expanded state.
�* <p>
�* @param expanded the new expanded state.
�*
�* @exception
SWTError <ul>
�*��������� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread</li>
�*��������� <li>ERROR_WIDGET_DISPOSED when the widget has been
disposed</li>
�*��� </ul>
�*/
public void setExpanded (boolean expanded) {
����� if (items.length == 0) return;
����� this.expanded = expanded;
����� if (tableItem == null) return;
����� parent.setRedraw(false);
����� for (int i = 0; i <
items.length; i++) {
����������� items[i].setVisible(expanded);
����� }
����� Image
image = expanded ? parent.getMinusImage() : parent.getPlusImage();
����� tableItem.setImage(0,
image);
����� parent.setRedraw(true);
}
/**
�* Sets the image at an index.
�* <p>
�*
The image can be null.
�* The image in column 0 is reserved for the [+] and [-]
�* images of the tree, therefore do nothing if index is 0.
�*
�* @param
image the new
image or null
�*
�* @exception
SWTError <ul>
�*��������� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread</li>
�*��������� <li>ERROR_WIDGET_DISPOSED when the widget has been
disposed</li>
�*��� </ul>
�*/
public void setImage (int index, Image image) {
����� int columnCount =
Math.max(parent.getTable().getColumnCount(), 1);
����� if (index <= 0 || index >= columnCount) return;
����� if (images.length < columnCount) {
����������� Image[]
newImages = new
Image[columnCount];
����������� System.arraycopy(images,
0, newImages, 0, images.length);
����������� images
= newImages;
����� }
����� images[index]
= image;
����� if (tableItem != null) tableItem.setImage(index, image);
}
/**
�* Sets the first image.
�* <p>
�*
The image can be null.
�* The image in column 0 is reserved for the [+] and [-]
�* images of the tree, therefore do nothing.
�*
�* @param
image the new
image or null
�*/
public void setImage (Image image) {
����� setImage(0,
image);
}
/**
�* Sets the widget text.
�* <p>
�*
�* The widget text for an item is the label of the
�* item or the label of the text specified by a column
�* number.
�*
�* @param
index the column
number
�* @param
text the new text
�*
�* @exception
SWTError <ul>
�*��������� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread</li>
�*��������� <li>ERROR_WIDGET_DISPOSED when the widget has been
disposed</li>
�*��������� <li>ERROR_NULL_ARGUMENT when string is null</li>
�*��� </ul>
�*/
public void setText(int index, String text) {
����� int columnCount =
Math.max(parent.getTable().getColumnCount(), 1);
����� if (index < 0 || index >= columnCount) return;
����� if (texts.length < columnCount) {
����������� String[]
newTexts = new String[columnCount];
����������� System.arraycopy(texts,
0, newTexts, 0, texts.length);
����������� texts
= newTexts;
����� }
����� texts[index]
= text;
����� if (tableItem != null) tableItem.setText(index, text);
}
/**
�* Sets the widget text.
�* <p>
�*
�* The widget text for an item is the label of the
�* item or the label of the text specified by a column
�* number.
�*
�* @param
index the column
number
�* @param
text the new text
�*
�* @exception
SWTError <ul>
�*��������� <li>ERROR_THREAD_INVALID_ACCESS when called from the wrong
thread</li>
�*��������� <li>ERROR_WIDGET_DISPOSED when the widget has been
disposed</li>
�*��������� <li>ERROR_NULL_ARGUMENT when string is null</li>
�*��� </ul>
�*/
public void setText (String string) {
����� setText(0,
string);
}
void setVisible (boolean show) {
����� if (parentItem == null) return; // this is a root and can not be toggled between
visible and hidden
����� if (getVisible() == show) return;
����� if (show) {
����������� if (!parentItem.getVisible()) return; // parentItem must already be visible
����������� //
create underlying table item and set data in table item to stored data
����������� Table table = parent.getTable();
����������� int parentIndex = table.indexOf(parentItem.tableItem);
����������� int index = parentItem.expandedIndexOf(this) + parentIndex + 1;
����������� if (index < 0) return;
����������� tableItem
= new TableItem(table, getStyle(),
index);
����������� tableItem.setData(this);
����������� tableItem.setImageIndent(getIndent());
����������� addCheck();
����������� // restore fields to item
����������� //
ignore any images in the first column
����������� int columnCount = Math.max(table.getColumnCount(), 1);
����������� for (int i = 0; i <
columnCount; i++) {
����������������� if (i < texts.length && texts[i] != null) setText(i, texts[i]);
����������������� if (i < images.length && images[i] != null) setImage(i, images[i]);
����������� }
����������� // display the children and the
appropriate [+]/[-] symbol as required
����������� if (items.length != 0) {
����������������� if (expanded) {
����������������������� tableItem.setImage(0,
parent.getMinusImage());
����������������������� for (int i = 0, length =
items.length; i < length; i++) {
����������������������������� items[i].setVisible(true);
����������������������� }
����������������� }
else {
����������������������� tableItem.setImage(0,
parent.getPlusImage());
����������������� }
����������� }
�����������
����� }
else {
����������� for (int i = 0, length =
items.length; i < length; i++) {
����������������� items[i].setVisible(false);
����������� }
����������� // remove row from table
����������� tableItem.dispose();
����������� tableItem
= null;
����� }
}
}