blob: dc1a37c940fd68724aa97f20587da6b5b25f5c14 [file] [log] [blame]
package org.eclipse.swt.tests.manualJUnit;
import java.text.Collator;
import java.util.Arrays;
import java.util.Locale;
import java.util.Random;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.TextLayout;
import org.eclipse.swt.graphics.TextStyle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
@FixMethodOrder(MethodSorters.JVM) // To make it easier for human to go through the tests. Same order makes tests easier to recognize.
public class MJ_Table extends MJ_root {
// Shared elements:
final Listener ownerDrawnListener = event -> {
final TableItem item = (TableItem)event.item;
Table table = item.getParent();
AtomicBoolean packpending = (AtomicBoolean) table.getData();
if (event.type == SWT.PaintItem) {
final String text1 = (String)item.getData();
if (event.index == 0) {
event.gc.drawText(text1, event.x, event.y, true);
}
}
if (event.type == SWT.MeasureItem) {
event.height = 50;
event.width = 100;
}
if (event.type == SWT.SetData) {
final int index = table.indexOf(item);
final String data = "Item " + index;
item.setData(data);
if (table.getColumnCount() > 1) {
for (int i = 1; i <= table.getColumnCount(); i++) {
item.setText(i, "Column: " + i + " " + data);
}
}
// BUG BREAKER.
if (packpending.get()) {
packpending.set(false);
display.asyncExec(() -> {
table.setRedraw(false);
for (TableColumn column : table.getColumns()) {
column.pack();
}
table.setRedraw(true);
});
}
}
};
@Test
public void basicTable_Snippet35() {
Shell shell = mkShell("Basic Table with a few items, no column, no headers");
shell.setLayout(new FillLayout());
Table table = new Table (shell, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
for (int i=0; i<12; i++) {
TableItem item = new TableItem (table, 0);
item.setText ("Item " + i);
}
shell.setSize (SWIDTH, SHEIGHT);
shell.open ();
mainLoop(shell);
}
/**
* <a href="https://bugs.eclipse.org/bugs/attachment.cgi?id=272647">Screenshot </a>
*/
@Test
public void ownerDrawn_cheese_single_column () {
Shell shell = mkShell("Expected: There should be no cheese in the items. Move over shouldn't cheese out. See javadoc for screenshot");
shell.setLayout(new FillLayout(SWT.VERTICAL));
final Table table = new Table(shell, SWT.VIRTUAL | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
AtomicBoolean packpending = new AtomicBoolean(true);
table.setData(packpending);
table.addListener(SWT.EraseItem, ownerDrawnListener);
table.addListener(SWT.SetData, ownerDrawnListener);
table.addListener(SWT.MeasureItem, ownerDrawnListener);
table.addListener(SWT.PaintItem, ownerDrawnListener);
final TableColumn tableColumn = new TableColumn(table, SWT.LEFT);
tableColumn.setText("First Left Column");
tableColumn.setMoveable(true);
for (int i = 0; i < 100; i++) {
TableItem item1 = new TableItem(table, SWT.NONE);
item1.setText("hello " + i);
}
// for (int i = 0; i < 2; i++) {
// table.getColumn(i).setWidth(1); // Setting width seems to fix issue.
// table.getColumn(i).pack(); // table is empty on Gtk3. // packing doesn't fix issue.
// }
shell.setSize(800, 600); // Shell size seems to have a litlte bit of an initial impact. (may show proper with some shell sizes, incorrectly for others).
shell.open();
mainLoop(shell);
}
@Test
public void ownerDrawn_cheese_multiple_columns() {
final Shell shell = mkShell("Expected: No cheese in multiple column, also mouse move over no cheese.");
shell.setLayout(new FillLayout(SWT.VERTICAL));
final Table table = new Table(shell, SWT.VIRTUAL | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
AtomicBoolean packpending = new AtomicBoolean(true);
table.setData(packpending);
table.addListener(SWT.EraseItem, ownerDrawnListener);
table.addListener(SWT.SetData, ownerDrawnListener);
table.addListener(SWT.MeasureItem, ownerDrawnListener);
table.addListener(SWT.PaintItem, ownerDrawnListener);
BiConsumer<Integer, String> createColCons = (colStyle, colName) -> {
final TableColumn tableColumn = new TableColumn(table, colStyle);
tableColumn.setText(colName);
tableColumn.setMoveable(true);
};
createColCons.accept(SWT.LEFT, "LEFT");
createColCons.accept(SWT.CENTER, "CENTER");
createColCons.accept(SWT.RIGHT, "RIGHT");
int ItemCount = 1000;
table.setItemCount(ItemCount);
table.setHeaderVisible(true);
shell.setSize(SWIDTH, SHEIGHT);
shell.open();
mainLoop(shell);
}
/**
* <a href="http://www.eclipse.org/articles/Article-CustomDrawingTableAndTreeItems/customDraw.htm#_example4"> Screenshot </a>
*/
@Test
public void ownerDrawn_eraseItem_Snippet273() {
knownToBeBrokenGtk3("Test currently broken on Gtk3. See Comment#1 of Bug 531551");
final String[] MONTHS = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
final int[] HIGHS = {-7, -4, 1, 11, 18, 24, 26, 25, 20, 13, 5, -4};
final int[] LOWS = {-15, -13, -7, 1, 7, 13, 15, 14, 10, 4, -2, -11};
final int SCALE_MIN = -30; final int SCALE_MAX = 30;
final int SCALE_RANGE = Math.abs(SCALE_MIN - SCALE_MAX);
Shell shell = mkShell(" Gtk3:broken, no erasing (1st March 2018) Gtk2: Background is used as bar-chart of sort. See screenshot.");
final Color blue = display.getSystemColor(SWT.COLOR_BLUE);
final Color white = display.getSystemColor(SWT.COLOR_WHITE);
final Color red = display.getSystemColor(SWT.COLOR_RED);
// final Image parliamentImage = new Image(display, "./parliament.jpg");
final Table table = new Table(shell, SWT.NONE);
table.setBounds(10,10,350,300);
// table.setBackgroundImage(parliamentImage);
for (int i = 0; i < 12; i++) {
TableItem item = new TableItem(table, SWT.NONE);
item.setText(MONTHS[i] + " (" + LOWS[i] + "C..." + HIGHS[i] + "C)");
}
final int clientWidth = table.getClientArea().width;
/*
* NOTE: MeasureItem and EraseItem are called repeatedly. Therefore it is
* critical for performance that these methods be as efficient as possible.
*/
table.addListener(SWT.MeasureItem, event -> {
int itemIndex = table.indexOf((TableItem)event.item);
int rightX = (HIGHS[itemIndex] - SCALE_MIN) * clientWidth / SCALE_RANGE;
event.width = rightX;
});
table.addListener(SWT.EraseItem, event -> {
int itemIndex = table.indexOf((TableItem)event.item);
int leftX = (LOWS[itemIndex] - SCALE_MIN) * clientWidth / SCALE_RANGE;
int rightX = (HIGHS[itemIndex] - SCALE_MIN) * clientWidth / SCALE_RANGE;
GC gc = event.gc;
Rectangle clipping = gc.getClipping();
clipping.x = leftX;
clipping.width = rightX - leftX;
gc.setClipping(clipping);
Color oldForeground = gc.getForeground();
Color oldBackground = gc.getBackground();
gc.setForeground(blue);
gc.setBackground(white);
gc.fillGradientRectangle(event.x, event.y, event.width / 2, event.height, false);
gc.setForeground(white);
gc.setBackground(red);
gc.fillGradientRectangle(
event.x + event.width / 2, event.y, event.width / 2, event.height, false);
gc.setForeground(oldForeground);
gc.setBackground(oldBackground);
event.detail &= ~SWT.BACKGROUND;
event.detail &= ~SWT.HOT;
});
shell.setSize(SWIDTH, SHEIGHT);
shell.open();
mainLoop(shell);
}
@Test
public void ownerDrawn_icons_on_right_side_of_column_Snippet230() {
Shell shell = mkShell("Verify icons are visible on all columns on right side. (on gtk3, icons are cut off Bug 531882)");
knownToBeBrokenGtk3("On gtk3, icons in col 1 and 2 are cut off. Bug 531882");
final Image image = display.getSystemImage(SWT.ICON_INFORMATION);
shell.setLayout(new FillLayout ());
Table table = new Table(shell, SWT.MULTI | SWT.FULL_SELECTION);
table.setHeaderVisible(true);
table.setLinesVisible(true);
int columnCount = 3;
for (int i=0; i<columnCount; i++) {
TableColumn column = new TableColumn(table, SWT.NONE);
column.setText("Column " + i);
}
int itemCount = 8;
for(int i = 0; i < itemCount; i++) {
TableItem item = new TableItem(table, SWT.NONE);
item.setText(new String[] {"item "+i+" a", "item "+i+" b", "item "+i+" c"});
}
/*
* NOTE: MeasureItem, PaintItem and EraseItem are called repeatedly.
* Therefore, it is critical for performance that these methods be
* as efficient as possible.
*/
Listener paintListener = event -> {
switch(event.type) {
case SWT.MeasureItem: {
Rectangle rect1 = image.getBounds();
event.width += rect1.width;
event.height = Math.max(event.height, rect1.height + 2);
break;
}
case SWT.PaintItem: {
int x = event.x + event.width;
Rectangle rect2 = image.getBounds();
int offset = Math.max(0, (event.height - rect2.height) / 2);
event.gc.drawImage(image, x, event.y + offset);
break;
}
}
};
table.addListener(SWT.MeasureItem, paintListener);
table.addListener(SWT.PaintItem, paintListener);
for(int i = 0; i < columnCount; i++) {
table.getColumn(i).pack();
}
shell.setSize (SWIDTH, SHEIGHT);
shell.open();
shell.addDisposeListener(e -> {
if(image != null) image.dispose();
});
mainLoop(shell);
}
@Test
public void ownerDrawn_barChart_Snippet228() {
Shell shell = mkShell("Ensure you see bar-charts in 2nd column and they resize with shell.");
shell.setLayout(new FillLayout());
final Table table = new Table(shell, SWT.BORDER);
table.setHeaderVisible(true);
table.setLinesVisible(true);
TableColumn column1 = new TableColumn(table, SWT.NONE);
column1.setText("Bug Status");
column1.setWidth(100);
final TableColumn column2 = new TableColumn(table, SWT.NONE);
column2.setText("Percent");
column2.setWidth(200);
String[] labels = new String[]{"Resolved", "New", "Won't Fix", "Invalid"};
for (int i=0; i<labels.length; i++) {
TableItem item = new TableItem(table, SWT.NONE);
item.setText(labels[i]);
}
/*
* NOTE: MeasureItem, PaintItem and EraseItem are called repeatedly.
* Therefore, it is critical for performance that these methods be
* as efficient as possible.
*/
table.addListener(SWT.PaintItem, new Listener() {
int[] percents = new int[] {50, 30, 5, 15};
@Override
public void handleEvent(Event event) {
if (event.index == 1) {
GC gc = event.gc;
TableItem item = (TableItem)event.item;
int index = table.indexOf(item);
int percent = percents[index];
Color foreground = gc.getForeground();
Color background = gc.getBackground();
gc.setForeground(display.getSystemColor(SWT.COLOR_RED));
gc.setBackground(display.getSystemColor(SWT.COLOR_YELLOW));
int width = (column2.getWidth() - 1) * percent / 100;
gc.fillGradientRectangle(event.x, event.y, width, event.height, true);
Rectangle rect2 = new Rectangle(event.x, event.y, width-1, event.height-1);
gc.drawRectangle(rect2);
gc.setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND));
String text = percent+"%";
Point size = event.gc.textExtent(text);
int offset = Math.max(0, (event.height - size.y) / 2);
gc.drawText(text, event.x+2, event.y+offset, true);
gc.setForeground(background);
gc.setBackground(foreground);
}
}
});
shell.setSize (SWIDTH, SHEIGHT);
shell.open();
mainLoop(shell);
}
@Test
public void ownerDrawn_textAlignment_Snippet231 () {
Shell shell = mkShell("Ensure there is no cheese, also when hoving over items");
final int COLUMN_COUNT = 4;
final int ITEM_COUNT = 8;
final int TEXT_MARGIN = 3;
shell.setLayout(new FillLayout());
final Table table = new Table(shell, SWT.FULL_SELECTION);
table.setHeaderVisible(true);
table.setLinesVisible(true);
for (int i = 0; i < COLUMN_COUNT; i++) {
new TableColumn(table, SWT.NONE);
}
for (int i = 0; i < ITEM_COUNT; i++) {
TableItem item = new TableItem(table, SWT.NONE);
for (int j = 0; j < COLUMN_COUNT; j++) {
String string = "item " + i + " col " + j;
if ((i + j) % 3 == 1) {
string +="\nnew line1";
}
if ((i + j) % 3 == 2) {
string +="\nnew line1\nnew line2";
}
item.setText(j, string);
}
}
/*
* NOTE: MeasureItem, PaintItem and EraseItem are called repeatedly.
* Therefore, it is critical for performance that these methods be
* as efficient as possible.
*/
table.addListener(SWT.MeasureItem, event -> {
TableItem item = (TableItem)event.item;
String text = item.getText(event.index);
Point size = event.gc.textExtent(text);
event.width = size.x + 2 * TEXT_MARGIN;
event.height = Math.max(event.height, size.y + TEXT_MARGIN);
});
table.addListener(SWT.EraseItem, event -> event.detail &= ~SWT.FOREGROUND);
table.addListener(SWT.PaintItem, event -> {
TableItem item = (TableItem)event.item;
String text = item.getText(event.index);
/* center column 1 vertically */
int yOffset = 0;
if (event.index == 1) {
Point size = event.gc.textExtent(text);
yOffset = Math.max(0, (event.height - size.y) / 2);
}
event.gc.drawText(text, event.x + TEXT_MARGIN, event.y + yOffset, true);
});
for (int i = 0; i < COLUMN_COUNT; i++) {
table.getColumn(i).pack();
}
shell.open();
mainLoop(shell);
}
@Test
public void ownerDrawn_multiColumn_gc_snippet239 () {
Shell shell = mkShell("Verify that text is correctly drawn across 2 columns");
shell.setText("Text spans two columns in a TableItem");
shell.setLayout (new FillLayout());
final Table table = new Table(shell, SWT.MULTI | SWT.FULL_SELECTION);
table.setHeaderVisible(true);
int columnCount = 4;
for (int i=0; i<columnCount; i++) {
TableColumn column = new TableColumn(table, SWT.NONE);
column.setText("Column " + i);
}
int itemCount = 8;
for (int i = 0; i < itemCount; i++) {
TableItem item = new TableItem(table, SWT.NONE);
item.setText(0, "item "+i+" a");
item.setText(3, "item "+i+" d");
}
/*
* NOTE: MeasureItem, PaintItem and EraseItem are called repeatedly.
* Therefore, it is critical for performance that these methods be
* as efficient as possible.
*/
final String string = "text that spans two columns";
GC gc = new GC(table);
final Point extent = gc.stringExtent(string);
gc.dispose();
final Color red = display.getSystemColor(SWT.COLOR_RED);
Listener paintListener = event -> {
switch(event.type) {
case SWT.MeasureItem: {
if (event.index == 1 || event.index == 2) {
event.width = extent.x/2;
event.height = Math.max(event.height, extent.y + 2);
}
break;
}
case SWT.PaintItem: {
if (event.index == 1 || event.index == 2) {
int offset = 0;
if (event.index == 2) {
TableColumn column1 = table.getColumn(1);
offset = column1.getWidth();
}
event.gc.setForeground(red);
int y = event.y + (event.height - extent.y)/2;
event.gc.drawString(string, event.x - offset, y, true);
}
break;
}
}
};
table.addListener(SWT.MeasureItem, paintListener);
table.addListener(SWT.PaintItem, paintListener);
for (int i = 0; i < columnCount; i++) {
table.getColumn(i).pack();
}
shell.setSize(SWIDTH, SHEIGHT);
shell.open();
mainLoop(shell);
}
@Test
public void ownerDrawn_CustomItemHeight () {
Shell shell = mkShell("Ensure Item 3 (yellow) is bigger than the other items");
int bigItem = 3;
shell.setLayout(new FillLayout());
shell.setSize (SWIDTH, SHEIGHT);
final Table table = new Table(shell, SWT.NONE);
table.setLinesVisible(true);
for (int i = 0; i < 5; i++) {
TableItem item = new TableItem(table, SWT.NONE);
if (i == bigItem) {
item.setText("Item " + bigItem + " has bigger height");
item.setBackground(display.getSystemColor(SWT.COLOR_YELLOW));
}
else {
item.setText("item " + i);
item.setBackground(display.getSystemColor(SWT.COLOR_DARK_GRAY));
}
}
/*
* NOTE: MeasureItem is called repeatedly. Therefore it is critical
* for performance that this method be as efficient as possible.
*/
table.addListener(SWT.MeasureItem, event -> {
int clientWidth = table.getClientArea().width;
event.height = event.gc.getFontMetrics().getHeight() * 2; // * table.indexOf((TableItem) event.item) to have different height rows.
event.width = clientWidth * 2;
if (table.indexOf((TableItem) event.item) == bigItem) {
event.height *= 2;
}
});
shell.open();
mainLoop(shell);
}
/**
* Snippet 144 modified to auto-populate items when shell is activated instead.
*/
@Test
public void virtual_addManyItems_Snippet144 () {
final Shell shell = mkShell("Shell Should show and items should be populated in lazy way");
shell.setSize (SWIDTH, SHEIGHT);
final int COUNT = 100000;
shell.setLayout(new RowLayout(SWT.VERTICAL));
final Table table = new Table (shell, SWT.VIRTUAL | SWT.BORDER);
final Label label1 = new Label(shell, SWT.NONE);
table.addListener (SWT.SetData, event -> {
TableItem item = (TableItem) event.item;
int index = table.indexOf (item);
item.setText ("Item " + index);
label1.setText("Added " + item.getText());
});
table.setLayoutData (new RowData (shell.getBounds().width - 100, 400));
final Label label2 = new Label(shell, SWT.NONE);
shell.addShellListener( new ShellAdapter() {
@Override
public void shellActivated(ShellEvent e) {
System.out.println("activated");
long t1 = System.currentTimeMillis ();
table.setItemCount (COUNT);
long t2 = System.currentTimeMillis ();
label2.setText ("Items: " + COUNT + ", Time: " + (t2 - t1) + " (ms)");
shell.layout ();
}
});
shell.open ();
mainLoop(shell);
}
@Test
public void column_headers_Snippet38() {
Shell shell = mkShell("Matrix with rows & columns and columns with description. (BUG gtk2/3 text seems slightly cut off, Bug 531875)");
knownToBeBrokenGtk("Text in column is cut off at the moment. See Bug 531875");
shell.setLayout(new GridLayout());
Table table = new Table (shell, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION);
table.setLinesVisible (true);
table.setHeaderVisible (true);
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
data.heightHint = 200;
table.setLayoutData(data);
String[] titles = {" ", "C", "!", "Description", "Resource", "In Folder", "Location"};
for (int i=0; i<titles.length; i++) {
TableColumn column = new TableColumn (table, SWT.NONE);
column.setText (titles [i]);
}
int count = 128;
for (int i=0; i<count; i++) {
TableItem item = new TableItem (table, SWT.NONE);
item.setText (0, "x");
item.setText (1, "y");
item.setText (2, "!");
item.setText (3, "this stuff behaves the way I expect");
item.setText (4, "almost everywhere");
item.setText (5, "some.folder");
item.setText (6, "line " + i + " in nowhere");
}
for (int i=0; i<titles.length; i++) {
table.getColumn (i).pack ();
}
shell.setSize(SWIDTH, SHEIGHT);
shell.open ();
mainLoop(shell);
}
// TODO - see how this behaves on windows.
@Test
public void column_noWidth_bug399522 () {
Shell shell = mkShell("Expected : (Not sure?) On Gtk/Cocoa no items are now shown till column width is actually specified or column is packed.");
final Table table = new Table(shell, SWT.BORDER);
table.setHeaderVisible(true);
new TableItem(table, SWT.NONE).setText("Item1");
TableColumn column1 = new TableColumn(table, SWT.NONE);
// column1.setWidth(10); // Setting column width makes items visible.
// column1.pack();
table.setSize(200, 200);
System.out.println(column1.handle);
shell.addListener(SWT.MouseDown, event -> System.out.println(table.computeSize(-1, -1)));
TableColumn col2 = new TableColumn(table, SWT.NONE);
System.out.println(col2.handle);
shell.setSize(SWIDTH, SHEIGHT);
shell.open();
mainLoop(shell);
}
@Test
public void column_header_icons_Snippet297() {
Display display = new Display ();
Image images[] = new Image[] {
display.getSystemImage(SWT.ICON_INFORMATION),
display.getSystemImage(SWT.ICON_ERROR),
display.getSystemImage(SWT.ICON_QUESTION),
display.getSystemImage(SWT.ICON_WARNING),
};
String[] titles = {"Information", "Error", "Question", "Warning"};
String[] questions = {"who?", "what?", "where?", "when?", "why?"};
Shell shell = new Shell (display);
shell.setLayout(new GridLayout());
Table table = new Table (shell, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION);
GridData data = new GridData (SWT.FILL, SWT.FILL, true, true);
data.heightHint = 200;
table.setLayoutData (data);
table.setLinesVisible (true);
table.setHeaderVisible (true);
for (int i=0; i<titles.length; i++) {
TableColumn column = new TableColumn (table, SWT.NONE);
column.setText (titles [i]);
column.setImage(images [i]);
}
int count = 128;
for (int i=0; i<count; i++) {
TableItem item = new TableItem (table, SWT.NONE);
item.setText (0, "some info");
item.setText (1, "error #" + i);
item.setText (2, questions [i % questions.length]);
item.setText (3, "look out!");
}
for (int i=0; i<titles.length; i++) {
table.getColumn (i).pack ();
}
table.setHeaderBackground(display.getSystemColor(SWT.COLOR_BLUE));
table.setHeaderForeground(display.getSystemColor(SWT.COLOR_RED));
shell.setSize(SWIDTH, SHEIGHT);
shell.open ();
mainLoop(shell);
}
/**
* Based on Snippet 106 with some modificaitons.
*/
@Test
public void column_dynamically_added_after_shellOpened_Snippet106() {
Shell shell = mkShell("Verify dynamic column (2) was added properly.");
final Table table = new Table (shell, SWT.BORDER | SWT.MULTI);
table.setHeaderVisible (true);
for (int i=0; i<4; i++) {
TableColumn column = new TableColumn (table, SWT.NONE);
column.setText ("Column " + i);
}
final TableColumn [] columns = table.getColumns ();
for (int i=0; i<12; i++) {
TableItem item = new TableItem (table, SWT.NONE);
for (int j=0; j<columns.length; j++) {
item.setText (j, "Item " + i);
}
}
for (int i=0; i<columns.length; i++) columns [i].pack ();
Button button = new Button (shell, SWT.PUSH);
final int index = 1;
button.setText ("Insert Column " + index + "a");
shell.addShellListener(new ShellAdapter() {
@Override
public void shellActivated(ShellEvent e) {
TableColumn column = new TableColumn (table, SWT.NONE, index);
column.setImage(display.getSystemImage(SWT.ICON_WARNING)); //added to make it easier to spot in a test.
column.setText ("Column " + index + " added after shellopen");
TableItem [] items = table.getItems ();
for (int i=0; i<items.length; i++) {
items [i].setText (index, "Item " + i + " added");
}
column.pack ();
}
});
shell.setSize (SWIDTH, SHEIGHT);
Rectangle shellClientArea = shell.getClientArea();
table.setSize(shellClientArea.width, shellClientArea.height);
shell.open ();
mainLoop(shell);
}
@Test
public void column_dynamic_resize() {
Shell shell = mkShell("Try resizing shell. Columns should resize as you resize shell");
shell.setLayout(new FillLayout());
final Composite comp = new Composite(shell, SWT.NONE);
final Table table = new Table(comp, SWT.BORDER | SWT.V_SCROLL);
table.setHeaderVisible(true);
table.setLinesVisible(true);
final TableColumn column1 = new TableColumn(table, SWT.NONE);
column1.setText("Column 1");
final TableColumn column2 = new TableColumn(table, SWT.NONE);
column2.setText("Column 2");
for (int i = 0; i < 10; i++) {
TableItem item = new TableItem(table, SWT.NONE);
item.setText(new String[] {"item 0" + i, "item 1"+i});
}
comp.addControlListener(ControlListener.controlResizedAdapter(e -> {
Rectangle area = comp.getClientArea();
Point size = table.computeSize(SWT.DEFAULT, SWT.DEFAULT);
ScrollBar vBar = table.getVerticalBar();
int width = area.width - table.computeTrim(0, 0, 0, 0).width - vBar.getSize().x;
if (size.y > area.height + table.getHeaderHeight()) {
// Subtract the scrollbar width from the total column width
// if a vertical scrollbar will be required
Point vBarSize = vBar.getSize();
width -= vBarSize.x;
}
Point oldSize = table.getSize();
if (oldSize.x > area.width) {
// table is getting smaller so make the columns
// smaller first and then resize the table to
// match the client area width
column1.setWidth(width / 3);
column2.setWidth(width - column1.getWidth());
table.setSize(area.width, area.height);
} else {
// table is getting bigger so make the table
// bigger first and then make the columns wider
// to match the client area width
table.setSize(area.width, area.height);
column1.setWidth(width / 3);
column2.setWidth(width - column1.getWidth());
}
}));
shell.open();
mainLoop(shell);
}
@Test
public void measureItem_custom_Column_width_onPack_Snippet272() {
Shell shell = mkShell("Double click on column boundary '|', observe column get's bigger");
shell.setSize(SWIDTH, SHEIGHT);
shell.setLayout(new FillLayout());
Table table = new Table(shell, SWT.NONE);
table.setHeaderVisible(true);
table.setLinesVisible(true);
final TableColumn column0 = new TableColumn(table, SWT.NONE);
column0.setWidth(110);
column0.setText("2x Click pipe ->");
final TableColumn column1 = new TableColumn(table, SWT.NONE);
column1.setWidth(110);
column0.addListener(SWT.Selection, event -> column0.pack());
column1.addListener(SWT.Selection, event -> column1.pack());
for (int i = 0; i < 5; i++) {
TableItem item = new TableItem(table, SWT.NONE);
item.setText(0, "item " + i + " col 0");
item.setText(1, "item " + i + " col 1");
}
/*
* NOTE: MeasureItem is called repeatedly. Therefore it is critical
* for performance that this method be as efficient as possible.
*/
table.addListener(SWT.MeasureItem, event -> event.width *= 4); // This guy makes the difference.
shell.open();
mainLoop(shell);
}
@Test
public void checkBoxes() {
Shell shell = mkShell("You should see some checkboxes");
shell.setLayout(new FillLayout());
Table table = new Table (shell, SWT.CHECK | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
for (int i=0; i<12; i++) {
TableItem item = new TableItem (table, SWT.NONE);
item.setText ("Item " + i);
}
Rectangle clientArea = shell.getClientArea ();
table.setBounds (clientArea.x, clientArea.y, 600, 500);
final Label label = new Label(shell, SWT.NONE);
table.addListener (SWT.Selection, event -> {
String string = event.detail == SWT.CHECK ? "Checked" : "Selected";
label.setText(event.item + " " + string);
});
shell.setSize(SWIDTH, SHEIGHT);
shell.open ();
mainLoop(shell);
}
@Test
public void color_singleColumn() {
Shell shell = mkShell("Header and content should be colored red and blue. Column header should be of a darker color.");
shell.setLayout(new FillLayout());
Table table = new Table (shell, SWT.None);
table.setHeaderVisible(true);
TableColumn column = new TableColumn(table, SWT.LEFT);
column.setText("Column header has darker colors.");
column.pack();
for (int i = 0; i < 200; i++) {
TableItem item = new TableItem(table, SWT.None);
item.setText("Item " + i);
}
table.setBackground(display.getSystemColor(SWT.COLOR_BLUE));
table.setForeground(display.getSystemColor(SWT.COLOR_RED));
table.setHeaderBackground(display.getSystemColor(SWT.COLOR_DARK_BLUE));
table.setHeaderForeground(display.getSystemColor(SWT.COLOR_DARK_RED));
shell.open();
mainLoop(shell);
}
@Test
public void color_MultipleColumn() {
Shell shell = mkShell("Header and content should be colored red and blue. Column header should be of a darker color.");
shell.setLayout(new FillLayout());
Table table = new Table (shell, SWT.None);
table.setHeaderVisible(true);
TableColumn column = new TableColumn(table, SWT.LEFT);
column.setText("Column 1");
column.pack();
TableColumn column2 = new TableColumn(table, SWT.LEFT);
column2.setText("Column 2");
column2.pack();
for (int i = 0; i < 200; i++) {
TableItem item = new TableItem(table, SWT.None);
item.setText(new String[] {"Item " + i, "Item col2: " + i});
}
table.setBackground(display.getSystemColor(SWT.COLOR_BLUE));
table.setForeground(display.getSystemColor(SWT.COLOR_RED));
table.setHeaderBackground(display.getSystemColor(SWT.COLOR_DARK_BLUE));
table.setHeaderForeground(display.getSystemColor(SWT.COLOR_DARK_RED));
shell.open();
mainLoop(shell);
}
@Test
public void color_differentCells_Snippet129 () {
Shell shell = mkShell("Table cells should be of different colors");
Color red = display.getSystemColor(SWT.COLOR_RED);
Color blue = display.getSystemColor(SWT.COLOR_BLUE);
Color white = display.getSystemColor(SWT.COLOR_WHITE);
Color gray = display.getSystemColor(SWT.COLOR_GRAY);
shell.setLayout(new FillLayout());
Table table = new Table(shell, SWT.BORDER | SWT.FULL_SELECTION);
table.setBackground(gray);
TableColumn column1 = new TableColumn(table, SWT.NONE);
TableColumn column2 = new TableColumn(table, SWT.NONE);
TableColumn column3 = new TableColumn(table, SWT.NONE);
TableItem item = new TableItem(table, SWT.NONE);
item.setText(new String[] {"entire","row","red foreground"});
item.setForeground(red);
item = new TableItem(table, SWT.NONE);
item.setText(new String[] {"entire","row","red background"});
item.setBackground(red);
item = new TableItem(table, SWT.NONE);
item.setText(new String[] {"entire","row","white fore/red back"});
item.setForeground(white);
item.setBackground(red);
item = new TableItem(table, SWT.NONE);
item.setText(new String[] {"normal","blue foreground","red foreground"});
item.setForeground(1, blue);
item.setForeground(2, red);
item = new TableItem(table, SWT.NONE);
item.setText(new String[] {"normal","blue background","red background"});
item.setBackground(1, blue);
item.setBackground(2, red);
item = new TableItem(table, SWT.NONE);
item.setText(new String[] {"white fore/blue back","normal","white fore/red back"});
item.setForeground(0, white);
item.setBackground(0, blue);
item.setForeground(2, white);
item.setBackground(2, red);
column1.pack();
column2.pack();
column3.pack();
shell.setSize(SWIDTH, SHEIGHT);
shell.open();
mainLoop(shell);
}
@Test
public void programaticScrolling_Snippet52() {
Shell shell = mkShell("Table should be scrolled down to 100th item");
Table table = new Table (shell, SWT.BORDER | SWT.MULTI);
Rectangle clientArea = shell.getClientArea ();
table.setBounds (clientArea.x, clientArea.y,800, 600);
for (int i=0; i<128; i++) {
TableItem item = new TableItem (table, SWT.NONE);
item.setText ("Item " + i);
}
table.setSelection (100); // <<< This is what we're testing.
shell.pack ();
shell.open ();
mainLoop(shell);
}
@Test
public void sort_by_column_Snippet2() {
Shell shell = mkShell("Click on columns to verify items are sorted properly");
shell.setLayout(new FillLayout());
final Table table = new Table(shell, SWT.BORDER);
table.setHeaderVisible(true);
final TableColumn column1 = new TableColumn(table, SWT.NONE);
column1.setText("Column 1");
final TableColumn column2 = new TableColumn(table, SWT.NONE);
column2.setText("Column 2");
TableItem item = new TableItem(table, SWT.NONE);
item.setText(new String[] {"a", "3"});
item = new TableItem(table, SWT.NONE);
item.setText(new String[] {"b", "2"});
item = new TableItem(table, SWT.NONE);
item.setText(new String[] {"c", "1"});
column1.setWidth(100);
column2.setWidth(100);
Listener sortListener = e -> {
TableItem[] items = table.getItems();
Collator collator = Collator.getInstance(Locale.getDefault());
TableColumn column = (TableColumn)e.widget;
int index = column == column1 ? 0 : 1;
for (int i = 1; i < items.length; i++) {
String value1 = items[i].getText(index);
for (int j = 0; j < i; j++){
String value2 = items[j].getText(index);
if (collator.compare(value1, value2) < 0) {
String[] values = {items[i].getText(0), items[i].getText(1)};
items[i].dispose();
TableItem item1 = new TableItem(table, SWT.NONE, j);
item1.setText(values);
items = table.getItems();
break;
}
}
}
table.setSortColumn(column);
};
column1.addListener(SWT.Selection, sortListener);
column2.addListener(SWT.Selection, sortListener);
table.setSortColumn(column1);
table.setSortDirection(SWT.UP);
shell.setSize(SWIDTH, SHEIGHT);
shell.open();
mainLoop(shell);
}
@Test
public void sort_by_columnt_virtual_Snippet192 () {
Shell shell = mkShell("Click on column heading to sort");
// initialize data with keys and random values
int size = 100;
Random random = new Random();
final int[][] data = new int[size][];
for (int i = 0; i < data.length; i++) {
data[i] = new int[] {i, random.nextInt()};
}
// create a virtual table to display data
shell.setLayout(new FillLayout());
final Table table = new Table(shell, SWT.VIRTUAL);
table.setHeaderVisible(true);
table.setLinesVisible(true);
table.setItemCount(size);
final TableColumn column1 = new TableColumn(table, SWT.NONE);
column1.setText("Key");
column1.setWidth(200);
final TableColumn column2 = new TableColumn(table, SWT.NONE);
column2.setText("Value");
column2.setWidth(200);
table.addListener(SWT.SetData, e -> {
TableItem item = (TableItem) e.item;
int index = table.indexOf(item);
int[] datum = data[index];
item.setText(new String[] {Integer.toString(datum[0]),
Integer.toString(datum[1]) });
});
// Add sort indicator and sort data when column selected
Listener sortListener = e -> {
// determine new sort column and direction
TableColumn sortColumn = table.getSortColumn();
TableColumn currentColumn = (TableColumn) e.widget;
int dir = table.getSortDirection();
if (sortColumn == currentColumn) {
dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
} else {
table.setSortColumn(currentColumn);
dir = SWT.UP;
}
// sort the data based on column and direction
final int index = currentColumn == column1 ? 0 : 1;
final int direction = dir;
Arrays.sort(data, (a, b) -> {
if (a[index] == b[index]) return 0;
if (direction == SWT.UP) {
return a[index] < b[index] ? -1 : 1;
}
return a[index] < b[index] ? 1 : -1;
});
// update data displayed in table
table.setSortDirection(dir);
table.clearAll();
};
column1.addListener(SWT.Selection, sortListener);
column2.addListener(SWT.Selection, sortListener);
table.setSortColumn(column1);
table.setSortDirection(SWT.UP);
shell.setSize(SWIDTH, SHEIGHT);
shell.open();
mainLoop(shell);
}
@Test
public void icons_ofDiffSize_inItems_Snippet349() {
Shell shell = mkShell("Verify that items have icons of different sizes and icons are not cut off");
BiFunction<Integer, Integer, Image> createImage = (width, height) -> {
Image result = new Image(display, width, height);
GC gc = new GC(result);
for (int x = -height; x < width; x += 4) {
gc.drawLine(x, 0, x + height, height);
}
gc.dispose();
return result;
};
final int COLUMN_COUNT = 3;
final int TEXT_MARGIN = 3;
final String KEY_WIDTHS = "widths";
final String KEY_IMAGES = "images";
Image[] images = new Image[4];
images[0] = createImage.apply(16, 16);
images[1] = createImage.apply(32, 16);
images[2] = createImage.apply(48, 16);
shell.setLayout(new FillLayout());
Table table = new Table(shell, SWT.NONE);
for (int i = 0; i < COLUMN_COUNT; i++) {
new TableColumn(table, SWT.NONE);
}
for (int i = 0; i < 8; i++) {
TableItem item = new TableItem(table, SWT.NONE);
Image[] itemImages = new Image[COLUMN_COUNT];
item.setData(KEY_IMAGES, itemImages);
for (int j = 0; j < COLUMN_COUNT; j++) {
item.setText(j, "item " + i + " col " + j);
itemImages[j] = images[(i * COLUMN_COUNT + j) % images.length];
}
}
/*
* NOTE: MeasureItem, PaintItem and EraseItem are called repeatedly.
* Therefore, it is critical for performance that these methods be
* as efficient as possible.
*/
final int itemHeight = table.getItemHeight();
GC gc = new GC(table);
FontMetrics metrics = gc.getFontMetrics();
final int fontHeight = metrics.getHeight();
gc.dispose();
Listener paintListener = event -> {
switch (event.type) {
case SWT.MeasureItem: {
int column1 = event.index;
TableItem item1 = (TableItem)event.item;
Image[] images1 = (Image[])item1.getData(KEY_IMAGES);
Image image1 = images1[column1];
if (image1 == null) {
/* don't change the native-calculated event.width */
break;
}
int[] cachedWidths = (int[])item1.getData(KEY_WIDTHS);
if (cachedWidths == null) {
cachedWidths = new int[COLUMN_COUNT];
item1.setData(KEY_WIDTHS, cachedWidths);
}
if (cachedWidths[column1] == 0) {
int width = image1.getBounds().width + 2 * TEXT_MARGIN;
GC gc1 = new GC(item1.getParent());
width += gc1.stringExtent(item1.getText()).x;
gc1.dispose();
cachedWidths[column1] = width;
}
event.width = cachedWidths[column1];
break;
}
case SWT.EraseItem: {
int column2 = event.index;
TableItem item2 = (TableItem)event.item;
Image[] images2 = (Image[])item2.getData(KEY_IMAGES);
Image image2 = images2[column2];
if (image2 == null) {
break;
}
/* disable the native drawing of this item */
event.detail &= ~SWT.FOREGROUND;
break;
}
case SWT.PaintItem: {
int column3 = event.index;
TableItem item3 = (TableItem)event.item;
Image[] images3 = (Image[])item3.getData(KEY_IMAGES);
Image image3 = images3[column3];
if (image3 == null) {
/* this item is drawn natively, don't touch it*/
break;
}
int x = event.x;
event.gc.drawImage(image3, x, event.y + (itemHeight - image3.getBounds().height) / 2);
x += image3.getBounds().width + TEXT_MARGIN;
event.gc.drawString(item3.getText(column3), x, event.y + (itemHeight - fontHeight) / 2);
break;
}
}
};
table.addListener(SWT.MeasureItem, paintListener);
table.addListener(SWT.EraseItem, paintListener);
table.addListener(SWT.PaintItem, paintListener);
for (int i = 0; i < COLUMN_COUNT; i++) {
table.getColumn(i).pack();
}
shell.addDisposeListener(e -> {
for (int i = 0; i < images.length; i++) {
if (images[i] != null) {
images[i].dispose();
}
}
});
shell.setSize(SWIDTH, SHEIGHT);
shell.open();
mainLoop(shell);
}
@Test
public void styledItems_Snippet236() {
Shell shell = mkShell("Verify tableitems with custom styleText control looks proper & multiple items can be selected");
shell.setLayout(new FillLayout());
Table table = new Table(shell, SWT.MULTI | SWT.FULL_SELECTION);
table.setLinesVisible(true);
for(int i = 0; i < 10; i++) {
new TableItem(table, SWT.NONE);
}
final TextLayout textLayout = new TextLayout(display);
textLayout.setText("SWT: Standard Widget Toolkit");
Font font1 = new Font(display, "Tahoma", 14, SWT.BOLD);
Font font2 = new Font(display, "Tahoma", 10, SWT.NORMAL);
Font font3 = new Font(display, "Tahoma", 14, SWT.ITALIC);
TextStyle style1 = new TextStyle(font1, display.getSystemColor(SWT.COLOR_BLUE), null);
TextStyle style2 = new TextStyle(font2, display.getSystemColor(SWT.COLOR_MAGENTA), null);
TextStyle style3 = new TextStyle(font3, display.getSystemColor(SWT.COLOR_RED), null);
textLayout.setStyle(style1, 0, 0); textLayout.setStyle(style1, 5, 12);
textLayout.setStyle(style2, 1, 1); textLayout.setStyle(style2, 14, 19);
textLayout.setStyle(style3, 2, 2); textLayout.setStyle(style3, 21, 27);
/*
* NOTE: MeasureItem, PaintItem and EraseItem are called repeatedly.
* Therefore, it is critical for performance that these methods be
* as efficient as possible.
*/
table.addListener(SWT.PaintItem, event -> textLayout.draw(event.gc, event.x, event.y));
final Rectangle textLayoutBounds = textLayout.getBounds();
table.addListener(SWT.MeasureItem, e -> {
e.width = textLayoutBounds.width + 2;
e.height = textLayoutBounds.height + 2;
});
shell.setSize (SWIDTH, SHEIGHT);
shell.open();
shell.addDisposeListener(e -> {
font1.dispose();
font2.dispose();
font3.dispose();
textLayout.dispose();
});
mainLoop(shell);
}
@Test
public void cout_visible_items_Snippet253 () {
final Shell shell = mkShell("Ensure correct item count is displayed in count. Try resizing shell to show 15 items, it should show 15. Gtk3 issues");
knownToBeBrokenGtk3("On gtk3, the measure is off, see bug 531884");
FillLayout layout = new FillLayout (SWT.VERTICAL);
shell.setLayout (layout);
final Table table = new Table (shell, SWT.NONE);
for (int i=0; i<32; i++) {
TableItem item = new TableItem (table, SWT.NONE);
item.setText ("Item " + (i+1) + " is quite long");
}
final Button button = new Button (shell, SWT.PUSH);
Runnable fixCount = () -> {
Rectangle rect = table.getClientArea ();
int itemHeight = table.getItemHeight ();
int headerHeight = table.getHeaderHeight ();
int visibleCount = (rect.height - headerHeight + itemHeight - 1) / itemHeight;
button.setText ("Visible Items [" + visibleCount + "]");
};
button.setText ("Visible Items []");
button.addListener (SWT.Selection, e -> {
fixCount.run();
});
shell.addControlListener(new ControlAdapter() {
@Override
public void controlResized(ControlEvent e) {
fixCount.run();
}
});
shell.addShellListener(new ShellAdapter() {
@Override
public void shellActivated(ShellEvent e) {
fixCount.run();
}
});
// setSize(..)_ affects bug/snippet behaviour.
shell.setSize(1160, 820); //820 => ~15 items or so, depending on your theme.
shell.open();
mainLoop(shell);
}
/** Snippet 149 was modified.
* - No added columns.
* - Button instead of progress bar.
*/
@Test
public void tableEditor_multiple_controls_Snippet149 () {
knownToBeBrokenGtk3("Snippet is broken on Gtk3. See Bug 531885");
Shell shell = mkShell("Items should be replaced with Buttons (broken on Gtk3, Bug 531885)");
shell.setLayout (new FillLayout ());
Table table = new Table (shell, SWT.BORDER);
for (int i = 0; i < 20; i++) {
TableItem item = new TableItem (table, SWT.NONE);
item.setText ("Task " + i);
Button button = new Button (table, SWT.NONE);
button.setText("hello world " + i);
button.setVisible(true);
button.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
System.out.println("Button pressed");
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
});
TableEditor editor = new TableEditor (table);
editor.grabHorizontal = editor.grabVertical = true;
editor.setEditor (button, item, 0);
}
shell.setSize (SWIDTH, SHEIGHT);
shell.open();
mainLoop(shell);
}
@Test
public void tableEditor_dynamically_created_Snippet124() {
Shell shell = mkShell("Verify you can edit cells");
shell.setLayout (new FillLayout ());
final Table table = new Table(shell, SWT.BORDER | SWT.MULTI);
table.setLinesVisible (true);
for (int i=0; i<3; i++) {
TableColumn column = new TableColumn (table, SWT.NONE);
column.setWidth(100);
}
for (int i=0; i<3; i++) {
TableItem item = new TableItem (table, SWT.NONE);
item.setText(new String [] {"" + i, "" + i , "" + i});
}
final TableEditor editor = new TableEditor (table);
editor.horizontalAlignment = SWT.LEFT;
editor.grabHorizontal = true;
table.addListener (SWT.MouseDown, event -> {
Rectangle clientArea = table.getClientArea ();
Point pt = new Point (event.x, event.y);
int index = table.getTopIndex ();
while (index < table.getItemCount ()) {
boolean visible = false;
final TableItem item = table.getItem (index);
for (int i=0; i<table.getColumnCount (); i++) {
Rectangle rect = item.getBounds (i);
if (rect.contains (pt)) {
final int column = i;
final Text text = new Text (table, SWT.NONE);
Listener textListener = e -> {
switch (e.type) {
case SWT.FocusOut:
item.setText (column, text.getText ());
text.dispose ();
break;
case SWT.Traverse:
switch (e.detail) {
case SWT.TRAVERSE_RETURN:
item.setText (column, text.getText ());
//FALL THROUGH
case SWT.TRAVERSE_ESCAPE:
text.dispose ();
e.doit = false;
}
break;
}
};
text.addListener (SWT.FocusOut, textListener);
text.addListener (SWT.Traverse, textListener);
editor.setEditor (text, item, i);
text.setText (item.getText (i));
text.selectAll ();
text.setFocus ();
return;
}
if (!visible && rect.intersects (clientArea)) {
visible = true;
}
}
if (!visible) return;
index++;
}
});
shell.setSize(SWIDTH, SHEIGHT);
shell.open ();
mainLoop(shell);
}
}