SWT - Modifying Window Close Button (Red X) - java

When a user closes any of the application windows using the Window Close Button(red X) button. It causes Widget is Disposed issues with my application. When they close the window using the close application I provided. Everything works correctly.
#Override
protected void createButtonsForButtonBar(Composite parent) {
createButton(parent, IDialogConstants.OK_ID, "Close Aplot", true);
}
#Override
protected void okPressed() {
getShell().setVisible(false);
}
Can you catch the press of the Window Close Button(red X) to use the code above?
Can you just disable the Window close Button(red X)?

Listen for SWT.Close on the Shell.
This should help:
public static void main(String[] args)
{
Display display = new Display();
final Shell shell = new Shell(display);
shell.addListener(SWT.Close, new Listener()
{
public void handleEvent(Event event)
{
int style = SWT.APPLICATION_MODAL | SWT.YES | SWT.NO;
MessageBox messageBox = new MessageBox(shell, style);
messageBox.setText("Information");
messageBox.setMessage("Close the shell?");
event.doit = messageBox.open() == SWT.YES;
}
});
shell.pack();
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
It will prompt the user to verify the decision.

In a jface dialog, always it will invoke close() method irrespective of where OK is pressed or CANCEL is pressed or close(red x button) is clicked.
Override close method and check return code ( use getReturnCode() method).

First thing I do is override the close() method in the ApplicationWindow
/** the rc from the message dialog */
int rc = -1;
#Override
public boolean close()
{
MessageDialog messagedialog = new MessageDialog(getShell(),
"Confirm Exit", null, "Are you sure you want to exit?", 4,
new String[]
{ "Yes", "No" }, 1);
messagedialog.setBlockOnOpen(true);
messagedialog.open();
rc = messagedialog.getReturnCode();
/** int to hold the return code from the message dialog */
if (rc == 0)
{
return true;
} else
{
return false;
}
}
The second thing I do is listen for events on the 'X' close button
shell.addListener(SWT.Close, new Listener()
{
#Override
public void handleEvent(Event event)
{
switch (rc)
{
case 0: // yes pressed
event.doit = true;
break;
case 1: // no pressed
event.doit = false;
break;
case -1: // escape pressed
break; // do nothing
default:
break;
}
}
});
The "event.doit" boolean field determines the closure of the shell. If the value is equal to 'true' - "lets doit", lets close the shell (i.e. rc = 0).
If this value is equal to 1 (rc = 1) the shell is left open.
If ESC is pressed (i.e. the rc = -1) we simply do nothing. But we could minimize the shell if this was a requirement or perform some other action based on this event.

Related

Preventing SWT shell from disposing

I created a SWT dialog with this implementation:
public class FindDialog extends Dialog {
private DialogResult result;
private Display display;
private Shell shell;
private Button okayButton;
/*...*/
public FindDialog(Shell parent) {
this(parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
}
public FindDialog(Shell parent, int style) {
super(parent, style);
display = getParent().getDisplay();
initUI();
}
public DialogResult open() {
result = DialogResult.Cancel;
shell.open();
while (shell.isVisible()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
return result;
}
private void initUI() {
shell = new Shell(getParent(), getStyle());
shell.addListener(SWT.Close, new ShellClosingHandler());
okayButton = new Button(shell, SWT.PUSH);
okayButton.addListener(SWT.Selection, new ButtonClickedHandler());
/*...*/
}
private class ButtonClickedHandler implements Listener {
public void handleEvent(Event e) {
Button button = (Button)e.widget;
if (button == okayButton) {
result = DialogResult.OK;
shell.close();
}
}
}
private class ShellClosingHandler implements Listener {
public void handleEvent(Event e) {
if (result == DialogResult.OK) {
e.doit = validate();
}
}
private boolean validate() {
/*...*/
}
}
}
There are some more text fields, buttons and checkboxes but I think that it's not important for my question.
The dialog window popups correctly and I can make my changes on the GUI without any problems.
At last I click the ok button and then the following happens:
The SWT.Close event is firing, my validation method is called and depending on the result the dialog is closed or not. That's ok so far.
But shell.close() not only closes the dialog, it also disposes the shell. And exactly here is the problem because
I don't want to rebuild the dialog GUI everytime the open method is called. I create all my dialogs at program startup and then only want to open and close it if needed.
I need some values of the text fields or states of checkboxes after closing the dialog at different positions in the main program. So it seems a good idea to hold a reference of the dialog object and implement some getters to pull out the data. But if the shell is disposed I have no chance to get the information.
If the shell is disposed then I will loose the "state" of the dialog so I have to refill it next time I display the dialog.
So my question: Is there a possibility to prevent the shell from disposing?
Or is there another concept that I overlooked so I don't have to restructure my complete dialog set?
if (button == okayButton) {
result = DialogResult.OK;
shell.setVisible(false);
}
You can use setVisible(false) instead of close
So it will get hide and wont get dispose.
You can get the values of the text box after hide
No need to rebuild again
The past values in the textbox will be there after hide.

SWT Communicate between Child shell and parent shell takes time

We are using 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.
It will Show Selected Component from Teamcenter on Open dialog .
Dialog has One text field with Button.
User go back to parent window and select item and then click button on dialog this will set selected item on opened dialog.
But When Dialog open and i go back to parent i.e OTB teamcenter application for selecting item it takes time it looks like it got hanged.
Note:
Text Button
List
text and button are adjacent field.
If user select 1200 parts and goto menu and select item then it will show popup and then click on parent window for single item selection,clicking on parent takes time
but if we have 200 parts and then go back and click on parent window it doesn't take much time
Can anyone please suggest how to improve time performance ?
// open( ) : First Call on Menu selection will call open() method
//setSourceBomLinesOnSessionInfo() :Call from Open method() to set Required selected item information in session required to be set on Dialog List component
// SetScope() :Set text data on button selection on opened dialog
// user will go on parent window and select item and then coming back on opened dialog and click button
public void open()
{
eQOTMLoggerManager.logger.debug("open 'OTM Compare' Dialog");
eQOTMSessionInfo.getInstance().clearCurrentSelection();
Shell prevShell = getOTMCompareDialog();
if (prevShell != null)
{
prevShell.setMinimized(false);
}else{
try{
//Set Source BomLine on OTM Dialog Window
bSetInputOnDialog = setSourceBomLinesOnSessionInfo();
if( bSetInputOnDialog )
{
initializeUIComponents();
mainDialogShell.open();
Display display = mainDialogShell.getDisplay();
while (!mainDialogShell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
mainDialogShell.dispose();
}
else if (mainDialogShell != null)
{
mainDialogShell.dispose();
}
eQOTMLoggerManager.logger.error("INFO:Exit initialize UI Components for OTM compare dialog.");
}
catch (Throwable th)
{
eQOTMLoggerManager.logger.error("Exception occurred while initializing UI Components for OTM compare dialog. Error: "+th.getMessage(),th);
}
}
}
//Initialize UI Component
private void initializeUIComponents() throws TCException
{
eQOTMLoggerManager.logger.error("INFO:In initialize UI Components for OTM compare dialog !!!");
mainDialogShell = new Shell(this.m_parentShell, SWT.DIALOG_TRIM |SWT.MODELESS);
mainDialogShell.setText(this.m_sOTMDialogTitle);
mainDialogShell.setLocation(getParent().toDisplay(300, 200));
mainDialogShell.setSize(450, 400);
/* Image dialogicon = new Image(mainDialogShell.getDisplay(),"icon/ecubeIcon.png");
mainDialogShell.setImage(dialogicon);
*/
/*Main grid*/
GridLayout gridLayout = new GridLayout(4, false);
gridLayout.verticalSpacing = 10;
mainDialogShell.setLayout(gridLayout);
//Scope label to display on UI
new Label(mainDialogShell, SWT.NONE|SWT.CENTER).setText("Scope:");
//Text filed for scope
this.m_textScopeName = new Text(mainDialogShell,SWT.READ_ONLY|SWT.SINGLE | SWT.BORDER);
GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
gridData.horizontalSpan = 2;
this.m_textScopeName.setLayoutData(gridData);
//Button to set scope
Button btnsetscope = new Button(mainDialogShell, SWT.PUSH);
btnsetscope.setText("Set Scope");
gridData = new GridData();
gridData.horizontalSpan = 1;
gridData.horizontalAlignment = GridData.END;
btnsetscope.setLayoutData(gridData);
//Label for List of Parts to Compare
new Label(mainDialogShell, SWT.NONE).setText("List of Parts to Compare :");
//Text filed for List of Parts to Compare
m_listKitParts = new Text(mainDialogShell, SWT.MULTI | SWT.BORDER | SWT.H_SCROLL
| SWT.V_SCROLL);
gridData = new GridData(GridData.FILL, GridData.FILL, true, true);
gridData.horizontalSpan = 3;
gridData.grabExcessVerticalSpace = true;
m_listKitParts.setLayoutData(gridData);
final Button btnCompare = new Button(mainDialogShell, SWT.PUSH);
btnCompare.setText("Identify");
gridData = new GridData();
gridData.horizontalSpan = 3;
gridData.horizontalAlignment = GridData.END;
btnCompare.setLayoutData(gridData);
final Button btnCancel = new Button(mainDialogShell, SWT.PUSH);
btnCancel.setText(" Cancel ");
gridData = new GridData();
gridData.horizontalSpan = 1;
gridData.horizontalAlignment = GridData.END;
btnCancel.setLayoutData(gridData);
long start_time = System.nanoTime();
/*
TCComponentBOMLine[] alSelectedSRCBOMLinetemp = eQOTMSessionInfo.getInstance().getCurrentSourceBOMLines();
int componentsize=alSelectedSRCBOMLinetemp.length;
for(int i=0;i<componentsize;i++)
{
m_listKitParts.append(alSelectedSRCBOMLinetemp[i].toString()+"\n");
}
*/
InterfaceAIFComponent selectedcomponent[]=m_sourcepanel.getSelectedComponents();
int componentsize=selectedcomponent.length;
for(int i=0;i<componentsize;i++)
{
m_listKitParts.append(selectedcomponent[i]+"\n");
}
long end_time = System.nanoTime();
double difference = (end_time - start_time)/1e6;
eQOTMLoggerManager.logger.error("INFO:Response return to TC. Total time taken: "+(difference)/1000);
//Set scope Button Listener
btnsetscope.addSelectionListener(new SelectionAdapter()
{
public void widgetSelected(SelectionEvent event)
{
//Set Scope for Compare BOMLine operation
SetScope();
}
});
//Compare Button Listener
btnCompare.addSelectionListener(new SelectionAdapter()
{
public void widgetSelected(SelectionEvent event)
{
if(m_textScopeName.getText().length()<=0)
{
m_textScopeName.setFocus();
MessageBox.post(Messages.eQOTM_ScopeSelection_info,Messages.eQOTM_ScopeSelection_title, 2);
}
else
{
btnCompare.setEnabled(false);
btnCancel.setEnabled(false);
Job serverJob = new Job(eQOTMConstants.Stausmessage)
{
protected IStatus run(IProgressMonitor monitor)
{
eQOTMLoggerManager.logger.error("INFO:Started backgound thread to call MI process\n");
compareBOMLines();
mainDialogShell.getDisplay().syncExec(new Runnable()
{
public void run()
{
mainDialogShell.close();
}
});
return Status.OK_STATUS;
}
};
serverJob.setPriority(Job.SHORT);
serverJob.schedule();
}
}
});
//cancel Button Listener
btnCancel.addSelectionListener(new SelectionAdapter()
{
public void widgetSelected(SelectionEvent e)
{
mainDialogShell.close();
}
});
eQOTMLoggerManager.logger.error("INFO:Exit initialize UI Components for OTM compare dialog.");
}
private boolean setSourceBomLinesOnSessionInfo() throws TCException
{
eQOTMLoggerManager.logger.debug("In setSourceBomLinesOnCompareDialog");
InterfaceComparable sourcePanel = m_currentTcApplication.getActiveComparable();
eQOTMSessionInfo objOTMSession = eQOTMSessionInfo.getInstance();
this.m_sourcepanel=sourcePanel;
TCComponentBOMLine[] arrayOfTargetTCComponentBOMLine = null;
ArrayList<TCComponentBOMLine> arrlcheckedBOMLine = new ArrayList<TCComponentBOMLine>();
if(((BOMTreeTable)sourcePanel.getCompareTreeTable()).getBOMWindow().getTopBOMLine().getDisplayType().toString().equals(eQOTMConstants.IS_MFG_PLAN))
{
if( !SetScope() )//on error return false
return false;
if( !setCheckedBomlines(arrlcheckedBOMLine)){//on error return false
return false;
}
arrayOfTargetTCComponentBOMLine = (TCComponentBOMLine[])arrlcheckedBOMLine.toArray(new TCComponentBOMLine[arrlcheckedBOMLine.size()]);
}else
{
//EBOM Install to -EBOM Install /MBOM kit to EBOM install Comparison
arrayOfTargetTCComponentBOMLine = ((BOMTreeTable)sourcePanel.getCompareTreeTable()).getSelectedBOMLines();
}
if ( arrayOfTargetTCComponentBOMLine == null || arrayOfTargetTCComponentBOMLine.length == 0)
{
MessageBox.post(Messages.eQOTM_KitSelection_info,Messages.eQOTM_KitSelection_title, 2);
return false;
}
objOTMSession.setCurrentSourceBOMLines(arrayOfTargetTCComponentBOMLine);
eQOTMLoggerManager.logger.error("INFO:No. of Bomlines selected for comparison : "+arrayOfTargetTCComponentBOMLine.length);
eQOTMLoggerManager.logger.debug("Exit setSourceBomLinesOnCompareDialog");
return true;
}
private boolean SetScope()
{
InterfaceComparable targetPanel = m_currentTcApplication.getActiveComparable();
eQOTMSessionInfo objOTMSession = eQOTMSessionInfo.getInstance();
objOTMSession.setTargetBOMTreeTable((BOMTreeTable)targetPanel.getCompareTreeTable());
try
{
objOTMSession.addUserSessionVariable(eQOTMConstants.REVISIONRULE,((BOMTreeTable)targetPanel.getCompareTreeTable()).getBOMWindow().getRevisionRule().toString());
}
catch (Exception e)
{
eQOTMLoggerManager.logger.error("Error occurred while getting RevisionRule from TC user session. Error : "+e.getMessage(),e);
MessageBox.post(Messages.eQOTM_ScopeRevisionRule_info,Messages.eQOTM_ScopeSelection_title, 2);
return false;
}
TCComponentBOMLine[] arrayOfScopeTCComponentBOMLine = ((BOMTreeTable)targetPanel.getCompareTreeTable()).getSelectedBOMLines();
if( arrayOfScopeTCComponentBOMLine==null || arrayOfScopeTCComponentBOMLine.length<1 )
{
MessageBox.post(Messages.eQOTM_ScopeSelection_info,Messages.eQOTM_ScopeSelection_title, 2);
return false;
}
TCComponentBOMLine scopebomline = arrayOfScopeTCComponentBOMLine[0];
try
{
if (scopebomline.getChildrenCount() ==0)
{
MessageBox.post(Messages.eQOTM_ScopeNoChild_info,Messages.eQOTM_ScopeSelection_title, 2);
return false;
}
}
catch (TCException localTCException1)
{
eQOTMLoggerManager.logger.error("Exception Occurred while getting child count for scope");
}
this.m_textScopeName.setText(scopebomline.toString());
eQBOMLineBean currentScopeBOMLine = new eQBOMLineBean(scopebomline);
objOTMSession.setCurrentScopeBOMLine(currentScopeBOMLine);
return true;
}

SWT Adding KeyListener to a Display

I want to add a KeyListener to my existing window. I want to catch 3 KeyDown's. On the first KeyDown I want to put something in a Combo. On the second KeyDown I want to put something in another Combo. If both textbox are filled, I want the next KeyDown to simulate the OK Button.
But I have a problem with the error widget disposed. Because I dont know when to remove the filter correct. This only happend if I open the window again!
My Code:
_disp.addFilter(SWT.KeyDown, new Listener() {
public void handleEvent(Event e) {
if(!_disp.isDisposed()){
_disp.removeFilter(SWT.KeyDown, this);
}
if (e.keyCode == SWT.CR) {
if (_cmbCCID.getText().isEmpty()) {
_cmbCCID.setText(_lastFiveCCID[0]);
} else if (_cmbDescription.getText().isEmpty()) {
_cmbDescription.setText(_lastFiveComment[0]);
} else if (!_cmbCCID.getText().isEmpty() && !_cmbDescription.getText().isEmpty()) {
_btnOk.notifyListeners(SWT.Selection, new Event());
}
}
}
});
You're removing the filter after the first key press. Try something like this:
public static void main(String[] args)
{
final Display display = new Display();
Shell shell = new Shell(display);
shell.setText("StackOverflow");
shell.setLayout(new FillLayout());
new Text(shell, SWT.NONE);
display.addFilter(SWT.KeyDown, new Listener()
{
int i = 0;
#Override
public void handleEvent(Event arg0)
{
if (i < 2)
System.out.println("Press " + i);
else
{
System.out.println("Press " + i);
System.out.println("Remove");
if (!display.isDisposed())
display.removeFilter(SWT.KeyDown, this);
}
i++;
}
});
shell.pack();
shell.open();
while (!shell.isDisposed())
{
while (!display.readAndDispatch())
{
display.sleep();
}
}
}
It will remove the filter after the third key press event.

How to combine and validate two text fields for a swt dialog?

i have another question. I use a ModifyListener for one textfield to activate and deactivate the OK-Button in a swt dialog. It works great.
Now I want to add a ModifyListener for another textfield. I want that the OK-Button only is activated if in both text fields is min one char.
This is the code of the two fields:
descriptionText.addModifyListener(new ModifyListener(){
public void modifyText(ModifyEvent e) {
Text text = (Text) e.widget;
if (text.getText().length() == 0) {
getButton(IDialogConstants.OK_ID).setEnabled(false);
}
if (text.getText().length() >= 1) {
getButton(IDialogConstants.OK_ID).setEnabled(true);
}
}
});
}
the second field:
ccidText.addModifyListener(new ModifyListener(){
public void modifyText(ModifyEvent e) {
Text text = (Text) e.widget;
if (text.getText().length() == 0) {
getButton(IDialogConstants.OK_ID).setEnabled(false);
}
if (text.getText().length() >= 1){
getButton(IDialogConstants.OK_ID).setEnabled(true);
}
}
});
}
I know that it doesn´t work because there are no dependencies between the two buttons.
How can i combine it?
I want to set the ok-button false while both modifylistener detect a char.
If i delete all chars in one testfield the button must be deactivated again.
Thank u.
You can use the same Listener for both Text fields and add it for SWT.KeyUp:
public static void main(String[] args)
{
final Display display = new Display();
Shell shell = new Shell(display);
shell.setText("StackOverflow");
shell.setLayout(new FillLayout(SWT.VERTICAL));
final Text first = new Text(shell, SWT.BORDER);
final Text second = new Text(shell, SWT.BORDER);
final Button button = new Button(shell, SWT.PUSH);
button.setText("disabled");
button.setEnabled(false);
Listener listener = new Listener()
{
#Override
public void handleEvent(Event e)
{
String firstString = first.getText();
String secondString = second.getText();
button.setEnabled(!isEmpty(firstString) && !isEmpty(secondString));
button.setText(button.isEnabled() ? "enabled" : "disabled");
}
};
first.addListener(SWT.KeyUp, listener);
second.addListener(SWT.KeyUp, listener);
shell.pack();
shell.setSize(300, shell.getSize().y);
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
private static boolean isEmpty(String input)
{
if(input == null)
return true;
else
return input.trim().isEmpty();
}
Looks like this:
The code will basically (on each key stroke) check if both Texts are empty. If so, disable the Button, else enable it.

Display parent modal dialog with SWT

AWT/Swing allows to show application modal (blocking the whole application) and parent modal (blocking only the parents) dialogs. How can I achieve the same with SWT?
In order to block the whole application, you can create the dialog Shell with the style SWT.APPLICATION_MODAL, open it, and then pump the UI events until the shell is disposed:
Display display = Display.getDefault();
Shell dialogShell = new Shell(display, SWT.APPLICATION_MODAL);
// populate dialogShell
dialogShell.open();
while (!dialogShell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
If you want to block input only to the parent, try using the style SWT.PRIMARY_MODAL, though the Javadocs specify (as for the other modal styles) that this is a hint; i.e., that different SWT implementations may not exactly handle it the same way. Likewise, I don't know of an implementation that would honor the SWT.SYSTEM_MODAL style.
UPDATE: Answer to first comment
If you have two or more primary modals open at the same time, you cannot use the tricks to pump the events until the modal is closed, as they could be closed in any order. The code will run, but execution will resume after the while loop after the current dialog is closed and all other such dialogs that have been opened after it. In this case, I would register a DisposeListener on each dialog to get a callback when they are closed. Something like this:
void run() {
Display display = new Display();
Shell shell1 = openDocumentShell(display);
Shell shell2 = openDocumentShell(display);
// close both shells to exit
while (!shell1.isDisposed() || !shell2.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
Shell openDocumentShell(final Display display) {
final Shell shell = new Shell(display, SWT.SHELL_TRIM);
shell.setLayout(new FillLayout());
Button button = new Button(shell, SWT.PUSH);
button.setText("Open Modal Dialog");
button.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
System.out.println("Button pressed, about to open modal dialog");
final Shell dialogShell = new Shell(shell, SWT.PRIMARY_MODAL | SWT.SHEET);
dialogShell.setLayout(new FillLayout());
Button closeButton = new Button(dialogShell, SWT.PUSH);
closeButton.setText("Close");
closeButton.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
dialogShell.dispose();
}
});
dialogShell.setDefaultButton(closeButton);
dialogShell.addDisposeListener(new DisposeListener() {
#Override
public void widgetDisposed(DisposeEvent e) {
System.out.println("Modal dialog closed");
}
});
dialogShell.pack();
dialogShell.open();
}
});
shell.pack();
shell.open();
return shell;
}

Categories

Resources