CompositeTable.java
上传用户:hengxinggs
上传日期:2008-01-15
资源大小:212k
文件大小:30k
源码类别:

PlugIns编程

开发平台:

Java

  1. /*
  2.  * Copyright (C) 2005 David Orme <djo@coconut-palm-software.com>
  3.  * 
  4.  * All rights reserved. This program and the accompanying materials
  5.  * are made available under the terms of the Eclipse Public License v1.0
  6.  * which accompanies this distribution, and is available at
  7.  * http://www.eclipse.org/legal/epl-v10.html
  8.  *
  9.  * Contributors:
  10.  *     David Orme                  - Initial API and implementation
  11.  *     Coconut Palm Software, Inc. - API cleanup
  12.  */
  13. package org.eclipse.jface.examples.databinding.compositetable;
  14. import java.lang.reflect.Constructor;
  15. import java.util.ArrayList;
  16. import java.util.LinkedList;
  17. import org.eclipse.swt.SWT;
  18. import org.eclipse.swt.graphics.Color;
  19. import org.eclipse.swt.graphics.Point;
  20. import org.eclipse.swt.widgets.Canvas;
  21. import org.eclipse.swt.widgets.Composite;
  22. import org.eclipse.swt.widgets.Control;
  23. import org.eclipse.swt.widgets.Display;
  24. import org.eclipse.swt.widgets.Layout;
  25. /**
  26.  * Class CompositeTable.  n.  (1) An SWT virtual table control that extends Composite.  
  27.  * (2) An SWT virtual table control that is composed of many Composites, each representing 
  28.  * a header or a row, one below the other.<p>
  29.  * 
  30.  * CompositeTable is designed specifically to work nicely in the Eclipse Visual Editor,
  31.  * but it is equally easy to use in hand-coded layouts.<p>
  32.  * 
  33.  * <b>Synopsis:</b><p>
  34.  * 
  35.  * In order to edit anything, one must:<p>
  36.  * 
  37.  * <ul>
  38.  * <li>Extend Composite or Canvas and create an object that can be duplicated to 
  39.  * represent the rows in your table.
  40.  * <li>Optionally, extend Composite or Canvas and create a header object in the
  41.  * same way.
  42.  * <li>If the canvas and row objects do not have a layout manager, the CompositeTable 
  43.  * will automatically supply one that lays out child controls in a visual table.  If
  44.  * they have a layout manager, CompositeTable will let them use that.
  45.  * <li>Create a CompositeTable object, either using VE or using hand-coded SWT.
  46.  * <li>Drop the header (if applicable), then the row object on the CompositeTable or
  47.  * simply write code that creates instances of these objects in that order as child
  48.  * controls of your CompositeTable.
  49.  * <li>Set the RunTime property to "true".  Your control is now "live."
  50.  * <li>Add a RowConstructionListener if you need to add event handlers to individual row 
  51.  * controls when a row is created.
  52.  * <li>Add a RowContentProvider that knows how to put data into your row object's 
  53.  * controls on demand.
  54.  * <li>Add a RowFocusListener to validate and save changed data.
  55.  * <li>Set the NumRowsInCollection property to the number of rows in the underlying data
  56.  * structure.
  57.  * </ul>
  58.  *
  59.  * Detailed description:<p>
  60.  * 
  61.  * This control is designed to work inside of the Eclipse Visual Editor.  To use it,
  62.  * drop one on the design surface.  (Even though it extends Canvas, it does not make
  63.  * sense to put a layout manager on it.)<p>
  64.  * 
  65.  * Next create one or two new custom controls by using the Visual Editor to extend
  66.  * Composite.  If you create one custom control, it will be used as the prototype
  67.  * for all rows that will be displayed in the table.  If you create two, the first
  68.  * one will be used as a prototype for the header and the second one will be used 
  69.  * as a prototype for the rows.<p>
  70.  * 
  71.  * If these custom controls are not given layout managers (null layout), then 
  72.  * CompositeTable will automatically detect this situation and will supply its own
  73.  * layout manager that will automatically lay out the children of these controls in 
  74.  * columns to form a table.  However, if you supply layout managers for your header 
  75.  * prototype and row prototype objects, CompositeTable will respect your choice.
  76.  * If you use CompositeTable's built-in layout manager, then the weights property
  77.  * will be used to determine what percentage of the total width will be allocated
  78.  * to each column.  If this property is not set or if the sum of their elements
  79.  * does not equal 100, the columns are created as equal sizes.<p>
  80.  * 
  81.  * Once you have created your (optional) Header and Row custom controls, simply drop
  82.  * them onto your CompositeTable control in VE.  The first of these two custom
  83.  * controls to be instantiated in your code will be interpreted by the CompositeTable
  84.  * as the header control and the second will be interpreted as the row control.<p>
  85.  * 
  86.  * Now that you have defined the (optional) header and row, you can switch your 
  87.  * CompositeTable into run mode and use it.  This is done by switching the RunTime 
  88.  * property to true.<p>
  89.  * 
  90.  * Once in run mode, all of the CompositeTable's properties will be active.  In order
  91.  * to use it, set the NumRowsInCollection property to the number of rows in the 
  92.  * collection you want to display.  And add a RefreshContentProvider, which will
  93.  * be called whenever CompositeTable needs to refresh a particular row.<p>
  94.  * 
  95.  * Please refer to the remainder of the JavaDoc for information on the remaining
  96.  * properties and events.<p>
  97.  * 
  98.  * Although this control extends Composite, it is not intended to be subclassed
  99.  * except within its own implementation and it makes no sense to set a layout 
  100.  * manager on it (although as discussed above, the child controls may have layout
  101.  * managers).
  102.  * 
  103.  * @author djo
  104.  * @since 3.2
  105.  * TODO: eliminate flicker when scrolling backwards
  106.  */
  107. public class CompositeTable extends Canvas {
  108. // Property fields here
  109. private boolean runTime = false;
  110. private int[] weights = new int[0];
  111. private int numRowsInCollection = 0;
  112. private int maxRowsVisible = Integer.MAX_VALUE;
  113. // Private fields here
  114. private Constructor headerConstructor = null;
  115. private Control headerControl = null;
  116. private Constructor rowConstructor = null;
  117. private Control rowControl = null;
  118. private InternalCompositeTable contentPane = null;
  119. /**
  120.  * Constructor CompositeTable.  Construct a CompositeTable control.  CompositeTable
  121.  * accepts the same style bits as the SWT Canvas.
  122.  * 
  123.  * @param parent The SWT parent control.
  124.  * @param style Style bits.  These are the same as Canvas
  125.  */
  126. public CompositeTable(Composite parent, int style) {
  127. super(parent, style);
  128. setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
  129. setLayout(new Layout() {
  130. protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
  131. if (headerControl == null && rowControl == null) {
  132. return new Point(2, 20);
  133. }
  134. Point headerSize = new Point(0, 0);
  135. if (headerControl != null) {
  136. headerSize = headerControl.computeSize(SWT.DEFAULT, SWT.DEFAULT);
  137. }
  138. Point rowSize = new Point(0, 0);
  139. if (rowControl != null) {
  140. rowSize = rowControl.computeSize(SWT.DEFAULT, SWT.DEFAULT);
  141. }
  142. Point result = new Point(Math.max(headerSize.x, rowSize.x), headerSize.y + rowSize.y);
  143. return result;
  144. }
  145. protected void layout(Composite composite, boolean flushCache) {
  146. resize();
  147. }
  148. });
  149. }
  150. /* (non-Javadoc)
  151.  * @see org.eclipse.swt.widgets.Control#setBackground(org.eclipse.swt.graphics.Color)
  152.  */
  153. public void setBackground(Color color) {
  154. super.setBackground(color);
  155. if (contentPane != null) {
  156. contentPane.setBackground(color);
  157. }
  158. }
  159. private int numChildrenLastTime = 0;
  160. /** (non-API)
  161.  * Method resize.  Resize this table's contents.  Called from within the custom 
  162.  * layout manager.
  163.  */
  164. protected final void resize() {
  165. if (isRunTime()) {
  166. int childrenLength = getChildren().length;
  167. if (numChildrenLastTime != childrenLength) {
  168. resizeAndRecordPrototypeRows();
  169. showPrototypes(false);
  170. contentPane.dispose();
  171. contentPane = new InternalCompositeTable(this, SWT.NULL);
  172. }
  173. updateVisibleRows();
  174. } else {
  175. resizeAndRecordPrototypeRows();
  176. }
  177. }
  178. /** (non-API)
  179.  * Method updateVisibleRows.  Makes sure that the content pane is displaying the correct
  180.  * number of visible rows given the control's size.  Called from within #resize.
  181.  */
  182. protected void updateVisibleRows() {
  183. if (contentPane == null) {
  184. switchToRunMode();
  185. }
  186. Point size = getSize();
  187. contentPane.setBounds(0, 0, size.x, size.y);
  188. }
  189. /**
  190.  * Switch from design mode where prototype header/row objects can be dropped on the 
  191.  * control into run mode where all of the properties do what you would expect.
  192.  */
  193. private void switchToRunMode() {
  194. showPrototypes(false);
  195. contentPane = new InternalCompositeTable(this, SWT.NULL);
  196. }
  197. /**
  198.  * Switch back to design mode so that the prototype header/row objects may be manipulated
  199.  * directly in a GUI design tool.
  200.  */
  201. private void switchToDesignMode(){
  202. contentPane.dispose();
  203. contentPane = null;
  204. showPrototypes(true);
  205. resizeAndRecordPrototypeRows();
  206. }
  207. /**
  208.  * Turns display of the prototype objects on or off.
  209.  * 
  210.  * @param newValue true of the prototype objects should be displayed; false otherwise.
  211.  */
  212. private void showPrototypes(boolean newValue) {
  213. if (headerControl != null) {
  214. headerControl.setVisible(newValue);
  215. }
  216. if (rowControl != null) {
  217. rowControl.setVisible(newValue);
  218. }
  219. }
  220. /**
  221.  * (non-API) Method resizeAndRecordPrototypeRows. Figure out what child
  222.  * controls are the header and row prototype rows respectively and resize
  223.  * them so they occupy the entire width and their preferred height.
  224.  */
  225. protected void resizeAndRecordPrototypeRows() {
  226. Control[] children = getChildren();
  227. ArrayList realChildren = new ArrayList();
  228. Control[] finalChildren = children;
  229. // Find first two prototypes
  230. for (int i = 0; i < children.length; i++) {
  231. if (children[i] instanceof InternalCompositeTable) {
  232. continue;
  233. }
  234. if (realChildren.size() < 2) {
  235. realChildren.add(children[i]);
  236. }
  237. }
  238. finalChildren = (Control[]) realChildren.toArray(new Control[realChildren.size()]);
  239. if (finalChildren.length == 0) {
  240. headerConstructor = null;
  241. headerControl = null;
  242. rowConstructor = null;
  243. rowControl = null;
  244. return;
  245. }
  246. // Get a constructor for the header and/or the row prototype
  247. headerConstructor = null;
  248. headerControl = null;
  249. rowConstructor = null;
  250. rowControl = null;
  251. if (finalChildren.length == 1) {
  252. try {
  253. rowControl = (Composite) finalChildren[0];
  254. rowConstructor = finalChildren[0].getClass().getConstructor(new Class[] {Composite.class, Integer.TYPE});
  255. } catch (Exception e) {
  256. }
  257. } else {
  258. try {
  259. headerConstructor = finalChildren[0].getClass().getConstructor(new Class[] {Composite.class, Integer.TYPE});
  260. headerControl = finalChildren[0];
  261. rowConstructor = finalChildren[1].getClass().getConstructor(new Class[] {Composite.class, Integer.TYPE});
  262. rowControl = finalChildren[1];
  263. } catch (Exception e) {
  264. }
  265. }
  266. // Now actually resize the children
  267. int top=0;
  268. int width = getSize().x;
  269. for (int i=0; i < finalChildren.length; ++i) {
  270. int height = 50;
  271. if (finalChildren[i] instanceof Composite) {
  272. Composite child = (Composite) finalChildren[i];
  273. if (child.getLayout() == null) {
  274. height = layoutHeaderOrRow(child);
  275. } else {
  276. height = finalChildren[i].computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
  277. }
  278. } else {
  279. height = finalChildren[i].computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
  280. }
  281. finalChildren[i].setBounds(0, top, width, height);
  282. top += height;
  283. }
  284. numChildrenLastTime = children.length;
  285. Display.getCurrent().asyncExec(new Runnable() {
  286. public void run() {
  287. getParent().layout(true);
  288. }
  289. });
  290. }
  291. /**(non-API)
  292.  * Method layoutHeaderOrRow.  If a header or row object does not have a layout manager, this
  293.  * method will automatically be called to layout the child controls of that header or row
  294.  * object.
  295.  * 
  296.  * @param child The child object to layout.
  297.  * @return the height of the header or row
  298.  */
  299. int layoutHeaderOrRow(Composite child) {
  300. Control[] children = child.getChildren();
  301. if (children.length == 0) {
  302. return 50;
  303. }
  304. int[] weights = this.weights;
  305. weights = checkWeights(weights, children.length);
  306. int maxHeight = 0;
  307. for (int i = 0; i < children.length; i++) {
  308. int height = children[i].computeSize(SWT.DEFAULT, SWT.DEFAULT, true).y;
  309. if (maxHeight < height) {
  310. maxHeight = height;
  311. }
  312. }
  313. ++maxHeight;
  314. int widthRemaining = child.getParent().getSize().x;
  315. int totalSize = widthRemaining;
  316. for (int i = 0; i < children.length-1; i++) {
  317. int left = totalSize - widthRemaining;
  318. int desiredHeight = children[i].computeSize(SWT.DEFAULT, SWT.DEFAULT, false).y;
  319. int top = maxHeight - desiredHeight-1;
  320. int width = (int)(((float)weights[i])/100 * totalSize);
  321. children[i].setBounds(left+2, top, width-4, desiredHeight);
  322. widthRemaining -= width;
  323. }
  324. int left = totalSize - widthRemaining;
  325. int desiredHeight = children[children.length-1].computeSize(SWT.DEFAULT, SWT.DEFAULT, false).y;
  326. int top = maxHeight - desiredHeight-1;
  327. children[children.length-1].setBounds(left+2, top, widthRemaining-4, desiredHeight);
  328. return maxHeight;
  329. }
  330. /**
  331.  * Compute and return a weights array where each weight is the percentage the corresponding
  332.  * column should occupy of the entire control width.  If the elements in the supplied weights 
  333.  * array add up to 100 and the length of the array is the same as the number of columns, the
  334.  * supplied weights array is used.  Otherwise, this method computes and returns a weights 
  335.  * array that makes each column an equal size. 
  336.  * 
  337.  * @param weights The default or user-supplied weights array.
  338.  * @param numChildren The number of child controls.
  339.  * @return The weights array that will be used by the layout manager.
  340.  */
  341. private int[] checkWeights(int[] weights, int numChildren) {
  342. if (weights.length == numChildren) {
  343. int sum = 0;
  344. for (int i = 0; i < weights.length; i++) {
  345. sum += weights[i];
  346. }
  347. if (sum == 100) {
  348. return weights;
  349. }
  350. }
  351. // Either the number of weights doesn't match or they don't add up.
  352. // Compute something sane and return that instead.
  353. int[] result = new int[numChildren];
  354. int weight = 100 / numChildren;
  355. int extra = 100 % numChildren;
  356. for (int i = 0; i < result.length-1; i++) {
  357. result[i] = weight;
  358. }
  359. result[numChildren-1] = weight + extra;
  360. return result;
  361. }
  362. /**
  363.  * Method isRunTime.  Returns if the CompositeTable is in run time mode as opposed
  364.  * to design time mode.  In design time mode, the only permitted operations are to
  365.  * add or remove child Composites to be used as the header and/or row prototype objects.
  366.  * 
  367.  * @return true if this CompositeTable is in run mode.  false otherwise.
  368.  */
  369. public boolean isRunTime() {
  370. return runTime;
  371. }
  372. /**
  373.  * Method setRunTime.  Turns run-time mode on or off.  When run-time mode is off, 
  374.  * CompositeTable ignores most property operations and will accept prototype child
  375.  * controls to be added.  When run-time mode is on, the prototype controls are 
  376.  * interpreted and all properties become active.
  377.  * 
  378.  * @param runTime true if run-time mode should be enabled; false otherwise.
  379.  */
  380. public void setRunTime(boolean runTime) {
  381. if (this.runTime != runTime) {
  382. this.runTime = runTime;
  383. if (runTime) {
  384. if (rowControl == null) {
  385. resizeAndRecordPrototypeRows();
  386. }
  387. switchToRunMode();
  388. } else {
  389. switchToDesignMode();
  390. }
  391. }
  392. }
  393. /**
  394.  * Method getWeights.  Returns an array representing the percentage of the total width
  395.  * each column is allocated or null if no weights have been specified.  This property is
  396.  * ignored if the programmer has set a layout manager on the header and/or the row
  397.  * prototype objects.
  398.  * 
  399.  * @return the current weights array or null if no weights have been specified.
  400.  */
  401. public int[] getWeights() {
  402. return weights;
  403. }
  404. /**
  405.  * Method setWeights.  Specifies the percentage of the total width that will be allocated
  406.  * to each column.  This property is ignored if the programmer has set a layout manager 
  407.  * on the header and/or the row prototype objects.<p>
  408.  * 
  409.  * The number of elements in the array must match the number of columns and the sum of
  410.  * all elements must equal 100.  If either of these constraints is not true, this property
  411.  * will be ignored and all columns will be created equal in width.
  412.  * 
  413.  * @param weights the weights to use if the CompositeTable is automatically laying out controls.
  414.  */
  415. public void setWeights(int[] weights) {
  416. this.weights = weights;
  417. if (contentPane != null) {
  418. contentPane.setWeights();
  419. }
  420. }
  421. boolean gridLinesOn = true;
  422. /**
  423.  * Method isGridLinesOn.  Returns if the CompositeTable will draw grid lines on the header
  424.  * and row Composite objects.  This property is ignored if the programmer has set a layout
  425.  * manager on the header and/or the row prototype objects.
  426.  * 
  427.  * @return true if the CompositeTable will draw grid lines; false otherwise.
  428.  */
  429. public boolean isGridLinesOn() {
  430. return gridLinesOn;
  431. }
  432. /**
  433.  * Method setGridLinesOn.  Sets if the CompositeTable will draw grid lines on the header and
  434.  * row Composite objects.  This property is ignored if the programmer has set a layout 
  435.  * manager on the header and/or the row prototype objects.
  436.  * 
  437.  * @param gridLinesOn true if the CompositeTable will draw grid lines; false otherwise.
  438.  */
  439. public void setGridLinesOn(boolean gridLinesOn) {
  440. this.gridLinesOn = gridLinesOn;
  441. }
  442. String insertHint = "Press <INS> to insert new data."; //$NON-NLS-1$
  443. /**
  444.  * Returns the hint string that will be displayed when there are no rows in the table.
  445.  * 
  446.  * @return The hint string that will be displayed when there are no rows in the table.
  447.  */
  448. public String getInsertHint() {
  449. return insertHint;
  450. }
  451. /**
  452.  * Sets the hint string that will be displayed when there are no rows in the table.  The
  453.  * default value is "Press &lt;INS> to insert a new row."
  454.  * 
  455.  * @param newHint
  456.  */
  457. public void setInsertHint(String newHint) {
  458. this.insertHint = newHint;
  459. }
  460. /**
  461.  * Method getMaxRowsVisible.  Returns the maximum number of rows that will be permitted 
  462.  * in the table at once.  For example, setting this property to 1 will have the effect of 
  463.  * creating a single editing area with a scroll bar on the right allowing the user to scroll
  464.  * through all rows using either the mouse or the PgUp/PgDn keys.  The default value is
  465.  * Integer.MAX_VALUE.
  466.  * 
  467.  * @return the maximum number of rows that are permitted to be visible at one time, regardless
  468.  * of the control's size.
  469.  */
  470. public int getMaxRowsVisible() {
  471. return maxRowsVisible;
  472. }
  473. /**
  474.  * Method setMaxRowsVisible.  Sets the maximum number of rows that will be permitted 
  475.  * in the table at once.  For example, setting this property to 1 will have the effect of 
  476.  * creating a single editing area with a scroll bar on the right allowing the user to scroll
  477.  * through all rows using either the mouse or the PgUp/PgDn keys.  The default value is
  478.  * Integer.MAX_VALUE.
  479.  * 
  480.  * @param maxRowsVisible the maximum number of rows that are permitted to be visible at one time, regardless
  481.  * of the control's size.
  482.  */
  483. public void setMaxRowsVisible(int maxRowsVisible) {
  484. this.maxRowsVisible = maxRowsVisible;
  485. if (contentPane != null) {
  486. contentPane.setMaxRowsVisible(maxRowsVisible);
  487. }
  488. }
  489. /**
  490.  * Method getNumRowsVisible.  Returns the actual number of rows that are currently visible.
  491.  * Normally CompositeTable displays as many rows as will fit vertically given the control's
  492.  * size.  This value can be clamped to a maximum using the MaxRowsVisible property.
  493.  * 
  494.  * @return the actual number of rows that are currently visible.
  495.  */
  496. public int getNumRowsVisible() {
  497. if (contentPane != null)
  498. return contentPane.getNumRowsVisible();
  499. return -1;
  500. }
  501. /**
  502.  * Method getNumRowsInCollection.  Returns the number of rows in the data structure that is
  503.  * being edited.
  504.  * 
  505.  * @return the number of rows in the underlying data structure.
  506.  */
  507. public int getNumRowsInCollection() {
  508. return numRowsInCollection;
  509. }
  510. /**
  511.  * Method setNumRowsInCollection.  Sets the number of rows in the data structure that is
  512.  * being edited.
  513.  * 
  514.  * @param numRowsInCollection the number of rows represented by the underlying data structure.
  515.  */
  516. public void setNumRowsInCollection(int numRowsInCollection) {
  517. this.numRowsInCollection = numRowsInCollection;
  518. if (contentPane != null) {
  519. contentPane.setNumRowsInCollection(numRowsInCollection);
  520. }
  521. }
  522. private int topRow=0;
  523. /**
  524.  * Method getTopRow.  Return the number of the line that is being displayed in the top row
  525.  * of the CompositeTable editor (0-based).
  526.  * 
  527.  * @return the number of the top line.
  528.  */
  529. public int getTopRow() {
  530. if (contentPane != null) {
  531. return contentPane.getTopRow();
  532. }
  533. return topRow;
  534. }
  535. /**
  536.  * Method setTopRow. Set the number of the line that is being displayed in the top row
  537.  * of the CompositeTable editor (0-based).  If the new top row is not equal to the current
  538.  * top row, the table will automatically be scrolled to the new position.  This number must
  539.  * be greater than 0 and less than NumRowsInCollection.
  540.  * 
  541.  * @param topRow the line number of the new top row.
  542.  */
  543. public void setTopRow(int topRow) {
  544. this.topRow = topRow;
  545. if (contentPane != null) {
  546. contentPane.setTopRow(topRow);
  547. }
  548. }
  549. /**
  550.  * Method refreshAllRows.  Refresh all visible rows in the CompositeTable from the
  551.  * original data.
  552.  */
  553. public void refreshAllRows() {
  554. if (contentPane != null) {
  555. contentPane.updateVisibleRows();
  556. contentPane.refreshAllRows();
  557. }
  558. }
  559. /**
  560.  * Method getCurrentColumn.  Returns the column number of the currently-focused column 
  561.  * (0-based).
  562.  * 
  563.  * @return the column number of the currently-focused column.
  564.  */
  565. public int getCurrentColumn() {
  566. if (contentPane == null) {
  567. return -1;
  568. }
  569. return getSelection().x;
  570. }
  571. /**
  572.  * Method setCurrentColumn.  Sets the column number of the currently-focused column 
  573.  * (0-based).
  574.  * 
  575.  * @param column The new column to focus.
  576.  */
  577. public void setCurrentColumn(int column) {
  578. setSelection(column, getCurrentRow());
  579. }
  580. /**
  581.  * Method getCurrentRow.  Returns the current row number as an offset from the top of the
  582.  * table window.  In order to get the current row in the underlying data structure, compute
  583.  * getTopRow() + getCurrentRow().
  584.  * 
  585.  * @return the current row number as an offset from the top of the table window.
  586.  */
  587. public int getCurrentRow() {
  588. if (contentPane == null) {
  589. return -1;
  590. }
  591. return getSelection().y;
  592. }
  593. /**
  594.  * Method setCurrentRow.  Sets the current row number as an offset from the top of the
  595.  * table window.  In order to get the current row in the underlying data structure, compute
  596.  * getTopRow() + getCurrentRow().
  597.  * 
  598.  * @param row the current row number as an offset from the top of the table window.
  599.  */
  600. public void setCurrentRow(int row) {
  601. setSelection(getCurrentColumn(), row);
  602. }
  603. /**
  604.  * Method getCurrentRowControl.  Returns the SWT control that displays the current row.
  605.  * 
  606.  * @return Control the current row control.
  607.  */
  608. public Control getCurrentRowControl() {
  609. return contentPane.getCurrentRowControl();
  610. }
  611. /**
  612.  * Method getSelection.  Returns the currently-selected (column, row) pair where the row 
  613.  * specifies the offset from the top of the table window.  In order to get the current 
  614.  * row in the underlying data structure, use getSelection().y + getCurrentRow().
  615.  * 
  616.  * @return  the currently-selected (column, row) pair where the row specifies the offset 
  617.  * from the top of the table window.
  618.  */
  619. public Point getSelection() {
  620. if (contentPane == null) {
  621. return null;
  622. }
  623. return contentPane.getSelection();
  624. }
  625. /**
  626.  * Method setSelection.  Sets the currently-selected (column, row) pair where the row 
  627.  * specifies the offset from the top of the table window.  In order to get the current 
  628.  * row in the underlying data structure, use getSelection().y + getCurrentRow().
  629.  * 
  630.  * @param selection the (column, row) to select
  631.  */
  632. public void setSelection(Point selection) {
  633. setSelection(selection.x, selection.y);
  634. }
  635. /**
  636.  * Method setSelection.  Sets the currently-selected (column, row) pair where the row 
  637.  * specifies the offset from the top of the table window.  In order to get the current 
  638.  * row in the underlying data structure, use getSelection().y + getCurrentRow().
  639.  * 
  640.  * @param column the column to select
  641.  * @param row the row to select as an offset from the top of the window
  642.  */
  643. public void setSelection(int column, int row) {
  644. if (contentPane == null) {
  645. return;
  646. }
  647. contentPane.setSelection(column, row);
  648. }
  649. /** (non-API)
  650.  * Method getHeaderConstructor.  Returns the Constructor object used internally to
  651.  * construct the table's header or null if there is none.
  652.  * 
  653.  * @return the header's constructor.
  654.  */
  655. public Constructor getHeaderConstructor() {
  656. return headerConstructor;
  657. }
  658. /** (non-API)
  659.  * Method getRowConstructor.  Returns the Constructor object used internally to 
  660.  * construct each row object.
  661.  * 
  662.  * @return the rows' constructor
  663.  */
  664. public Constructor getRowConstructor() {
  665. return rowConstructor;
  666. }
  667. /** (non-API)
  668.  * Method getHeaderControl.  Returns the prototype header control.
  669.  * 
  670.  * @return the prototype header control.
  671.  */
  672. public Control getHeaderControl() {
  673. return headerControl;
  674. }
  675. /** (non-API)
  676.  * Method getRowControl.  Returns the prototype row control.
  677.  * 
  678.  * @return the prototype row control.
  679.  */
  680. public Control getRowControl() {
  681. return rowControl;
  682. }
  683. LinkedList contentProviders = new LinkedList();
  684. /**
  685.  * Method addRowContentProvider.  Adds the specified content provider to the list of
  686.  * content providers that will be called when a row needs to be filled with data.
  687.  * Most of the time it only makes sense to add a single one.
  688.  * 
  689.  * @param contentProvider The content provider to add.
  690.  */
  691. public void addRowContentProvider(IRowContentProvider contentProvider) {
  692. contentProviders.add(contentProvider);
  693. }
  694. /**
  695.  * Method removeRowContentProvider.  Removes the specified content provider from the list of
  696.  * content providers that will be called when a row needs to be filled with data.
  697.  * 
  698.  * @param contentProvider The content provider to remove.
  699.  */
  700. public void removeRowContentProvider(IRowContentProvider contentProvider) {
  701. contentProviders.remove(contentProvider);
  702. }
  703. LinkedList rowFocusListeners = new LinkedList();
  704. /**
  705.  * Method addRowListener.  Adds the specified listener to the set of listeners that 
  706.  * will be notified when the user wishes to leave a row and when the user has already
  707.  * left a row.  If any listener vetos leaving a row, the focus remains in the row.
  708.  * 
  709.  * @param rowListener The listener to add.
  710.  */
  711. public void addRowFocusListener(IRowFocusListener rowListener) {
  712. rowFocusListeners.add(rowListener);
  713. }
  714. /**
  715.  * Method removeRowListener.  Removes the specified listener from the set of listeners that 
  716.  * will be notified when the user wishes to leave a row and when the user has already
  717.  * left a row.  If any listener vetos leaving a row, the focus remains in the row.
  718.  * 
  719.  * @param listener The listener to remove.
  720.  */
  721. public void removeRowFocusListener(IRowFocusListener listener) {
  722. rowFocusListeners.remove(listener);
  723. }
  724. LinkedList insertHandlers = new LinkedList();
  725. /**
  726.  * Method addInsertHandler.  Adds the specified insertHandler to the set of objects that
  727.  * will be used to handle insert requests.
  728.  * 
  729.  * @param insertHandler the insertHandler to add.
  730.  */
  731. public void addInsertHandler(IInsertHandler insertHandler) {
  732. insertHandlers.add(insertHandler);
  733. }
  734. /**
  735.  * Method removeInsertHandler.  Removes the specified insertHandler from the set of objects that
  736.  * will be used to handle insert requests.
  737.  * 
  738.  * @param insertHandler the insertHandler to remove.
  739.  */
  740. public void removeInsertHandler(IInsertHandler insertHandler) {
  741. insertHandlers.remove(insertHandler);
  742. }
  743. LinkedList deleteHandlers = new LinkedList();
  744. /**
  745.  * Method addDeleteHandler.  Adds the specified deleteHandler to the set of objects that
  746.  * will be used to handle delete requests.
  747.  * 
  748.  * @param deleteHandler the deleteHandler to add.
  749.  */
  750. public void addDeleteHandler(IDeleteHandler deleteHandler) {
  751. deleteHandlers.add(deleteHandler);
  752. }
  753. /**
  754.  * Method removeDeleteHandler.  Removes the specified deleteHandler from the set of objects that
  755.  * will be used to handle delete requests.
  756.  * 
  757.  * @param deleteHandler the deleteHandler to remove.
  758.  */
  759. public void removeDeleteHandler(IDeleteHandler deleteHandler) {
  760. deleteHandlers.remove(deleteHandler);
  761. }
  762. LinkedList rowConstructionListeners = new LinkedList();
  763. /**
  764.  * Method addRowConstructionListener.  Adds the specified rowConstructionListener to the set of objects that
  765.  * will be used to listen to row construction events.
  766.  * 
  767.  * @param rowConstructionListener the rowConstructionListener to add.
  768.  */
  769. public void addRowConstructionListener(IRowConstructionListener rowConstructionListener) {
  770. rowConstructionListeners.add(rowConstructionListener);
  771. }
  772. /**
  773.  * Method removeRowConstructionListener.  Removes the specified rowConstructionListener from the set of objects that
  774.  * will be used to listen to row construction events.
  775.  * 
  776.  * @param rowConstructionListener the rowConstructionListener to remove.
  777.  */
  778. public void removeRowConstructionListener(IRowConstructionListener rowConstructionListener) {
  779. rowConstructionListeners.remove(rowConstructionListener);
  780. }
  781. boolean deleteEnabled = true;
  782. /**
  783.  * Method isDeleteEnabled.  Returns if delete is enabled.  Deletions are only processed if
  784.  * the DeleteEnabled property is true and at least one delete handler has been registered.<p>
  785.  * 
  786.  * The default value is true.
  787.  * 
  788.  * @return true if delete is enabled.  false otherwise.
  789.  */
  790. public boolean isDeleteEnabled() {
  791. return deleteEnabled;
  792. }
  793. /**
  794.  * Method setDeleteEnabled.  Sets if delete is enabled.  Deletions are only processed if
  795.  * the DeleteEnabled property is true and at least one delete handler has been registered.<p>
  796.  * 
  797.  * The default value is true.
  798.  * 
  799.  * @param deleteEnabled true if delete should be enabled.  false otherwise.
  800.  */
  801. public void setDeleteEnabled(boolean deleteEnabled) {
  802. this.deleteEnabled = deleteEnabled;
  803. }
  804. }  //  @jve:decl-index=0:visual-constraint="10,10"