package org.eclipse.swt.widgets; /* * Copyright (c) 2000, 2002 IBM Corp. All rights reserved. * This file is made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html */ import org.eclipse.swt.*; import org.eclipse.swt.internal.*; import org.eclipse.swt.internal.gtk.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.events.*; /** * Instances of this class implement a selectable user interface * object that displays a list of images and strings and issue * notificiation when selected. *

* The item children that may be added to instances of this class * must be of type TableItem. *

* Note that although this class is a subclass of Composite, * it does not make sense to add Control children to it, * or set a layout on it. *

*

*
Styles:
*
SINGLE, MULTI, CHECK, FULL_SELECTION, HIDE_SELECTION
*
Events:
*
Selection, DefaultSelection
*
*

* Note: Only one of the styles SINGLE, and MULTI may be specified. *

* IMPORTANT: This class is not intended to be subclassed. *

*/ public class Table extends Composite { int modelHandle, checkRenderer; int itemCount, columnCount; TableItem [] items; TableColumn [] columns; ImageList imageList; /** * Constructs a new instance of this class given its parent * and a style value describing its behavior and appearance. *

* The style value is either one of the style constants defined in * class SWT which is applicable to instances of this * class, or must be built by bitwise OR'ing together * (that is, using the int "|" operator) two or more * of those SWT style constants. The class description * lists the style constants that are applicable to the class. * Style bits are also inherited from superclasses. *

* * @param parent a composite control which will be the parent of the new instance (cannot be null) * @param style the style of control to construct * * @exception IllegalArgumentException * @exception SWTException * * @see SWT#SINGLE * @see SWT#MULTI * @see SWT#CHECK * @see SWT#FULL_SELECTION * @see SWT#HIDE_SELECTION * @see Widget#checkSubclass * @see Widget#getStyle */ public Table (Composite parent, int style) { super (parent, checkStyle (style)); } static int checkStyle (int style) { /* * To be compatible with Windows, force the H_SCROLL * and V_SCROLL style bits. On Windows, it is not * possible to create a table without scroll bars. */ style |= SWT.H_SCROLL | SWT.V_SCROLL; return checkBits (style, SWT.SINGLE, SWT.MULTI, 0, 0, 0, 0); } /** * Adds the listener to the collection of listeners who will * be notified when the receiver's selection changes, by sending * it one of the messages defined in the SelectionListener * interface. *

* When widgetSelected is called, the item field of the event object is valid. * If the reciever has SWT.CHECK style set and the check selection changes, * the event object detail field contains the value SWT.CHECK. * widgetDefaultSelected is typically called when an item is double-clicked. * The item field of the event object is valid for default selection, but the detail field is not used. *

* * @param listener the listener which should be notified * * @exception IllegalArgumentException * @exception SWTException * * @see SelectionListener * @see #removeSelectionListener * @see SelectionEvent */ public void addSelectionListener (SelectionListener listener) { checkWidget(); if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); TypedListener typedListener = new TypedListener (listener); addListener (SWT.Selection,typedListener); addListener (SWT.DefaultSelection,typedListener); } public Point computeSize (int wHint, int hHint, boolean changed) { checkWidget (); Point size = computeNativeSize(handle, wHint, hHint, changed); Rectangle trim = computeTrim (0, 0, size.x, size.y); size.x = trim.width; size.y = trim.height; return size; } void createHandle (int index) { state |= HANDLE; fixedHandle = OS.gtk_fixed_new (); if (fixedHandle == 0) error (SWT.ERROR_NO_HANDLES); OS.gtk_fixed_set_has_window (fixedHandle, true); scrolledHandle = OS.gtk_scrolled_window_new (0, 0); if (scrolledHandle == 0) error (SWT.ERROR_NO_HANDLES); /* * Columns: * 0 - check * 1 - foreground * 2 - background * 3 - text * 4 - pixbuf * 5 - ... */ int [] types = getColumnTypes (1); modelHandle = OS.gtk_list_store_newv (types.length, types); if (modelHandle == 0) error (SWT.ERROR_NO_HANDLES); handle = OS.gtk_tree_view_new_with_model (modelHandle); if (handle == 0) error (SWT.ERROR_NO_HANDLES); if ((style & SWT.CHECK) != 0) { checkRenderer = OS.gtk_cell_renderer_toggle_new (); if (checkRenderer == 0) error (SWT.ERROR_NO_HANDLES); OS.g_object_ref (checkRenderer); } createColumn (null, 0); int parentHandle = parent.parentingHandle (); OS.gtk_container_add (parentHandle, fixedHandle); OS.gtk_container_add (fixedHandle, scrolledHandle); OS.gtk_container_add (scrolledHandle, handle); OS.gtk_widget_show (fixedHandle); OS.gtk_widget_show (scrolledHandle); OS.gtk_widget_show (handle); int mode = (style & SWT.MULTI) != 0 ? OS.GTK_SELECTION_MULTIPLE : OS.GTK_SELECTION_BROWSE; int selectionHandle = OS.gtk_tree_view_get_selection (handle); OS.gtk_tree_selection_set_mode (selectionHandle, mode); OS.gtk_tree_view_set_headers_visible (handle, false); int hsp = (style & SWT.H_SCROLL) != 0 ? OS.GTK_POLICY_AUTOMATIC : OS.GTK_POLICY_NEVER; int vsp = (style & SWT.V_SCROLL) != 0 ? OS.GTK_POLICY_AUTOMATIC : OS.GTK_POLICY_NEVER; OS.gtk_scrolled_window_set_policy (scrolledHandle, hsp, vsp); if ((style & SWT.BORDER) != 0) OS.gtk_scrolled_window_set_shadow_type (scrolledHandle, OS.GTK_SHADOW_ETCHED_IN); } void createColumn (TableColumn column, int index) { int modelIndex = 3; if (columnCount != 0) { int modelLength = OS.gtk_tree_model_get_n_columns (modelHandle); boolean [] usedColumns = new boolean [modelLength]; for (int i=0; i 0) { TableColumn checkColumn = columns [0]; createRenderers (checkColumn.handle, checkColumn.modelIndex, false); } createRenderers (columnHandle, modelIndex, index == 0); OS.gtk_tree_view_column_set_resizable (columnHandle, true); OS.gtk_tree_view_column_set_clickable (columnHandle, true); OS.gtk_tree_view_insert_column (handle, columnHandle, index); if (column != null) { column.handle = columnHandle; column.modelIndex = modelIndex; } } void createRenderers (int columnHandle, int modelIndex, boolean check) { OS.gtk_tree_view_column_clear (columnHandle); if ((style & SWT.CHECK) != 0 && check) { OS.gtk_tree_view_column_pack_start (columnHandle, checkRenderer, false); OS.gtk_tree_view_column_add_attribute (columnHandle, checkRenderer, "active", 0); } int pixbufRenderer = OS.gtk_cell_renderer_pixbuf_new (); if (pixbufRenderer == 0) error (SWT.ERROR_NO_HANDLES); OS.gtk_tree_view_column_pack_start (columnHandle, pixbufRenderer, false); OS.gtk_tree_view_column_add_attribute (columnHandle, pixbufRenderer, "pixbuf", modelIndex); /* * Feature on GTK. When a tree view column contains only one activatable * cell renderer such as a toggle renderer, mouse clicks anywhere in a cell * activate that renderer. The workaround is to set a second cell renderer * to be activatable. */ if ((style & SWT.CHECK) != 0 && check) { OS.g_object_set (pixbufRenderer, OS.mode, OS.GTK_CELL_RENDERER_MODE_ACTIVATABLE); } int textRenderer = OS.gtk_cell_renderer_text_new (); if (textRenderer == 0) error (SWT.ERROR_NO_HANDLES); OS.gtk_tree_view_column_pack_start (columnHandle, textRenderer, true); OS.gtk_tree_view_column_add_attribute (columnHandle, textRenderer, "text", modelIndex + 1); OS.gtk_tree_view_column_add_attribute (columnHandle, textRenderer, "foreground-gdk", 1); OS.gtk_tree_view_column_add_attribute (columnHandle, textRenderer, "background-gdk", 2); } void createItem (TableColumn column, int index) { if (!(0 <= index && index <= columnCount)) error (SWT.ERROR_INVALID_RANGE); if (columnCount == 0) { column.handle = OS.gtk_tree_view_get_column (handle, 0); column.modelIndex = 3; } else { createColumn (column, index); } if (columnCount == columns.length) { TableColumn [] newColumns = new TableColumn [columns.length + 4]; System.arraycopy (columns, 0, newColumns, 0, columns.length); columns = newColumns; } System.arraycopy (columns, index, columns, index + 1, columnCount++ - index); columns [index] = column; } void createItem (TableItem item, int index) { if (!(0 <= index && index <= itemCount)) error (SWT.ERROR_INVALID_RANGE); if (itemCount == items.length) { TableItem [] newItems = new TableItem [items.length + 4]; System.arraycopy (items, 0, newItems, 0, items.length); items = newItems; } item.handle = OS.g_malloc (OS.GtkTreeIter_sizeof ()); if (item.handle == 0) error (SWT.ERROR_NO_HANDLES); OS.gtk_list_store_insert (modelHandle, item.handle, index); System.arraycopy (items, index, items, index + 1, itemCount++ - index); items [index] = item; } void createWidget (int index) { super.createWidget (index); items = new TableItem [4]; columns = new TableColumn [4]; itemCount = columnCount = 0; } GdkColor defaultBackground () { Display display = getDisplay (); return display.COLOR_LIST_BACKGROUND; } GdkColor defaultForeground () { Display display = getDisplay (); return display.COLOR_LIST_FOREGROUND; } void deregister() { super.deregister (); WidgetTable.remove (OS.gtk_tree_view_get_selection (handle)); if (checkRenderer != 0) WidgetTable.remove (checkRenderer); } /** * Deselects the item at the given zero-relative index in the receiver. * If the item at the index was already deselected, it remains * deselected. Indices that are out of range are ignored. * * @param index the index of the item to deselect * * @exception SWTException */ public void deselect (int index) { checkWidget(); if (index < 0 || index >= itemCount) return; int selection = OS.gtk_tree_view_get_selection (handle); OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED); OS.gtk_tree_selection_unselect_iter (selection, items [index].handle); OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED); } /** * Deselects the items at the given zero-relative indices in the receiver. * If the item at the given zero-relative index in the receiver * is selected, it is deselected. If the item at the index * was not selected, it remains deselected. The range of the * indices is inclusive. Indices that are out of range are ignored. * * @param start the start index of the items to deselect * @param end the end index of the items to deselect * * @exception SWTException */ public void deselect (int start, int end) { checkWidget(); int selection = OS.gtk_tree_view_get_selection (handle); OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED); for (int index=start; index<=end; index++) { if (index < 0 || index >= itemCount) continue; OS.gtk_tree_selection_unselect_iter (selection, items [index].handle); } OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED); } /** * Deselects the items at the given zero-relative indices in the receiver. * If the item at the given zero-relative index in the receiver * is selected, it is deselected. If the item at the index * was not selected, it remains deselected. Indices that are out * of range and duplicate indices are ignored. * * @param indices the array of indices for the items to deselect * * @exception IllegalArgumentException * @exception SWTException */ public void deselect (int [] indices) { checkWidget(); if (indices == null) error (SWT.ERROR_NULL_ARGUMENT); int selection = OS.gtk_tree_view_get_selection (handle); OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED); for (int i=0; i= itemCount) continue; OS.gtk_tree_selection_unselect_iter (selection, items [index].handle); } OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED); } /** * Deselects all selected items in the receiver. * * @exception SWTException */ public void deselectAll () { checkWidget(); int selection = OS.gtk_tree_view_get_selection (handle); OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED); OS.gtk_tree_selection_unselect_all (selection); OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED); } void destroyItem (TableColumn column) { int index = 0; while (index < columnCount) { if (columns [index] == column) break; index++; } if (index == columnCount) return; int columnHandle = column.handle; System.arraycopy (columns, index + 1, columns, index, --columnCount - index); columns [columnCount] = null; OS.gtk_tree_view_remove_column (handle, columnHandle); if (columnCount == 0) { int oldModel = modelHandle; int[] types = getColumnTypes (1); int newModel = OS.gtk_list_store_newv (types.length, types); if (newModel == 0) error (SWT.ERROR_NO_HANDLES); int [] ptr = new int [1]; for (int i=0; iTableColumns were created by the programmer, * this method will throw ERROR_INVALID_RANGE despite * the fact that a single column of data may be visible in the table. * This occurs when the programmer uses the table like a list, adding * items but never creating a column. * * @param index the index of the column to return * @return the column at the given index * * @exception IllegalArgumentException
    *
  • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
  • *
* @exception SWTException
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • *
*/ public TableColumn getColumn (int index) { checkWidget(); if (!(0 <= index && index < columnCount)) error (SWT.ERROR_CANNOT_GET_ITEM); return columns [index]; } /** * Returns the number of columns contained in the receiver. * If no TableColumns were created by the programmer, * this value is zero, despite the fact that visually, one column * of items is may be visible. This occurs when the programmer uses * the table like a list, adding items but never creating a column. * * @return the number of columns * * @exception SWTException
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • *
* @exception SWTError
    *
  • ERROR_CANNOT_GET_COUNT - if the operation fails because of an operating system failure
  • *
*/ public int getColumnCount () { checkWidget(); return columnCount; } int[] getColumnTypes (int n) { int[] types = new int [(n * 2) + 3]; types [0] = OS.G_TYPE_BOOLEAN (); types [1] = types [2] = OS.GDK_TYPE_COLOR (); for (int i=3; iTableColumns which are the * columns in the receiver. If no TableColumns were * created by the programmer, the array is empty, despite the fact * that visually, one column of items may be visible. This occurs * when the programmer uses the table like a list, adding items but * never creating a column. *

* Note: This is not the actual structure used by the receiver * to maintain its list of items, so modifying the array will * not affect the receiver. *

* * @return the items in the receiver * * @exception SWTException
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • *
*/ public TableColumn [] getColumns () { checkWidget(); TableColumn [] result = new TableColumn [columnCount]; System.arraycopy (columns, 0, result, 0, columnCount); return result; } TableItem getFocusItem () { int [] path = new int [1]; OS.gtk_tree_view_get_cursor (handle, path, null); if (path [0] == 0) return null; TableItem item = null; int indices = OS.gtk_tree_path_get_indices (path [0]); if (indices != 0) { int [] index = new int []{-1}; OS.memmove (index, indices, 4); item = items [index [0]]; } OS.gtk_tree_path_free (path [0]); return item; } GdkColor getForegroundColor () { return getTextColor (); } /** * Returns the width in pixels of a grid line. * * @exception SWTException
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • *
*/ public int getGridLineWidth () { checkWidget(); return 0; } /** * Returns the height of the receiver's header * * @return the height of the header or zero if the header is not visible * * @exception SWTException
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • *
* * @since 2.0 */ public int getHeaderHeight () { checkWidget (); if (!OS.gtk_tree_view_get_headers_visible (handle)) return 0; OS.gtk_widget_realize (handle); int fixedWindow = OS.GTK_WIDGET_WINDOW (fixedHandle); int binWindow = OS.gtk_tree_view_get_bin_window (handle); int [] binY = new int [1]; OS.gdk_window_get_origin (binWindow, null, binY); int [] fixedY = new int [1]; OS.gdk_window_get_origin (fixedWindow, null, fixedY); return binY [0] - fixedY [0]; } /** * Returns true if the receiver's header is visible, * and false otherwise. *

* If one of the receiver's ancestors is not visible or some * other condition makes the receiver not visible, this method * may still indicate that it is considered visible even though * it may not actually be showing. *

* * @return the receiver's header's visibility state * * @exception SWTException
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • *
*/ public boolean getHeaderVisible () { checkWidget(); return OS.gtk_tree_view_get_headers_visible (handle); } /** * Returns the item at the given, zero-relative index in the * receiver. Throws an exception if the index is out of range. * * @param index the index of the item to return * @return the item at the given index * * @exception IllegalArgumentException
    *
  • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
  • *
* @exception SWTException
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • *
*/ public TableItem getItem (int index) { checkWidget(); if (!(0 <= index && index < itemCount)) error (SWT.ERROR_INVALID_RANGE); return items [index]; } /** * Returns the item at the given point in the receiver * or null if no such item exists. The point is in the * coordinate system of the receiver. * * @param point the point used to locate the item * @return the item at the given point * * @exception IllegalArgumentException
    *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • *
* @exception SWTException
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • *
*/ public TableItem getItem (Point pt) { checkWidget(); int [] path = new int [1]; int clientY = pt.y - getHeaderHeight (); if (!OS.gtk_tree_view_get_path_at_pos (handle, pt.x, clientY, path, null, null, null)) return null; if (path [0] == 0) return null; int indices = OS.gtk_tree_path_get_indices (path [0]); TableItem item = null; if (indices != 0) { int [] index = new int [1]; OS.memmove (index, indices, 4); item = items [index [0]]; } OS.gtk_tree_path_free (path [0]); return item; } /** * Returns the number of items contained in the receiver. * * @return the number of items * * @exception SWTException
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • *
*/ public int getItemCount () { checkWidget (); return itemCount; } /** * Returns the height of the area which would be used to * display one of the items in the receiver's. * * @return the height of one item * * @exception SWTException
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • *
*/ public int getItemHeight () { checkWidget(); // FIXME // I (bgs) am not sure what to do with this. // In GTK2, rows may have different heights, so asking // this question will only make sense given the item. if (itemCount == 0) return 15; GdkRectangle rect = new GdkRectangle (); int path = OS.gtk_tree_path_new_first (); OS.gtk_tree_view_get_cell_area (handle, path, 0, rect); OS.gtk_tree_path_free (path); return rect.height; } /** * Returns an array of TableItems which are the items * in the receiver. *

* Note: This is not the actual structure used by the receiver * to maintain its list of items, so modifying the array will * not affect the receiver. *

* * @return the items in the receiver * * @exception SWTException
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • *
*/ public TableItem [] getItems () { checkWidget(); TableItem [] result = new TableItem [itemCount]; System.arraycopy (items, 0, result, 0, itemCount); return result; } /** * Returns true if the receiver's lines are visible, * and false otherwise. *

* If one of the receiver's ancestors is not visible or some * other condition makes the receiver not visible, this method * may still indicate that it is considered visible even though * it may not actually be showing. *

* * @return the visibility state of the lines * * @exception SWTException
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • *
*/ public boolean getLinesVisible() { checkWidget(); return false; } /** * Returns an array of TableItems that are currently * selected in the receiver. An empty array indicates that no * items are selected. *

* Note: This is not the actual structure used by the receiver * to maintain its selection, so modifying the array will * not affect the receiver. *

* @return an array representing the selection * * @exception SWTException
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • *
*/ public TableItem [] getSelection () { checkWidget(); Display display = getDisplay (); display.treeSelectionLength = 0; display.treeSelection = new int [itemCount]; int selection = OS.gtk_tree_view_get_selection (handle); OS.gtk_tree_selection_selected_foreach (selection, display.treeSelectionProc, handle); TableItem [] result = new TableItem [display.treeSelectionLength]; for (int i=0; i *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • * */ public int getSelectionCount () { checkWidget(); Display display = getDisplay (); display.treeSelectionLength = 0; display.treeSelection = null; int selection = OS.gtk_tree_view_get_selection (handle); OS.gtk_tree_selection_selected_foreach (selection, display.treeSelectionProc, handle); return display.treeSelectionLength; } /** * Returns the zero-relative index of the item which is currently * selected in the receiver, or -1 if no item is selected. * * @return the index of the selected item * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    */ public int getSelectionIndex () { checkWidget(); Display display = getDisplay (); display.treeSelectionLength = 0; display.treeSelection = new int [itemCount]; int selection = OS.gtk_tree_view_get_selection (handle); OS.gtk_tree_selection_selected_foreach (selection, display.treeSelectionProc, handle); if (display.treeSelectionLength == 0) return -1; return display.treeSelection [0]; } /** * Returns the zero-relative indices of the items which are currently * selected in the receiver. The array is empty if no items are selected. *

    * Note: This is not the actual structure used by the receiver * to maintain its selection, so modifying the array will * not affect the receiver. *

    * @return the array of indices of the selected items * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    */ public int [] getSelectionIndices () { checkWidget(); Display display = getDisplay (); display.treeSelectionLength = 0; display.treeSelection = new int [itemCount]; int selection = OS.gtk_tree_view_get_selection (handle); OS.gtk_tree_selection_selected_foreach (selection, display.treeSelectionProc, handle); if (display.treeSelectionLength == display.treeSelection.length) return display.treeSelection; int [] result = new int [display.treeSelectionLength]; System.arraycopy (display.treeSelection, 0, result, 0, display.treeSelectionLength); return result; } /** * Returns the zero-relative index of the item which is currently * at the top of the receiver. This index can change when items are * scrolled or new items are added or removed. * * @return the index of the top item * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    */ public int getTopIndex () { checkWidget(); int [] path = new int [1]; if (!OS.gtk_tree_view_get_path_at_pos (handle, 1, 1, path, null, null, null)) return 0; if (path [0] == 0) return 0; int indices = OS.gtk_tree_path_get_indices (path[0]); int[] index = new int [1]; if (indices != 0) OS.memmove (index, indices, 4); OS.gtk_tree_path_free (path [0]); return index [0]; } int gtk_button_press_event (int widget, int event) { GdkEventButton gdkEvent = new GdkEventButton (); OS.memmove (gdkEvent, event, GdkEventButton.sizeof); if (gdkEvent.window != OS.gtk_tree_view_get_bin_window (handle)) return 0; int headerHeight = getHeaderHeight (); gdkEvent.y += headerHeight; OS.memmove (event, gdkEvent, GdkEventButton.sizeof); int result = super.gtk_button_press_event (widget, event); gdkEvent.y -= headerHeight; OS.memmove (event, gdkEvent, GdkEventButton.sizeof); if (result != 0) return result; /* * Note on GTK. When multiple items are already selected, the default handler * toggles the selection state of the item and clears any former selection. * This is not the desired behaviour when bringing up a popup menu. The * workaround is to detect that case and not run the default handler when the * item is already part of the current selection. */ if (menu != null && (style & SWT.MULTI) != 0) { int button = gdkEvent.button; if (button == 3 && gdkEvent.type == OS.GDK_BUTTON_PRESS) { int [] path = new int [1]; if (OS.gtk_tree_view_get_path_at_pos (handle, (int)gdkEvent.x, (int)gdkEvent.y, path, null, null, null)) { if (path [0] != 0) { int selection = OS.gtk_tree_view_get_selection (handle); if (OS.gtk_tree_selection_path_is_selected (selection, path [0])) result = 1; OS.gtk_tree_path_free (path [0]); } } } } return result; } int gtk_button_release_event (int widget, int event) { GdkEventButton gdkEvent = new GdkEventButton (); OS.memmove (gdkEvent, event, GdkEventButton.sizeof); if (gdkEvent.window != OS.gtk_tree_view_get_bin_window (handle)) return 0; int headerHeight = getHeaderHeight (); gdkEvent.y += headerHeight; OS.memmove (event, gdkEvent, GdkEventButton.sizeof); int result = super.gtk_button_release_event (widget, event); gdkEvent.y -= headerHeight; OS.memmove (event, gdkEvent, GdkEventButton.sizeof); return result; } int gtk_changed (int widget) { TableItem item = getFocusItem (); if (item != null) { Event event = new Event (); event.item = item; postEvent (SWT.Selection, event); } return 0; } int gtk_key_press_event (int widget, int eventPtr) { int result = super.gtk_key_press_event (widget, eventPtr); if (result != 0) return result; /* * Feature in GTK. When an item is default selected using * the return key, GTK does not issue notification. The fix is * to issue this notification when the return key is pressed. */ GdkEventKey keyEvent = new GdkEventKey (); OS.memmove (keyEvent, eventPtr, GdkEventKey.sizeof); int key = keyEvent.keyval; switch (key) { case OS.GDK_Return: case OS.GDK_KP_Enter: { Event event = new Event (); event.item = getFocusItem (); postEvent (SWT.DefaultSelection, event); break; } } return result; } int gtk_motion_notify_event (int widget, int event) { GdkEventButton gdkEvent = new GdkEventButton (); OS.memmove (gdkEvent, event, GdkEventButton.sizeof); if (gdkEvent.window != OS.gtk_tree_view_get_bin_window (handle)) return 0; int headerHeight = getHeaderHeight (); gdkEvent.y += headerHeight; OS.memmove (event, gdkEvent, GdkEventButton.sizeof); int result = super.gtk_motion_notify_event (widget, event); gdkEvent.y -= headerHeight; OS.memmove (event, gdkEvent, GdkEventButton.sizeof); return result; } int gtk_row_activated (int tree, int path, int column) { TableItem item = null; int indices = OS.gtk_tree_path_get_indices (path); if (indices != 0) { int [] index = new int []{-1}; OS.memmove (index, indices, 4); item = items [index [0]]; } Event event = new Event (); event.item = item; postEvent (SWT.DefaultSelection, event); return 0; } int gtk_toggled (int renderer, int pathStr) { int path = OS.gtk_tree_path_new_from_string (pathStr); if (path == 0) return 0; int indices = OS.gtk_tree_path_get_indices (path); if (indices != 0) { int [] index = new int [1]; OS.memmove (index, indices, 4); TableItem item = items [index [0]]; item.setChecked (!item.getChecked ()); Event event = new Event (); event.detail = SWT.CHECK; event.item = item; postEvent (SWT.Selection, event); } OS.gtk_tree_path_free (path); return 0; } void hookEvents () { super.hookEvents (); Display display = getDisplay (); int selection = OS.gtk_tree_view_get_selection(handle); OS.g_signal_connect (selection, OS.changed, display.windowProc2, CHANGED); OS.g_signal_connect (handle, OS.row_activated, display.windowProc4, ROW_ACTIVATED); if (checkRenderer != 0) { OS.g_signal_connect (checkRenderer, OS.toggled, display.windowProc3, TOGGLED); } } /** * Searches the receiver's list starting at the first column * (index 0) until a column is found that is equal to the * argument, and returns the index of that column. If no column * is found, returns -1. * * @param column the search column * @return the index of the column * * @exception IllegalArgumentException
      *
    • ERROR_NULL_ARGUMENT - if the string is null
    • *
    * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    */ public int indexOf (TableColumn column) { checkWidget(); if (column == null) error (SWT.ERROR_NULL_ARGUMENT); for (int i=0; i *
  • ERROR_NULL_ARGUMENT - if the string is null
  • * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    */ public int indexOf (TableItem item) { checkWidget(); if (item == null) error (SWT.ERROR_NULL_ARGUMENT); for (int i=0; itrue if the item is selected, * and false otherwise. Indices out of * range are ignored. * * @param index the index of the item * @return the visibility state of the item at the index * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    */ public boolean isSelected (int index) { checkWidget(); int selection = OS.gtk_tree_view_get_selection (handle); byte [] buffer = Converter.wcsToMbcs (null, Integer.toString (index), true); int path = OS.gtk_tree_path_new_from_string (buffer); boolean answer = OS.gtk_tree_selection_path_is_selected (selection, path); OS.gtk_tree_path_free (path); return answer; } int paintWindow () { OS.gtk_widget_realize (handle); return OS.gtk_tree_view_get_bin_window (handle); } void releaseWidget () { for (int i=0; i *
  • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
  • * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    * @exception SWTError
      *
    • ERROR_ITEM_NOT_REMOVED - if the operation fails because of an operating system failure
    • *
    */ public void remove (int index) { checkWidget(); if (!(0 <= index && index <= itemCount)) error (SWT.ERROR_ITEM_NOT_REMOVED); TableItem item = items [index]; OS.gtk_list_store_remove (modelHandle, item.handle); System.arraycopy (items, index + 1, items, index, --itemCount - index); items [itemCount] = null; item.releaseResources (); } /** * Removes the items from the receiver which are * between the given zero-relative start and end * indices (inclusive). * * @param start the start of the range * @param end the end of the range * * @exception IllegalArgumentException
      *
    • ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)
    • *
    * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    * @exception SWTError
      *
    • ERROR_ITEM_NOT_REMOVED - if the operation fails because of an operating system failure
    • *
    */ public void remove (int start, int end) { checkWidget(); int index = start; while (index <= end) { if (index < 0 || index >= itemCount) break; TableItem item = items [index]; OS.gtk_list_store_remove (modelHandle, item.handle); item.releaseResources (); index++; } System.arraycopy (items, index, items, start, itemCount - index); for (int i=itemCount-(index-start); i *
  • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
  • * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    * @exception SWTError
      *
    • ERROR_ITEM_NOT_REMOVED - if the operation fails because of an operating system failure
    • *
    */ public void remove (int [] indices) { checkWidget(); if (indices == null) error (SWT.ERROR_NULL_ARGUMENT); int [] newIndices = new int [indices.length]; System.arraycopy (indices, 0, newIndices, 0, indices.length); sort (newIndices); int last = -1; for (int i=0; i= itemCount) error (SWT.ERROR_INVALID_RANGE); TableItem item = items [index]; OS.gtk_list_store_remove (modelHandle, item.handle); // BUG - disposed callback could remove an item item.releaseResources (); System.arraycopy (items, index + 1, items, index, --itemCount - index); items [itemCount] = null; last = index; } } } /** * Removes all of the items from the receiver. *

    * @exception SWTException

      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    */ public void removeAll () { checkWidget(); OS.gtk_list_store_clear (modelHandle); int index = itemCount - 1; while (index >= 0) { TableItem item = items [index]; item.releaseResources (); --index; } items = new TableItem [4]; itemCount = 0; } /** * Removes the listener from the collection of listeners who will * be notified when the receiver's selection changes. * * @param listener the listener which should no longer be notified * * @exception IllegalArgumentException
      *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • *
    * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    * * @see SelectionListener * @see #addSelectionListener */ public void removeSelectionListener(SelectionListener listener) { checkWidget(); if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); if (eventTable == null) return; eventTable.unhook (SWT.Selection, listener); eventTable.unhook (SWT.DefaultSelection,listener); } /** * Selects the item at the given zero-relative index in the receiver. * If the item at the index was already selected, it remains * selected. Indices that are out of range are ignored. * * @param index the index of the item to select * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    */ public void select (int index) { checkWidget(); if (index <0 || index >= itemCount) return; int selection = OS.gtk_tree_view_get_selection (handle); OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED); OS.gtk_tree_selection_select_iter (selection, items [index].handle); int path = OS.gtk_tree_model_get_path (modelHandle, items[index].handle); OS.gtk_tree_view_set_cursor (handle, path, 0, false); OS.gtk_tree_path_free (path); OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED); } /** * Selects the items at the given zero-relative indices in the receiver. * If the item at the index was already selected, it remains * selected. The range of the indices is inclusive. Indices that are * out of range are ignored. * * @param start the start of the range * @param end the end of the range * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    */ public void select (int start, int end) { checkWidget(); int selection = OS.gtk_tree_view_get_selection (handle); OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED); for (int index=start; index<=end; index++) { if (index < 0 || index >= itemCount) continue; OS.gtk_tree_selection_select_iter (selection, items [index].handle); if ((style & SWT.SINGLE) != 0) { int path = OS.gtk_tree_model_get_path (modelHandle, items[index].handle); OS.gtk_tree_view_set_cursor (handle, path, 0, false); OS.gtk_tree_path_free (path); } } OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED); } /** * Selects the items at the given zero-relative indices in the receiver. * If the item at the given zero-relative index in the receiver * is not selected, it is selected. If the item at the index * was selected, it remains selected. Indices that are out * of range and duplicate indices are ignored. * * @param indices the array of indices for the items to select * * @exception IllegalArgumentException
      *
    • ERROR_NULL_ARGUMENT - if the array of indices is null
    • *
    * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    */ public void select (int [] indices) { checkWidget(); if (indices == null) error (SWT.ERROR_NULL_ARGUMENT); int selection = OS.gtk_tree_view_get_selection (handle); OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED); for (int i=0; i= itemCount) continue; OS.gtk_tree_selection_select_iter (selection, items [index].handle); if ((style & SWT.SINGLE) != 0) { int path = OS.gtk_tree_model_get_path (modelHandle, items[index].handle); OS.gtk_tree_view_set_cursor (handle, path, 0, false); OS.gtk_tree_path_free (path); break; } } OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED); } /** * Selects all the items in the receiver. * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    */ public void selectAll () { checkWidget(); if ((style & SWT.SINGLE) != 0) return; int selection = OS.gtk_tree_view_get_selection (handle); OS.g_signal_handlers_block_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED); OS.gtk_tree_selection_select_all (selection); OS.g_signal_handlers_unblock_matched (selection, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED); } void setBackgroundColor (GdkColor color) { super.setBackgroundColor (color); OS.gtk_widget_modify_base (handle, 0, color); } boolean setBounds (int x, int y, int width, int height, boolean move, boolean resize) { boolean result = super.setBounds (x, y, width, height, move, resize); /* * Bug on GTK. The tree view sometimes does not get a paint * event or resizes to a one pixel square when resized in a new * shell that is not visible after any event loop has been run. The * problem is intermittent. It doesn't seem to happen the first time * a new shell is created. The fix is to ensure the tree view is realized * after it has been resized. */ OS.gtk_widget_realize (handle); return result; } void setForegroundColor (GdkColor color) { super.setForegroundColor (color); OS.gtk_widget_modify_text (handle, 0, color); } /** * Marks the receiver's header as visible if the argument is true, * and marks it invisible otherwise. *

    * If one of the receiver's ancestors is not visible or some * other condition makes the receiver not visible, marking * it visible may not actually cause it to be displayed. *

    * * @param visible the new visibility state * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    */ public void setHeaderVisible (boolean show) { checkWidget (); OS.gtk_tree_view_set_headers_visible (handle, show); } /** * Marks the receiver's lines as visible if the argument is true, * and marks it invisible otherwise. *

    * If one of the receiver's ancestors is not visible or some * other condition makes the receiver not visible, marking * it visible may not actually cause it to be displayed. *

    * * @param visible the new visibility state * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    */ public void setLinesVisible (boolean show) { checkWidget(); } /** * Selects the item at the given zero-relative index in the receiver. * The current selected is first cleared, then the new item is selected. * * @param index the index of the item to select * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    * * @see Table#deselectAll() * @see Table#select(int) */ public void setSelection (int index) { deselectAll (); select (index); } /** * Selects the items at the given zero-relative indices in the receiver. * The current selected if first cleared, then the new items are selected. * * @param start the start index of the items to select * @param end the end index of the items to select * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    * * @see Table#deselectAll() * @see Table#select(int,int) */ public void setSelection (int start, int end) { deselectAll (); select (start, end); } /** * Selects the items at the given zero-relative indices in the receiver. * The current selected is first cleared, then the new items are selected. * * @param indices the indices of the items to select * * @exception IllegalArgumentException
      *
    • ERROR_NULL_ARGUMENT - if the array of indices is null
    • *
    * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    * * @see Table#deselectAll() * @see Table#select(int[]) */ public void setSelection (int [] indices) { deselectAll (); select (indices); } /** * Sets the receiver's selection to be the given array of items. * The current selected is first cleared, then the new items are * selected. * * @param items the array of items * * @exception IllegalArgumentException
      *
    • ERROR_NULL_ARGUMENT - if the array of items is null
    • *
    • ERROR_INVALID_ARGUMENT - if one of the item has been disposed
    • *
    * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    * * @see Table#deselectAll() * @see Table#select(int) */ public void setSelection (TableItem [] items) { checkWidget(); if (items == null) error (SWT.ERROR_NULL_ARGUMENT); deselectAll (); int length = items.length; if (length == 0) return; if ((style & SWT.SINGLE) != 0) length = 1; for (int i=length-1; i>=0; --i) { int index = indexOf (items [i]); if (index != -1) select (index); } } /** * Sets the zero-relative index of the item which is currently * at the top of the receiver. This index can change when items * are scrolled or new items are added and removed. * * @param index the index of the top item * * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    */ public void setTopIndex (int index) { checkWidget(); if (!(0 <= index && index < itemCount)) return; // FIXME - For some reason, sometimes the tree scrolls to the wrong place int path = OS.gtk_tree_model_get_path (modelHandle, items [index].handle); OS.gtk_tree_view_scroll_to_cell (handle, path, 0, true, 0, 0); OS.gtk_tree_path_free (path); } /** * Shows the item. If the item is already showing in the receiver, * this method simply returns. Otherwise, the items are scrolled until * the item is visible. * * @param item the item to be shown * * @exception IllegalArgumentException
      *
    • ERROR_NULL_ARGUMENT - if the item is null
    • *
    • ERROR_INVALID_ARGUMENT - if the item has been disposed
    • *
    * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    * * @see Table#showSelection() */ public void showItem (TableItem item) { checkWidget (); if (item == null) error (SWT.ERROR_NULL_ARGUMENT); if (item.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT); int path = OS.gtk_tree_model_get_path (modelHandle, item.handle); OS.gtk_tree_view_scroll_to_cell (handle, path, 0, false, 0, 0); OS.gtk_tree_path_free (path); } /** * Shows the selection. If the selection is already showing in the receiver, * this method simply returns. Otherwise, the items are scrolled until * the selection is visible. * * @exception IllegalArgumentException
      *
    • ERROR_NULL_ARGUMENT - if the listener is null
    • *
    * @exception SWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • *
    * * @see Table#showItem(TableItem) */ public void showSelection () { checkWidget(); TableItem [] selection = getSelection (); if (selection.length == 0) return; TableItem item = selection [0]; int path = OS.gtk_tree_model_get_path (modelHandle, item.handle); OS.gtk_tree_view_scroll_to_cell (handle, path, 0, false, 0, 0); OS.gtk_tree_path_free (path); } int treeSelectionProc (int model, int path, int iter, int[] selection, int length) { if (selection != null) { int indices = OS.gtk_tree_path_get_indices (path); if (indices != 0) { int [] index = new int [1]; OS.memmove (index, indices, 4); selection [length] = index [0]; } } return 0; } }