JFace dialog stays open after pressing the OK button - java

I am working with SWT JFace dialog.
I added a listener to the OK button, I want to display a message box once the user clicks on the OK button.
The problem in this step is that when I once click on the OK button the shell gets disposed. How I can prevent this behavior?

The following code will prevent the dialog from beeing closed via the "OK" button. Just don't call this.close() in the okPressed() method:
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
new OptionsDialog(shell).open();
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
private static class OptionsDialog extends Dialog {
private Composite composite;
public OptionsDialog(Shell parentShell)
{
super(parentShell);
setShellStyle(parentShell.getStyle() | SWT.CLOSE | SWT.TITLE | SWT.BORDER | SWT.APPLICATION_MODAL);
setBlockOnOpen(true);
}
protected Control createDialogArea(Composite parent) {
this.composite = (Composite) super.createDialogArea(parent);
GridLayout layout = new GridLayout(1, false);
layout.marginHeight = 5;
layout.marginWidth = 10;
composite.setLayout(layout);
createContent();
return composite;
}
private void createContent()
{
/* add your widgets */
}
protected void configureShell(Shell newShell)
{
super.configureShell(newShell);
newShell.setText("Shell name");
}
public void okPressed()
{
/* DO NOTHING HERE!!! */
//this.close();
}
}

Related

How to reopen a dialog programatically

I have a JFace dialog and a toggle button( whose text is either "freeze" or "unfreeze") in the button bar.
Initially i select an object and click on a menu item to open the dialog.
From then on, whenever I click on toggle button(when text on it is "unfreeze") the dialog should close and reopen.
How do i achieve this ?
This should give you an idea how to do it (quick hack):
private static MyDialog dialog;
public static void main(String[] args)
{
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
final Button openDialog = new Button(shell, SWT.TOGGLE);
openDialog.setText("Toggle dialog");
openDialog.addListener(SWT.Selection, new Listener()
{
#Override
public void handleEvent(Event arg0)
{
if (openDialog.getSelection())
{
if (dialog == null)
{
dialog = new MyDialog(new Shell(display));
dialog.open();
}
if(dialog.getShell() != null && !dialog.getShell().isDisposed())
dialog.getShell().setVisible(openDialog.getSelection());
}
else
{
if (dialog != null && dialog.getShell() != null && !dialog.getShell().isDisposed())
dialog.getShell().setVisible(openDialog.getSelection());
}
}
});
shell.open();
shell.pack();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
{
display.sleep();
}
}
display.dispose();
}
private static class MyDialog extends Dialog
{
public MyDialog(Shell parentShell)
{
super(parentShell);
setShellStyle(SWT.CLOSE | SWT.MODELESS | SWT.BORDER | SWT.TITLE);
}
#Override
protected Control createDialogArea(Composite parent)
{
Composite container = (Composite) super.createDialogArea(parent);
Text text = new Text(container, SWT.BORDER);
return container;
}
#Override
protected void configureShell(Shell newShell)
{
super.configureShell(newShell);
newShell.setText("Some dialog");
}
#Override
protected Point getInitialSize()
{
return new Point(450, 300);
}
}
It will create and open the dialog on first press of the button and hide/unhide in on consequent press events (using Shell#setVisible(boolean)).
If this is not what you had in mind, please update your question or post a comment.

Java SWT List - make it unselectable

I wish to use org.eclipse.swt.widgets.List just to present some data. User should not be allowed to select any item.
I could just:
List list = new List(this, SWT.V_SCROLL);
list.setEnabled(false);
But then I will loose scrolling feature. How can I just make list items unselectable?
Another alternative is to use a Table instead of List and disable selection painting like this:
table.addListener(SWT.EraseItem, new Listener() {
#Override
public void handleEvent(Event event) {
event.detail &= ~SWT.SELECTED;
event.detail &= ~SWT.HOT;
}
});
You could try to clear selection each time user selects an item. The selection will be visible for a short time interval, though.
list.addListener(SWT.Selection, new Listener() {
#Override
public void handleEvent(Event event) {
list.setSelection(new String[0]);
}
});
If you don't like my other answer with clearing selection, you could try to keep the list disabled, but inside a ScrolledComposite. It will look disabled, but scrolling will work. Here is a snippet:
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
final ScrolledComposite scrolledComposite = new ScrolledComposite(shell, SWT.H_SCROLL | SWT.V_SCROLL);
scrolledComposite.setExpandHorizontal(true);
scrolledComposite.setExpandVertical(true);
scrolledComposite.setBackground(display.getSystemColor(SWT.COLOR_CYAN));
final List list = new List(scrolledComposite, SWT.NONE);
list.setEnabled(false);
scrolledComposite.setContent(list);
scrolledComposite.addListener(SWT.Resize, new Listener() {
#Override
public void handleEvent(Event event) {
final Point size = list.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
scrolledComposite.setMinSize(size);
}
});
for (int i = 0; i < 1000; i++) {
list.add(Integer.toString(i));
}
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
Arrow keys and page up/down down do not work, so you will have to register key listeners and implement scrolling with keyboard.

SWT Popup Composite unexpected disposal

So I've stolen this cool PopupComposite, and I am really satisfied with it.
There's just one issue. If it put a org.eclipse.swt.widgets.Text in it, I open the popup, focus the Text, and press ESC, then both the Text and the PopupComposite dispose themselves.
I really can't figure out where the dispose call is coming from. Is it a Shell issue? What Shell should I use with the popup?
SSCCE:
/**
*
* #author ggrec
*
*/
public class PopupCompositeTester
{
public static void main(final String[] args)
{
new PopupCompositeTester();
}
private PopupCompositeTester()
{
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new GridLayout(1, false));
createContents(shell);
shell.pack();
shell.open();
while (!shell.isDisposed())
{
if ( !display.readAndDispatch() )
display.sleep();
}
display.dispose();
}
private static void createContents(final Composite parent)
{
final Button button = new Button(parent, SWT.PUSH);
button.setText("Poke Me");
final PopupComposite popup = new PopupComposite(parent.getShell());
new Text(popup, SWT.NONE);
popup.pack();
button.addSelectionListener(new SelectionAdapter()
{
#Override public void widgetSelected(final SelectionEvent e)
{
popup.show( Display.getDefault().map(parent, null, button.getLocation()) );
}
});
}
}
The reason for this is because when you focus the text field and press Escape, the field sends a SWT.TRAVERSE_ESCAPE event to its parent shell. The shell (in your case not being a top-level shell) responds by calling Shell.close(). You can work around that by adding a traverse listener to your text field, which would cancel the event (code below).
new Text(popup, SWT.NONE).addTraverseListener(new TraverseListener() {
#Override
public void keyTraversed(TraverseEvent e) {
if(e.detail == SWT.TRAVERSE_ESCAPE) {
e.doit = false;
}
}
});
Keep in mind, this is a rather crude solution to your specific issue. I would not recommend using this for anything other than testing purposes. You can read more about this here -> http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fswt%2Fevents%2FTraverseEvent.html
And here: http://help.eclipse.org/helios/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fswt%2Fwidgets%2FShell.html
Because my "bug" is actually a normal behaviour of the SWT platform, I've used the following workaround:
/**
* Lazy initialization of the popup composite
*/
private void createPopup()
{
// popupContainer is now a field
if (popupContainer != null && !popupContainer.isDisposed())
return;
// ... create popup AND its contents ...
}
and in the button listener:
createPopup();
popup.show( Display.getDefault().map(parent, null, button.getLocation()) );
Thank you #blgt

SWT - Inheriting parent dialog shell?

I am really needing to understand how parent/child dialogs work.
My users use a OTB Application called Teamcenter. I am writing a add on application that is invoked from a menu selection in the Teamcenter Application.
When they click the menu item, that executes a handler class and that creates the base dialog for my application.
public class AplotDialogHandler extends AbstractHandler {
private static AplotBaseDialog dlg = null;
public AplotDialogHandler() {
}// end Constructor
//////////////////////////////////////////////////////////////////////////
// execute() //
//////////////////////////////////////////////////////////////////////////
#Override
public Object execute(final ExecutionEvent event) throws ExecutionException {
if (dlg == null) {
try {
AbstractAIFApplication app = AIFDesktop.getActiveDesktop().getCurrentApplication();
TCSession session = (TCSession) app.getSession();
TCUserService userService = session.getUserService();
AplotVersion.negotiateVersion(userService);
AplotQueryCapabilities.initialize(userService);
dlg = new AplotBaseDialog(null, session);
}
catch (Exception ex) {
MessageBox.post(HandlerUtil.getActiveWorkbenchWindowChecked(event).getShell(), ex, true);
}
}
dlg.create();
dlg.getShell().setSize(700, 400);
dlg.open();
return null;
}// end execute()
}// end EdiDialogHandler()
Question 1. It seems like my application is not tied to the Teamcenter application. Meaning that I can close Teamcenter and my Application stays open.
Question 2. Should I get the workspace shell and pass it in the base dialog?
But even when my application is open, the user still needs to be able to use the Teamcenter application to select data to send to my application
Question 3. When opening dialogs from my base dialog, should I always pass the base dialog shell to those dialogs?
Question 4. Is there a standard way I should close down the dialogs when the user is done?
You need to pass the parent Shell to the dialog so that when you close parent shell, child shells will also be closed.
You should make your dialog MODELESS ( use SWT.MODELSS as style. Note: it is Hint) so that it will not block your parent shell.
Here is sample code:
public static void main(String[] args) {
Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new GridLayout(1, false));
shell.setSize(200, 200);
Button b = new Button(shell, SWT.NONE);
b.setText("Click");
b.addSelectionListener(new SelectionListener() {
#Override
public void widgetSelected(SelectionEvent e) {
CDialog dialog = new CDialog(shell);
dialog.open();
}
#Override
public void widgetDefaultSelected(SelectionEvent e) {
// TODO Auto-generated method stub
}
});
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
private static class CDialog extends Dialog
{
/**
* #param parentShell
*/
protected CDialog(Shell parentShell) {
super(parentShell);
}
/* (non-Javadoc)
* #see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
*/
#Override
protected Control createDialogArea(Composite parent) {
Composite comp = (Composite) super.createDialogArea(parent);
Label lbl = new Label(comp, SWT.NONE);
lbl.setText("Test modeless dialog");
return comp;
}
/* (non-Javadoc)
* #see org.eclipse.jface.window.Window#getShellStyle()
*/
#Override
protected int getShellStyle() {
return SWT.DIALOG_TRIM|SWT.MODELESS;
}
}

SWT/JFace: remove widgets

Group group = new Group(parent, SWT.NONE);
StyledText comment = new StyledText(group, SWT.BORDER_DASH);
This creates a group with a text area inside.
How can I later delete the text (remove it from the screen so that I can replace it with something else)?
Use Widget.dispose.
public class DisposeDemo {
private static void addControls(final Shell shell) {
shell.setLayout(new GridLayout());
Button button = new Button(shell, SWT.PUSH);
button.setText("Click to remove all controls from shell");
button.addSelectionListener(new SelectionListener() {
#Override public void widgetDefaultSelected(SelectionEvent event) {}
#Override public void widgetSelected(SelectionEvent event) {
for (Control kid : shell.getChildren()) {
kid.dispose();
}
}
});
for (int i = 0; i < 5; i++) {
Label label = new Label(shell, SWT.NONE);
label.setText("Hello, World!");
}
shell.pack();
}
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
addControls(shell);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
}
Another option is to use a StackLayout to switch between underlying controls. This prevents you from running into a "widget is disposed" error.
You have to either call comment.changeParent(newParent) or comment.setVisible(false) to remove/hide it from the Group. I am unsure if comment.changeParent(null) would work but I would give that a try.
We do it this way because SWT uses the Composite Pattern.
group.getChildren()[0].dispose() will remove the first child. You need to find a way to identify the precise child you want to delete. It could be comparing the id. You can do that by using the setData / getData on that control:
For example:
StyledText comment = new StyledText(group, SWT.BORDER_DASH);
comment.setData("ID","commentEditBox");
and then:
for (Control ctrl : group.getChildren()) {
if (control.getData("ID").equals("commentEditBox")) {
ctrl.dispose();
break;
}
}

Categories