package abbot.tester.swt; import java.util.ArrayList; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.ScrollBar; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import abbot.Log; import com.windowtester.runtime.WT; import com.windowtester.runtime.swt.internal.abbot.SWTWorkarounds; import com.windowtester.runtime.swt.internal.operation.SWTMouseOperation; /** * Provides widget-specific actions for testing Tables. Note that * actionShowTableColumn, actionSelectTableColumn, and actionResizeTableColumn * are currently platform-dependent. * * !pq: robot-related fixes made. * * @version $Id: TableTester.java,v 1.3 2007-11-27 17:17:39 pq Exp $ */ public class TableTester extends CompositeTester{ public static final String copyright = "Licensed Materials -- Property of IBM\n"+ "(c) Copyright International Business Machines Corporation, 2003\nUS Government "+ "Users Restricted Rights - Use, duplication or disclosure restricted by GSA "+ "ADP Schedule Contract with IBM Corp."; /* Begin getters */ /** * Proxy for {@link Table#getItem(int)}. * <p/> * @param table the table under test. * @param index the index of the item. * @return the item at the index. */ public TableItem getItem(final Table table, final int index){ TableItem result = (TableItem) Robot.syncExec(table.getDisplay(), new RunnableWithResult(){ public Object runWithResult(){ return table.getItem(index); } }); return result; } /** * Proxy for {@link Table#getItem(org.eclipse.swt.graphics.Point)}. * <p/> * @param table the table under test. * @param point the point to find the item under. * @return the item at the point. */ public TableItem getItem(final Table table, final Point point){ TableItem result = (TableItem) Robot.syncExec(table.getDisplay(), new RunnableWithResult(){ public Object runWithResult(){ return table.getItem(point); } }); return result; } /** * Proxy for {@link Table#getColumn(int)}. * <p/> * @param table the table under test. * @param index the index of the column. * @return the column at the index. */ public TableColumn getColumn(final Table table, final int index) { TableColumn result = (TableColumn) Robot.syncExec(table.getDisplay(), new RunnableWithResult(){ public Object runWithResult(){ return table.getColumn(index); } }); return result; } /** * Proxy for {@link Table#getColumnCount()}. * <p/> * @param table the table under test. * @return the number of columns of this table. */ public int getColumnCount(final Table table) { Integer result = (Integer) Robot.syncExec(table.getDisplay(), new RunnableWithResult(){ public Object runWithResult(){ return new Integer(table.getColumnCount()); } }); return result.intValue(); } /** * Proxy for {@link Table#getColumns()}. * <p/> * @param table the table under test. * @return the table columns. */ public TableColumn[] getColumns(final Table table) { TableColumn[] result = (TableColumn[]) Robot.syncExec(table.getDisplay(), new RunnableWithResult(){ public Object runWithResult(){ return table.getColumns(); } }); return result; } /** * Proxy for {@link Table#getGridLineWidth()}. * <p/> * @param table the table under test. * @return the grid line width. */ public int getGridLineWidth(final Table table) { Integer result = (Integer) Robot.syncExec(table.getDisplay(), new RunnableWithResult(){ public Object runWithResult(){ return new Integer(table.getGridLineWidth()); } }); return result.intValue(); } /** * Proxy for {@link Table#getHeaderHeight()}. * <p/> * @param table the table under test. * @return the header height. */ public int getHeaderHeight(final Table table) { Integer result = (Integer) Robot.syncExec(table.getDisplay(), new RunnableWithResult(){ public Object runWithResult(){ return new Integer(table.getHeaderHeight()); } }); return result.intValue(); } /** * Proxy for {@link Table#getHeaderVisible()}. * <p/> * @param table the table under test. * @return true if the header is visible. */ public boolean getHeaderVisible(final Table table) { Boolean result = (Boolean) Robot.syncExec(table.getDisplay(), new RunnableWithResult(){ public Object runWithResult(){ return Boolean.valueOf(table.getHeaderVisible()); } }); return result.booleanValue(); } /** * Proxy for {@link Table#getItemCount()}. * <p/> * @param table the table under test. * @return the number of rows in the table. */ public int getItemCount(final Table table) { Integer result = (Integer) Robot.syncExec(table.getDisplay(), new RunnableWithResult(){ public Object runWithResult(){ return new Integer(table.getItemCount()); } }); return result.intValue(); } /** * Proxy for {@link Table#getItemHeight()}. * <p/> * @param table the table under test. * @return the height of the items. */ public int getItemHeight(final Table table) { Integer result = (Integer) Robot.syncExec(table.getDisplay(), new RunnableWithResult(){ public Object runWithResult(){ return new Integer(table.getItemHeight()); } }); return result.intValue(); } /** * Proxy for {@link Table#getItems()}. * <p/> * @param table the table under test. * @return the items in the table. */ public TableItem[] getItems(final Table table) { TableItem[] result = (TableItem[]) Robot.syncExec(table.getDisplay(), new RunnableWithResult(){ public Object runWithResult(){ return table.getItems(); } }); return result; } /** * Proxy for {@link Table#getLinesVisible()}. * <p/> * @param table the table under test. * @return true if the lines are visible. */ public boolean getLinesVisible(final Table table) { Boolean result = (Boolean) Robot.syncExec(table.getDisplay(), new RunnableWithResult(){ public Object runWithResult(){ return Boolean.valueOf(table.getLinesVisible()); } }); return result.booleanValue(); } /** * Proxy for {@link Table#getSelection()}. * <p/> * @param table the table under test. * @return the selected items. */ public TableItem[] getSelection(final Table table) { TableItem[] result = (TableItem[]) Robot.syncExec(table.getDisplay(), new RunnableWithResult(){ public Object runWithResult(){ return table.getSelection(); } }); return result; } /** * Proxy for {@link Table#getSelectionCount()}. * <p/> * @param table the table under test. * @return the number of selected items. */ public int getSelectionCount(final Table table) { Integer result = (Integer) Robot.syncExec(table.getDisplay(), new RunnableWithResult(){ public Object runWithResult(){ return new Integer(table.getSelectionCount()); } }); return result.intValue(); } /** * Proxy for {@link Table#getSelectionIndex()}. * <p/> * @param table the table under test. * @return the index of the selected item. */ public int getSelectionIndex(final Table table) { Integer result = (Integer) Robot.syncExec(table.getDisplay(), new RunnableWithResult(){ public Object runWithResult(){ return new Integer(table.getSelectionIndex()); } }); return result.intValue(); } /** * Proxy for {@link Table#getTopIndex()}. * <p/> * @param table the table under test. * @return the index of the top item. */ public int getTopIndex(final Table table) { Integer result = (Integer) Robot.syncExec(table.getDisplay(), new RunnableWithResult(){ public Object runWithResult(){ return new Integer(table.getTopIndex()); } }); return result.intValue(); } /** * Proxy for {@link Table#indexOf(org.eclipse.swt.widgets.TableColumn)}. * <p/> * @param table the table under test. * @param column the column to return the index for. * @return the index of the column given. */ public int indexOf(final Table table, final TableColumn column) { Integer result = (Integer) Robot.syncExec(table.getDisplay(), new RunnableWithResult(){ public Object runWithResult(){ return new Integer(table.indexOf(column)); } }); return result.intValue(); } /** * Proxy for {@link Table#indexOf(org.eclipse.swt.widgets.TableItem)}. * <p/> * @param table the table under test. * @param item the item to return the index for. * @return the index of the item given. */ public int indexOf(final Table table, final TableItem item) { Integer result = (Integer) Robot.syncExec(table.getDisplay(), new RunnableWithResult(){ public Object runWithResult(){ return new Integer(table.indexOf(item)); } }); return result.intValue(); } /** * Proxy for {@link Table#isSelected(int)}. * <p/> * @param table the table under test. * @param index the index to return the selected property for. * @return true if the index given is selected. */ public boolean isSelected(final Table table, final int index) { Boolean result = (Boolean) Robot.syncExec(table.getDisplay(), new RunnableWithResult(){ public Object runWithResult(){ return Boolean.valueOf(table.isSelected(index)); } }); return result.booleanValue(); } /** * @since 3.9.1 */ public boolean isSelected(Table table, TableItem item) { TableItem[] items = getSelectedTableItems(table); for (int i = 0; i < items.length; i++) { if (items[i] == item) return true; } return false; } /* End getters */ /** Returns all selected items in the given table **/ public TableItem[] getSelectedTableItems(final Table table){ TableItem[] result = (TableItem[]) Robot.syncExec(table.getDisplay(),new RunnableWithResult(){ public Object runWithResult(){ return table.getSelection(); } }); return result; } /** Returns the indices of all selected items in the given table **/ public int[] getSelectedTableIndices(final Table table){ int[] result = (int[]) Robot.syncExec(table.getDisplay(),new RunnableWithResult(){ public Object runWithResult(){ return table.getSelectionIndices(); } }); return result; } /** Returns the all checked items in the given table **/ public TableItem[] getCheckedTableItems(final Table table){ TableItem[] result = (TableItem[]) Robot.syncExec(table.getDisplay(),new RunnableWithResult(){ public Object runWithResult(){ ArrayList checked = new ArrayList(); TableItem[] items = table.getItems(); for(int i=0; i<items.length;i++){ if(items[i].getChecked()) checked.add(items[i]); } return checked.toArray(new TableItem[checked.size()]); } }); return result; } /** Returns the indices of all checked items in the given table **/ public int[] getCheckedTableIndices(final Table table){ Integer[] result = (Integer[]) Robot.syncExec(table.getDisplay(), new RunnableWithResult(){ public Object runWithResult(){ ArrayList checked = new ArrayList(); TableItem[] items = table.getItems(); for(int i=0; i<items.length;i++){ if(items[i].getChecked()) checked.add(new Integer(i)); } return checked.toArray(new Integer[checked.size()]); } }); int[] res = new int[result.length]; for(int i=0; i<res.length;i++) res[i] = result[i].intValue(); return res; } /** Checks if the SWT.CHECK style bit is set for the given table **/ public boolean isCheckStyleBitSet(final Table table) { Boolean result = (Boolean) Robot.syncExec(table.getDisplay(),new RunnableWithResult(){ public Boolean runWithResult(){ return (table.getStyle() & SWT.CHECK) != 0; } }); return result; } /** Move the mouse pointer over the given TableItem **/ protected synchronized void mouseMoveTableItem(final Table table, final TableItem item){ Robot.syncExec(table.getDisplay(),this,new Runnable(){ public void run(){ table.setFocus(); table.showItem(item); Rectangle bounds = WidgetLocator.getBounds(table,true); int col0Width = table.getColumn(0).getWidth(); int itemHeight = table.getItemHeight(); Point p = new Point(col0Width/2,itemHeight/2); TableItem itemAtPoint=null; while(true){ if(p.y>bounds.y+bounds.height) break; itemAtPoint = table.getItem(p); if(itemAtPoint==item) break; p.y+=itemHeight; } if(itemAtPoint==item) mouseMove(bounds.x+p.x,bounds.y+p.y); } }); actionWaitForIdle(table.getDisplay()); } /** Move the mouse pointer over the TableItem at the given index **/ protected synchronized void mouseMoveTableIndex(final Table table, final int index){ //synchronized(this){ Robot.syncExec(table.getDisplay(),this,new Runnable(){ public void run(){ objT = table.getItem(index); } }); //} if(objT!=null) mouseMoveTableItem(table,(TableItem)objT); } /** Move the mouse pointer to the top of the given column **/ protected void mouseMoveTopOfColumn(final Table table, final TableColumn col){ Robot.syncExec(table.getDisplay(),null,new Runnable(){ public void run(){ table.setFocus(); TableColumn[] cols = table.getColumns(); int width = 0; int i; for(i=0; i<cols.length;i++){ width+=cols[i].getWidth(); if(col==cols[i]) break; } if(col==cols[i]){ int height = table.getHeaderHeight()/2; width-=col.getWidth()/2; Point loc = WidgetLocator.getLocation(table); mouseMove2(loc.x+width,loc.y+height); } } }); actionWaitForIdle(table.getDisplay()); } /** Click an item in the given table. NOTE: Support has been added for the case * when a table is being used as a list and has no columns, but this may not work * in all cases depending on the alignment of the text in the table. The problem * is that on some platforms only the text is clickable for purposes of making * a selection, but the current SWT API provides no method for getting the bounds * of this text. **/ public void actionClickTableItem(final Table table, final TableItem item){ actionClickTableItem(table,item,0); } public void actionClickTableItem(final Table table, final TableItem item ,final int column){ Point point = (Point)Robot.syncExec(table.getDisplay(),new RunnableWithResult(){ public Object runWithResult(){ /* Give the Table focus. */ table.setFocus(); table.showItem(item); /* Get relative bounds for table and item. */ Rectangle relativeBoundsOfItem = item.getBounds(column); Log.log("relativeBoundsOfItem["+column+"]:"+relativeBoundsOfItem); /* Determine relative click point. */ int x = relativeBoundsOfItem.x + (relativeBoundsOfItem.width / 2); int y = relativeBoundsOfItem.y + (relativeBoundsOfItem.height / 2); /* Convert to real coordinates on Display. */ Point point = table.toDisplay(x,y); return point; } }); Log.log("actionClickTableItem["+column+"]:"+point); mouseMove2(point.x,point.y); mousePress(SWT.BUTTON1); mouseRelease(SWT.BUTTON1); actionWaitForIdle(table.getDisplay()); } /** Click the item at the given index **/ public void actionClickTableIndex(final Table table, final int index){ Robot.syncExec(table.getDisplay(),this,new Runnable(){ public void run(){ objT = table.getItem(index); } }); if(objT!=null) actionClickTableItem(table,(TableItem)objT); } /** Click the given column's header (if headers are visible) **/ public void actionClickTableColumnHeader(final Table table, TableColumn column){ Robot.syncExec(table.getDisplay(),this,new Runnable(){ public void run(){ objT = new Boolean(table.getHeaderVisible()); } }); if(((Boolean)objT).booleanValue()){ actionShowTableColumn(table,column); // also positions pointer above header //!pq: keyClick fix // mousePress(SWT.BUTTON1); // mouseRelease(SWT.BUTTON1); // mousePress2(SWT.BUTTON1); // mouseRelease2(SWT.BUTTON1); new SWTMouseOperation(WT.BUTTON1).execute(); actionWaitForIdle(table.getDisplay()); } } /** Select an item from the given table, or deselect it if it was already selected. **/ public void actionSelectTableItem(final Table table, final TableItem item){ // Tao Weng 04/25/2005 10:39:05 AM: // > I have to comment out "mouseMoveTableItem(table,item);" from // > actionSelectTableItem. It seems to me that if I have that line // > uncommented, my script just hangs. // mouseMoveTableItem(table,item); System.out.println("calling Robot syncExec()"); Robot.syncExec(table.getDisplay(),null,new Runnable(){ public void run(){ System.out.println("setting focus"); table.setFocus(); System.out.println("getting items"); TableItem[] items = table.getItems(); int i; for(i=0; i<items.length;i++){ if(items[i]==item) break; } int index = i; if(items[i]==item){ System.out.println("showing item: " + item); table.showItem(item); System.out.println("getting selected items"); TableItem[] selectedItems = getSelectedTableItems(table); boolean selected =false; for(i=0; i<selectedItems.length;i++){ if(selectedItems[i]==item){ selected = true; System.out.println("deselecting item: " + i); table.deselect(i); break; } } if(!selected) { System.out.println("selecting item: " + index); table.select(index); } } } }); System.out.println("start wait for idle"); actionWaitForIdle(table.getDisplay()); System.out.println("stop wait for idle"); } /** Select the item at the given index from the table, or deselect it if it was already selected. **/ public void actionSelectTableIndex(final Table table, final int index){ //!pq: see note above //mouseMoveTableIndex(table,index); Robot.syncExec(table.getDisplay(),null,new Runnable(){ public void run(){ table.setFocus(); TableItem item = null; try{item = table.getItem(index);} catch(Exception ignored){} if(item!=null){ table.showItem(item); TableItem[] selectedItems = getSelectedTableItems(table); boolean selected =false; for(int i=0; i<selectedItems.length;i++){ if(selectedItems[i]==item){ selected = true; table.deselect(i); break; } } if(!selected) table.select(index); } } }); actionWaitForIdle(table.getDisplay()); } /** Put the item as high as possible in the given table's viewing window **/ public void actionShowTableItem(final Table table, final TableItem item) { Robot.syncExec(table.getDisplay(),null,new Runnable(){ public void run(){ table.setFocus(); table.showItem(item); // Commented this out since it seems not to work. If any objections, // please complain, rbirenheide // TableItem[] items = table.getItems(); // int i; // for(i=0; i<items.length;i++){ // if(items[i]==item) // break; // } // if(items[i]==item){ // table.setTopIndex(i); // } } }); actionWaitForIdle(table.getDisplay()); } /** Put the item at the given index as high as possible in the table's viewing window **/ public void actionShowTableIndex(final Table table, final int index){ Robot.syncExec(table.getDisplay(),null,new Runnable(){ public void run(){ table.setFocus(); table.setTopIndex(index); } }); actionWaitForIdle(table.getDisplay()); } /** * Scroll so that the given table column is visible, and place the mouse over the * column's heading, if visible. **/ public void actionShowTableColumn(final Table table, final TableColumn column){ Robot.syncExec(table.getDisplay(),null,new Runnable(){ public void run(){ table.setFocus(); ScrollBar scrollBar = table.getHorizontalBar(); int width = 0; int totalWidth = 0; TableColumn[] cols = table.getColumns(); for(int i=0; i<cols.length;i++){ totalWidth+=cols[i].getWidth(); } for(int i=0; i<cols.length&&cols[i]!=column;i++){ width+=cols[i].getWidth(); } width+=column.getWidth()/2; ScrollBarTester tester = (ScrollBarTester)WidgetTester.getTester(ScrollBar.class); Rectangle scrollBounds = SWTWorkarounds.getBounds(scrollBar); int max = scrollBar.getMaximum(); int min = scrollBar.getMinimum(); int tableWidth = table.getBounds().width; int setScroll =(int)( (double)((double)width /(double)totalWidth)*(max-min))-tableWidth/2; // System.out.println( "setScroll="+setScroll+" min=" // +scrollBar.getMinimum()+" max="+scrollBar.getMaximum() // +" thumb="+scrollBar.getThumb() // +" width="+width+" totalWidth="+totalWidth // +" tableWidth="+tableWidth+"scrollWidth="+scrollBounds.width); tester.actionScrollSetSelection(scrollBar,setScroll); // now move mouse to top of column int selection = scrollBar.getSelection(); //int thumb = scrollBar.getThumb(); double thumbEdge = (double)((double)selection/(double)(max-min)); int leftEdgeOfTableShowing = (int)(thumbEdge*totalWidth); Point tableLoc = WidgetLocator.getLocation(table); //System.out.println("Selection="+selection+" leftEdge...="+leftEdgeOfTableShowing); int offset = width - leftEdgeOfTableShowing; if(offset>=scrollBounds.width){ System.out.println("offset to large("+offset+")"); offset = scrollBounds.width-2; } mouseMove2( tableLoc.x+(offset), tableLoc.y+table.getHeaderHeight()/2); } }); actionWaitForIdle(table.getDisplay()); } /** Check the check box for an item in the given table,, or uncheck it if it * was already checked. **/ public void actionCheckTableItem(final Table table, final TableItem item){ //!pq: see note above //mouseMoveTableIndex(table,index); System.out.println("start checking table item"); Robot.syncExec(table.getDisplay(),null,new Runnable(){ public void run(){ table.setFocus(); table.showItem(item); if(item.getChecked()) item.setChecked(false); else item.setChecked(true); } }); actionWaitForIdle(table.getDisplay()); System.out.println("end checking table item"); } /** Check the check box for the item at the given index in the table, or * uncheck it if it was already checked. **/ public void actionCheckTableIndex(final Table table, final int index){ //!pq: see note above //mouseMoveTableIndex(table,index); System.out.println("start checking table item"); Robot.syncExec(table.getDisplay(),null,new Runnable(){ public void run(){ table.setFocus(); TableItem[] items = table.getItems(); if(index>=0 && index<items.length){ table.showItem(items[index]); if(items[index].getChecked()) items[index].setChecked(false); else items[index].setChecked(true); } } }); actionWaitForIdle(table.getDisplay()); System.out.println("end checking table item"); } /** Resize the column in the given table **/ public void actionResizeTableColumn(final Table table, final TableColumn column, final int width){ actionShowTableColumn(table,column); mouseMoveTopOfColumn(table,column); Robot.syncExec(table.getDisplay(),null,new Runnable(){ public void run(){ table.setFocus(); column.setWidth(width); // TODO need to make the column visible here and maybe move the mouse over it } }); actionWaitForIdle(table.getDisplay()); mouseMoveTopOfColumn(table,column); actionWaitForIdle(table.getDisplay()); } }