How to bind SWT objects to the center of the application window? - swt

I am using SWT to create an application GUI, and I don't really need to resize the components, but it does bother me that when the window is maximized, the components stay left-aligned. Is there a way to fix this with SWT or do I need to utilize a different set of GUI tools?
Thanks in advance. I am using SWT 4.8 for this application.
EDIT: Images
Small: https://imgur.com/CPbAlaZ
Maximized: https://imgur.com/4d6YXcl
Provided images are a basic application using the following code
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
public class TestWindow {
protected Shell shlSwtApplicationExample;
private Text text;
/**
* Launch the application.
* #param args
*/
public static void main(String[] args) {
try {
TestWindow window = new TestWindow();
window.open();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Open the window.
*/
public void open() {
Display display = Display.getDefault();
createContents();
shlSwtApplicationExample.open();
shlSwtApplicationExample.layout();
while (!shlSwtApplicationExample.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
/**
* Create contents of the window.
*/
protected void createContents() {
shlSwtApplicationExample = new Shell();
shlSwtApplicationExample.setSize(705, 529);
shlSwtApplicationExample.setText("SWT Application Example");
Composite composite = new Composite(shlSwtApplicationExample, SWT.NONE);
composite.setBounds(10, 10, 669, 465);
text = new Text(composite, SWT.BORDER);
text.setBounds(22, 10, 334, 295);
Button btnNewButton = new Button(composite, SWT.NONE);
btnNewButton.setBounds(49, 384, 137, 26);
btnNewButton.setText("New Button");
Button button = new Button(composite, SWT.NONE);
button.setText("New Button");
button.setBounds(300, 384, 137, 26);
}
}

I would not recommend using setBounds since it does not resize the components when you resize the application. Use Layouts, like for example below I have used GridLayout for both the Shell and the Composite which will properly arrange the UI when resize happens.
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
public class TestWindow {
protected Shell shlSwtApplicationExample;
private Text text;
/**
* Launch the application.
* #param args
*/
public static void main(String[] args) {
try {
TestWindow window = new TestWindow();
window.open();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Open the window.
*/
public void open() {
Display display = Display.getDefault();
createContents(display);
shlSwtApplicationExample.open();
shlSwtApplicationExample.layout();
shlSwtApplicationExample.setLayout(new GridLayout(1, false));
while (!shlSwtApplicationExample.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
/**
* Create contents of the window.
* #param display
*/
protected void createContents(Display display) {
shlSwtApplicationExample = new Shell(display);
shlSwtApplicationExample.setLayout(new GridLayout(1, false));
Composite txtcomposite = new Composite(shlSwtApplicationExample, SWT.NONE);
txtcomposite.setLayout(new GridLayout(1, false));
txtcomposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
Composite btncomposite = new Composite(shlSwtApplicationExample, SWT.NONE);
btncomposite.setLayout(new GridLayout(2, false));
btncomposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
text = new Text(txtcomposite, SWT.BORDER);
text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
Button btnNewButton = new Button(btncomposite, SWT.NONE);
btnNewButton.setText("New Button");
Button button = new Button(btncomposite, SWT.NONE);
button.setText("New Button");
shlSwtApplicationExample.setText("SWT Application Example");
//shlSwtApplicationExample.setSize(705, 529);
}
}

Since you are using setBounds you will need to add a Control listener to the shell to be told about resize and move events. You will then have to recalculate the positions on each resize event.
shlSwtApplicationExample.addControlListener(
new ControlListener() {
#Override
public void controlMoved(ControlEvent event) {
// No action
}
#Override
public void controlResized(ControlEvent event) {
Rectangle rect = shlSwtApplicationExample.getClientArea();
// TODO Call new `setBounds` on each control based on the
// client area size
}
});
This might be a good time to learn about using Layouts instead of setBounds (see here). Layouts will automatically deal with resizes.

Related

programmatically scroll ScrolledComposite TableViewer item

I have a dialog with large table viewer that lays on ScrolledComposite.
I need programmatically scroll ScrolledComposite to select item from TableViewer.
Looks like a easy task but I really got stack.
I tried number of thinks and non of them are working.
There is my sample code:
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TableItem;
/**
* Scroll a Viewer 99th element
*
*/
public class Snippet008RevealElement {
public class MyModel {
public int counter;
public MyModel(int counter) {
this.counter = counter;
}
#Override
public String toString() {
return "Item " + this.counter;
}
}
public Snippet008RevealElement(Shell shell) {
ScrolledComposite scrolledComposite = new ScrolledComposite(shell, SWT.V_SCROLL | SWT.H_SCROLL);
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
scrolledComposite.setLayoutData(data);
scrolledComposite.setExpandHorizontal(true);
scrolledComposite.setExpandVertical(true);
Composite main = new Composite(scrolledComposite, SWT.NONE);
main.setLayout(new GridLayout());
main.setLayoutData(new GridData(GridData.FILL_BOTH));
final TableViewer v = new TableViewer(main);
v.setLabelProvider(new LabelProvider());
v.setContentProvider(ArrayContentProvider.getInstance());
MyModel[] model = createModel();
v.setInput(model);
v.getTable().setLinesVisible(true);
// v.reveal(model[99]);
// v.getTable().setSelection(99);
TableItem[] items = v.getTable().getItems();
TableItem item = items[99];
scrolledComposite.getVerticalBar().setSelection(item.getBounds().y);
scrolledComposite.setContent(main);
scrolledComposite.setMinSize(main.computeSize(SWT.DEFAULT, SWT.DEFAULT));
}
private MyModel[] createModel() {
MyModel[] elements = new MyModel[100];
for( int i = 0; i < 100; i++ ) {
elements[i] = new MyModel(i);
}
return elements;
}
/**
* #param args
*/
public static void main(String[] args) {
Display display = new Display ();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
new Snippet008RevealElement(shell);
shell.open ();
while (!shell.isDisposed ()) {
if (!display.readAndDispatch ()) display.sleep ();
}
display.dispose ();
}
}
the real challenge or a bug is to find real bounds for TableItem item = items[99]; that not visible on composite.
You can use the setOrigin method of ScrolledComposite for this using something like:
scrolledComposite.setContent(main);
scrolledComposite.setMinSize(main.computeSize(SWT.DEFAULT, SWT.DEFAULT));
// Need to run the calculations after all size calculations have been done
// So do asynchronously.
final Display display = scrolledComposite.getDisplay();
display.asyncExec(() ->
{
final Table table = v.getTable();
final TableItem item = table.getItem(99);
Rectangle itemBounds = item.getBounds();
// Convert to be relative to scrolled composite
itemBounds = display.map(viewer.getTable(), scrolledComposite, itemBounds);
scrolledComposite.setOrigin(0, itemBounds.y);
});
Note: The bounds calculations are not accurate if you call this code during the initialization of the controls so I have shown it being done asynchronously here. The asyncExec is not needed if you run the code from a Button or something like that.

JScrollPane in Eclipse by using palette

I am trying to make a JFrame scrollable by using Palette. In Netbeans if I make a panel with dimensions (300, 500) and a ScrollPane with dimensions (200,200) then if I drag and drop the panel into the ScrollPane it creates automatically the bars.
In eclipse I tried it with the same way and I cannot make it. Moreover the final code in eclipse after the attempt is the following:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JScrollPane;
public class InsertWaterRawData extends JFrame {
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
InsertWaterRawData frame = new InsertWaterRawData();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public InsertWaterRawData() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 577, 383);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(236, 87, 200, 200);
contentPane.add(scrollPane);
JPanel panel = new JPanel();
scrollPane.setViewportView(panel);
panel.setLayout(null);
}
}
Is there any way to make it with the palette ??
Thanks in advance
panel.setLayout(null);
Don't use a null layout!!!
The scrollbars will appear automatically when the preferred size of the panel is greater than the size of the scrollpane.
When you use a layout manager the preferred size of the panel will be calculated automatically as you add components to the panel.
If you are doing custom painting on your panel, then you need to override the getPreferredSize() method of your panel to return an appropriate size.
Based on the code you posted there is no need for scrollbars because no components have been added to the panel.

CoolBar (java SWT WindowBuilder) Composite doesn't appear in Application

I have a problem when I try to use a coolBar in a composite and then I embed this composite in an application. The coolBar simply doesn't appear. This problem doesn't occours with another tools, like toolBar and other composites. What can I doing wrong or forgetting?
Before following the code, I refer my system:
Win7
Eclipse:Version: Indigo Service Release 2 Build id: 20120216-1857
Google WindowBuilder 1.5.0 Google
Plugin 3.1.0
SWT Designer 1.5.0
Google Web Toolkit 2.4.0
Composite code:
package xx.xxx.xx.pcommJavaGUI.composites;
import org.eclipse.swt.widgets.Composite;
public class TestComposite extends Composite {
public TestComposite(Composite parent, int style) {
super(parent, style);
setLayout(new GridLayout(1, false));
CoolBar coolBar = new CoolBar(this, SWT.FLAT);
CoolItem coolItem = new CoolItem(coolBar, SWT.NONE);
Button btnTest = new Button(coolBar, SWT.NONE);
coolItem.setControl(btnTest);
btnTest.setText("Test");
Tree tree = new Tree(this, SWT.BORDER);
tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
}
#Override
protected void checkSubclass() {
// Disable the check that prevents subclassing of SWT components
}
}
And the application Window code:
package xx.xxx.xx.pcommJavaGUI.composites;
import org.eclipse.swt.SWT;
public class TestApplication {
protected Shell shell;
public static void main(String[] args) {
try {
TestApplication window = new TestApplication();
window.open();
} catch (Exception e) {
e.printStackTrace();
}
}
public void open() {
Display display = Display.getDefault();
createContents();
shell.open();
shell.layout();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
protected void createContents() {
shell = new Shell();
shell.setSize(450, 300);
shell.setText("SWT Application");
shell.setLayout(new GridLayout(1, false));
TestComposite tc = new TestComposite(shell, SWT.NONE);
GridData gd_tc = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1);
tc.setLayoutData(gd_tc);
}
}
Thanks for helping.
You have to set the size of CoolItem manually.
First of all pack(); your Button to set it to it's default size.
Afterwards set the size of the CoolItem to the size of the Button.
The Button:
Button btnTest = new Button(coolBar, SWT.NONE);
coolItem.setControl(btnTest);
btnTest.setText("Test");
// If you do not call this, btnTest.getSize() will give you x=0,y=0.
btnTest.pack();
Set the size of CoolItem:
Point size = btnTest.getSize();
coolItem.setControl(btnTest);
coolItem.setSize(coolItem.computeSize(size.x, size.y));
Links:
CoolBar Examples
API: Control.pack();
It might be just because you aren't setting layout data for the coolbar. See this article to understand how layouts work.

Eclipse SWT browser and Firebug lite?

Is there a way to use Firebug lite "bookmarklet" feature within eclipse SWT browser?
Depends on the system browser which your SWT browser is using. For Win7 and IE8, you can have something like this:
Output
Code
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class FirebugLite
{
public static void main(String[] args) {
new FirebugLite().start();
}
public void start()
{
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new GridLayout(1, false));
GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
gridData.widthHint = SWT.DEFAULT;
gridData.heightHint = SWT.DEFAULT;
shell.setLayoutData(gridData);
shell.setText("Firebug Lite for SWT ;)");
final Browser browser = new Browser(shell, SWT.NONE);
GridData gridData2 = new GridData(SWT.FILL, SWT.FILL, true, true);
gridData2.widthHint = SWT.DEFAULT;
gridData2.heightHint = SWT.DEFAULT;
browser.setLayoutData(gridData2);
Button button = new Button(shell, SWT.PUSH);
button.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
button.setText("Install");
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
browser.setUrl("javascript:(function(F,i,r,e,b,u,g,L,I,T,E){if(F.getElementById(b))return;E=F[i+'NS']&&F.documentElement.namespaceURI;E=E?F[i+'NS'](E,'script'):F[i]('script');E[r]('id',b);E[r]('src',I+g+T);E[r](b,u);(F[e]('head')[0]||F[e]('body')[0]).appendChild(E);E=new%20Image;E[r]('src',I+L);})(document,'createElement','setAttribute','getElementsByTagName','FirebugLite','4','firebug-lite.js','releases/lite/latest/skin/xp/sprite.png','https://getfirebug.com/','#startOpened');");
}
});
browser.setUrl("http://stackoverflow.com/questions/12003602/eclipse-swt-browser-and-firebug-lite");
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
Note >> I have used the setUrl() API. You can try the execute() but I am not sure whether it would work.
I can not run on Linux. The exception web page appeared: 'URL cannot be shown'.
I tweaked Favonius's solution a bit. In my case we wanted to see inside iframes. I modified the setUrl to load firebug inside the last iframe. In my case it did what we wanted.
browser.setUrl("javascript: function lastIframeDocument(curr){while(curr.getElementsByTagName('iframe')[0]!=null){curr=curr.getElementsByTagName('iframe')[0].contentWindow.document;}return curr;}(function(F,i,r,e,b,u,g,L,I,T,E){if(F.getElementById(b))return;E=F[i+'NS']&&F.documentElement.namespaceURI;E=E?F[i+'NS'](E,'script'):F[i]('script');E[r]('id',b);E[r]('src',I+g+T);E[r](b,u);(F[e]('head')[0]||F[e]('body')[0]).appendChild(E);E=new%20Image;E[r]('src',I+L);})(lastIframeDocument(document),'createElement','setAttribute','getElementsByTagName','FirebugLite','4','firebug-lite.js','releases/lite/latest/skin/xp/sprite.png','https://getfirebug.com/','#startOpened');");

ExpandBar in Eclipse View Part

I am trying to add an expand bar to an Eclipse viewpart. When I click the expand button I would like the viewpart to move items below the expand bar down and show the expanded items. What currently happens is the expand bar items just disappear below the items below the expand bar. Any thoughts?
final ExpandBar expandBar = new ExpandBar(parent, SWT.NONE);
expandBar.setBackground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_LIGHT_SHADOW));
expandBar.setSpacing(0);
fd_toolBar.top = new FormAttachment(expandBar, 6);
FormData fd_expandBar = new FormData();
fd_expandBar.top = new FormAttachment(0, 62);
fd_expandBar.left = new FormAttachment(0, 3);
expandBar.setLayoutData(fd_expandBar);
formToolkit.paintBordersFor(expandBar);
final ExpandItem xpndtmWarningDetails = new ExpandItem(expandBar, SWT.NONE);
xpndtmWarningDetails.setExpanded(true);
xpndtmWarningDetails.setText("Warning Details");
final Composite composite_1 = new Composite(expandBar, SWT.NONE);
composite_1.setBackground(SWTResourceManager.getColor(SWT.COLOR_YELLOW));
xpndtmWarningDetails.setControl(composite_1);
formToolkit.paintBordersFor(composite_1);
xpndtmWarningDetails.setHeight(xpndtmWarningDetails.getControl().computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
Label lblTest = new Label(composite_1, SWT.NONE);
lblTest.setBounds(10, 10, 55, 15);
lblTest.setText("Test");
expandBar.addExpandListener(new ExpandListener(){
#Override
public void itemCollapsed(ExpandEvent e) {
expandBar.setSize(expandBar.getSize().x, xpndtmWarningDetails.getHeaderHeight());
parent.layout(true);
}
#Override
public void itemExpanded(ExpandEvent e) {
expandBar.setSize(expandBar.getSize().x, 300);
expandBar.layout(true);
parent.layout(true);
}
});
I think the ExpandBar works best when used like it is in this example...
http://git.eclipse.org/c/platform/eclipse.platform.swt.git/tree/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet343.java
... with several expand bars stacked on top of each other, and nothing else mixed in.
I think the functionality your looking for can be accomplished with an ExpandableComposite object. It depends on what else is going on in your ViewPart.
Here's a quick example of an ExpandableComposite.
package com.amx.designsuite.rcp;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.forms.widgets.TableWrapLayout;
public class ExpandableCompositeExample extends Composite {
/**
* Create the composite.
* #param parent
* #param style
*/
public ExpandableCompositeExample(final Composite parent, int style) {
super(parent, style);
FormToolkit toolkit;
toolkit = new FormToolkit(parent.getDisplay());
final ScrolledForm form = toolkit.createScrolledForm(parent);
form.setText("Title for Form holding Expandable Composite (optional)");
TableWrapLayout layout = new TableWrapLayout();
form.getBody().setLayout(layout);
ExpandableComposite expandableCompsite = toolkit.createExpandableComposite(form.getBody(), ExpandableComposite.TREE_NODE | ExpandableComposite.SHORT_TITLE_BAR);
toolkit.paintBordersFor(expandableCompsite);
expandableCompsite.setText("Expandable Composite Title (Optional)");
expandableCompsite.setExpanded(true);
Text txtMyNewText = toolkit.createText(expandableCompsite, "Text to show when composite is expanded", SWT.NONE);
expandableCompsite.setClient(txtMyNewText);
}
#Override
protected void checkSubclass() {
// Disable the check that prevents subclassing of SWT components
}
}