Is MultiColumn- explorer widget available in swt? - swt

As windows provide to view multiple files in column as i attached in the image.
Is there any SWT Widget available to display/arrange objects in multi column way similar to windows?
I have already used "Row layout(SWT.Vertical)" but i am facing some performance issue while painting if it has more than 2000+ objects.
While windows explorer doesn't have this kind of performance issue if it has more than 6000 data.
I can't use table viewer as it has each row as one object, but in my requirement I need to have object in each cell
Do let me know if any in-built widget is available in JFace/SWT for multi column view explorer to arrange objects.
Thanks

I didn't able to find direct JFace/SWT widget for this requirement. May be others senior members can give pointers.
For your requirement Nebula Gallery Widget
NOTE: THIS WIDGET AND ITS API ARE STILL UNDER DEVELOPMENT, as written in its Javadoc
Code goes below :
public class Test {
public static void main(String[] args) {
Display display = new Display();
Image itemImage = new Image(display, Program.findProgram("jpg").getImageData()); //$NON-NLS-1$
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
Gallery gallery = new Gallery(shell, SWT.H_SCROLL | SWT.MULTI | SWT.VIRTUAL);
// Renderers
NoGroupRenderer gr = new NoGroupRenderer();
gr.setMinMargin(2);
gr.setItemHeight(20);
gr.setItemWidth(100);
gr.setAutoMargin(true);
gallery.setGroupRenderer(gr);
ListItemRenderer ir = new ListItemRenderer();
gallery.setItemRenderer(ir);
GalleryItem group = new GalleryItem(gallery, SWT.NONE);
for (int i = 0; i < 20000; i++) {
GalleryItem item = new GalleryItem(group, SWT.NONE);
if (itemImage != null) {
item.setImage(itemImage);
}
item.setText("Item " + i); //$NON-NLS-1$
}
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
Output :

Related

SWT gridlayout align

When put all widgets in one container, the gridlayout could align normally.
But for some reason, I need to put some widgets to a sub-container such as the composite as below. The alignment is different.
So the question is: Is there a container that has no effect on the gridlayout?
Ps: I know that can use white space as a workaround, but...
Code:
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
GridLayoutFactory.fillDefaults().numColumns(2).margins(8, 3).applyTo(shell);
new Label(shell, 0).setText("Label1");
new Text(shell, 0);
new Label(shell, 0).setText("A long Label");
new Text(shell, 0);
Composite composite = new Composite(shell, 0);
GridDataFactory.fillDefaults().span(2, 1).applyTo(composite);
GridLayoutFactory.fillDefaults().numColumns(2).applyTo(composite);
new Label(composite, 0).setText("Label22");
new Text(composite, 0);
new Label(composite, 0).setText("Label223");
new Text(composite, 0);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
Result:
There is no container that can used like this. Sticking to a single composite is by far the easiest way to aligh the labels.
It is possible to specify the widthHint of the GridData for a label to specify the width. You would have to calculate the width required using something like:
List<Control> labels = ... list of Label controls
final int width = labels.stream()
.mapToInt(label -> label.computeSize(SWT.DEFAULT, SWT.DEFAULT).x)
.max()
.getAsInt();
final var labelData = GridDataFactory.swtDefaults().hint(width, SWT.DEFAULT);
labels.forEach(labelData::applyTo);

SWT - How to change the size of Text box dynamically

I am trying to create a Simple UI which contains a combo, a text box and a browse button. The combo will be containing two values: Execution Times and Execute with File.
When the Execution Times option is selected, the combo box followed by a text box should be displayed.
when the Execute with File option is selected, the combo box, a text box, and a browse button should be displayed.
When I am switching between these options, the widgets are not getting aligned properly. Refer to the below image. The text box size is not getting expanded to the available space.
public class TestUI {
public static void main(String[] args)
{
Display display = new Display();
final Shell shell = new Shell(display);
shell.setText("StackOverflow");
shell.setLayout(new GridLayout(1, true));
Composite composite = new Composite(shell, SWT.NONE);
composite.setLayout(new GridLayout(3, false));
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
Combo combo = new Combo(composite, SWT.READ_ONLY);
String[] input = { "Execution Times", "Execute with File" };
combo.setItems(input);
Text loopText = new Text(composite, SWT.SINGLE | SWT.BORDER);
GridData gridData = new GridData(SWT.BEGINNING | GridData.FILL_HORIZONTAL);
gridData.horizontalSpan = 2;
loopText.setLayoutData(gridData);
loopText.setEnabled(false);
Button browseButton = new Button(composite, SWT.PUSH);
browseButton.setText("Browse...");
browseButton.setVisible(false);
combo.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
String text2 = combo.getText();
System.out.println(text2);
if (text2.equals("Execution Times")) {
loopText.setEnabled(true);
loopText.setText("1");//$NON-NLS-1$
GridData gridData1 = new GridData(SWT.BEGINNING, SWT.TOP, false, false);
gridData1.grabExcessHorizontalSpace = true;
gridData1.horizontalSpan = 2;
loopText.setLayoutData(gridData1);
browseButton.setVisible(false);
loopText.getParent().layout();
}
if (text2.equals("Execute with File")) {
GridData gridData1 = new GridData(SWT.BEGINNING, SWT.TOP, false, false);
gridData1.grabExcessHorizontalSpace = true;
loopText.setLayoutData(gridData1);
gridData.exclude= false;
browseButton.setVisible(true);
browseButton.setFocus();
loopText.setText("");
loopText.setEnabled(false);
loopText.getParent().layout();
}
}
});
shell.pack();
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
}
Can any one help me on this?
From what I understand, depending on the combo selection, the text field and text field plus button serve different purposes:
when Execution Times is selected, the number of times is to be entered
otherwise Execute with File requires a file name to be entered or browsed for
Therefore, I would use a Composite next to the combo widget to hold either a text field to enter a number (or even a Spinner) or a text field and button to enter/select a file name.
Composite composite = new Composite( parent, SWT.NONE );
Text executionTimesText = new Text( composite, SWT.BORDER );
composite.setLayout( new StackLayout() );
Composite executionFileComposite = new Composite( composite, SWT.NONE );
// use a GridLayout to position the file name text field and button within the executionFileComposite
combo.addListener( SWT.Selection, event -> {
StackLayout layout = ( StackLayout )composite.getLayout();
if( combo.getSelectionIndex() == 0 ) {
layout.topControl = executionTimesText;
} else if( combo.getSelectionIndex() == 1 ) {
layout.topControl = executionFileComposite;
}
composite.layout();
}
The StackLayout allows you to stack the different input fields and switch betwen them as needed (i.e. according to the combo's selection).
For starters, you don't need to recreate the GridData for the Text widget every time. Instead, just modify the original via gridData.horizontalSpan, or if in practice you don't have access to the GridData instance, you can get at it via ((GridData) gridData.getLayoutData()).horizontalSpan, etc.
The reason you're seeing the blank space at the bottom of the Shell is because you've created a layout with 3 columns, and then added the following:
The Combo
The Text (with horizontalSpan set to 2, so this uses 2 columns)
The Button
The Combo and the Text take up all 3 columns, so a new row is added for the Button. Then you call pack(), and the preferred size is calculated, which will be for 2 rows, and the first row only sized for 2 widgets.
Instead of calling pack() and shrinking the size of the Shell down to the preferred size, we can just set a size on the Shell via Shell.setSize(...). In general you don't want to mix setSize(...) and layouts, but you've tagged your post with "RCP", so your Shell will already have a size and you won't be manually calling pack() and open().
Full example:
public static void main(String[] args) {
Display display = new Display();
final Shell shell = new Shell(display);
shell.setSize(300, 80);
shell.setText("StackOverflow");
shell.setLayout(new GridLayout(1, true));
Composite composite = new Composite(shell, SWT.NONE);
composite.setLayout(new GridLayout(3, false));
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
final Combo combo = new Combo(composite, SWT.READ_ONLY);
String[] input = {"Execution Times", "Execute with File"};
combo.setItems(input);
final Text loopText = new Text(composite, SWT.SINGLE | SWT.BORDER);
final GridData textGridData = new GridData(SWT.FILL, SWT.FILL, true, false);
textGridData.horizontalSpan = 2;
loopText.setLayoutData(textGridData);
loopText.setEnabled(false);
final Button browseButton = new Button(composite, SWT.PUSH);
browseButton.setText("Browse...");
browseButton.setVisible(false);
combo.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
String text2 = combo.getText();
System.out.println(text2);
if (text2.equals("Execution Times")) {
loopText.setEnabled(true);
loopText.setText("1");
// Can also do ((GridData) textGridData.getLayoutData())...
textGridData.grabExcessHorizontalSpace = true;
textGridData.horizontalSpan = 2;
browseButton.setVisible(false);
loopText.getParent().layout();
}
if (text2.equals("Execute with File")) {
loopText.setEnabled(false);
loopText.setText("");
textGridData.grabExcessHorizontalSpace = true;
textGridData.horizontalSpan = 1;
browseButton.setVisible(true);
browseButton.setFocus();
loopText.getParent().layout();
}
}
});
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
Alternatively, if you are actually creating and opening a new Shell, then call pack() (to get the preferred size) prior to making the Text widget take up two columns:
shell.pack();
// Move these two lines down to the end
textGridData.horizontalSpan = 2;
browseButton.setVisible(false);
shell.layout(true, true);
shell.open();
What we've done is add all 3 widgets without adjusting the horizontalSpan. Then, call pack() to set the size of the Shell assuming that all 3 widgets appear in a single row. After calling pack(), set the horizontalSpan to 2, and hide the Button. When the Shell is opened, you will see:

How to make ExpandItem fill all available vertical space?

This is the full working code:
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setSize(400, 300);
shell.setLayout(new GridLayout());
ExpandBar expandBar = new ExpandBar(shell, SWT.V_SCROLL);
expandBar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
for (int i = 0; i < 3; i++) {
Group group = new Group(expandBar, SWT.NONE);
GridData layoutData = new GridData(GridData.FILL_BOTH);
layoutData.minimumHeight = 225;
layoutData.minimumWidth = 225;
layoutData.grabExcessVerticalSpace = true;
group.setLayoutData(layoutData);
group.setLayout(new GridLayout());
new Label(group, SWT.NONE).setText("Text " + i);
ExpandItem expandItem = new ExpandItem(expandBar, SWT.NONE);
expandItem.setControl(group);
expandItem.setText("Group " + i);
expandItem.setHeight(group.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
expandItem.setExpanded(true);
}
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
If you run this program and try to resize the window, ExpandItems will be resized horizontally, but not vertically:
(Note the empty space at the bottom).
How to make them be resized vertically too?
The problem lies in this line:
expandItem.setHeight(group.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
Computed sized will be based on controls within a group + related layout information, like margins. So, since your group contains only one label, computed size height cannot be more then the size of the label. Even if you add more controls if will always compute the size to fit all the controls without adding any extra space.
What you could is could provide a height hint to computeSize method. Something like this:
expandItem.setHeight(group.computeSize(SWT.DEFAULT, 500).y);
Otherwise there is no way for SWT to understand how big you want your expand items to be.

objects cannot be dragged - with dnd gwt query

I created the follow grid of label that i want thme to be draggable:
public static Grid setLabels (String [] str){
Label [] lbl = new Label [str.length];
Grid grid = new Grid(5,1);
CellFormatter cellFormatter = grid.getCellFormatter();
for(int i=0; i<str.length; i++){
lbl[i] = new Label();
lbl[i].setText(str[i]);
DraggableWidget<Label> draggableLabel = new DraggableWidget<Label>(lbl[i]);
draggableLabel.setRevert(RevertOption.ON_INVALID_DROP);
draggableLabel.setDraggingZIndex(100);
draggableLabel.setDraggingCursor(Cursor.MOVE);
grid.setWidget(i, 0, draggableLabel);
cellFormatter.setHeight(i, 0, "50px");
}
return grid;
}
Then the grid is added on a Panel. Everything is displayed ok.
Then I create a dropable widget.
public static void createDND(){
final Label moveHere = new Label("Move here!");
DroppableWidget<Label> dnd1 = new DroppableWidget<Label>(moveHere);
dnd1.addDropHandler(new DropEventHandler() {
public void onDrop(DropEvent event) {
Widget droppedLabel= event.getDraggableWidget();
moveHere.setText("");
}
});
dndPanel1.add(dnd1);
}
But the labels cannot be dragged and dropped. I feel sth is missing but I can't figure out what.
I would say go NATIVE and make use of GWT HTML5 Drag and Drop support. You also have a sample project set up in GWT source code samples.
Demo - http://gwt-cloudtasks.appspot.com/
Also Refer - Drag and Drop in GWT 2.4

how to pop up calendar when button is clicked in Java SWT?

I am trying to develop Java SWT application in eclipse.
I need to populate text box using DateTime Calendar in SWT when a button is clicked.
I tried the following code but not able to see the Calendar, though it is created.
Any help would be appreciated.
Thanks
public void createPartControl(final Composite parent) {
Button button;
Label label;
final Display dev = parent.getDisplay();
Image image = new Image(dev,"C:\\Users\\rm186021\\Desktop\\Calendar.gif");
GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 3;
parent.setLayout(gridLayout);
label = new Label(parent, SWT.NULL);
label.setText("Start date ");
final Text start = new Text(parent, SWT.SINGLE | SWT.BORDER);
Button calButton = new Button(parent, SWT.PUSH);
calButton.setImage(image);
calButton.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
final Display display = new Display();
final Shell shell2 = new Shell(display);
shell2.addListener(SWT.CALENDAR, new Listener() {
public void handleEvent(Event event) {
final DateTime calendar = new DateTime(shell2,SWT.CALENDAR | SWT.POP_UP);
calendar.addSelectionListener (new SelectionAdapter () {
public void widgetSelected (SelectionEvent e) {
start.setData(" " + calendar.getYear() + "-" + (calendar.getMonth() + 1) + "-" + calendar.getDay());
System.out.println(start.getData());
//calendar.dispose();
}
});
}
});
}
});
You're creating a Shell, but never even opening it. Try calling shell2.open().
You're adding an SWT.CALENDAR listener to the Shell. This isn't going to do what you want to do. Or anything, for that matter, since Shell doesn't fire SWT.CALENDAR events. Instead, you simply need to add the DateTime to a container and hook up selection listeners to the Calendar.
SWT.POP_UP is not an appropriate style bit for Calendar.
I would recommend subclassing Dialog (call it CalendarDialog, for example), setting a FillLayout on it, adding a Calendar to it and hooking up listeners that way. Then call CalendarDialog.open().
The DateTime really shouldn't be created with code like that :) Try this instead:
calButton.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
final Shell shell2 = new Shell(dev.getActiveShell());
// new Display() won't work on many platforms if one already exists
final DateTime calendar = new DateTime(shell2, SWT.CALENDAR);
// no need to add a listener to shell2, and POP_UP doesn't work for DateTime
calendar.addSelectionListener(...);
shell2.open();
// Edward Thomson noticed it wasn't called, I missed it
}
};