Display parent modal dialog with SWT - java

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;
}

Related

Show/Hide Application from/to System Tray

I need some guidance in how to get the application to show up from the System Tray when I click on it.
I have managed to minimize the app on closure but I can't make it to show up.
If I'm builduing a new shell with same Contents would help?(I am building a SWT application)
This is how I am initializing my Shell: (I have modified it so I don't use AWT with SWT)
protected Shell shlSmartHouseSystem;
public void open() {
Display display = Display.getDefault();
createContents();
shlSmartHouseSystem.open();
shlSmartHouseSystem.layout();
while (!shlSmartHouseSystem.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
And this is my function where I am minimizing in Tray:
public void minimizeToTrayOnClose() {
final Display display = shlSmartHouseSystem.getDisplay();
Image image = new Image(display,"D:\\VIA_University_(Embedded_Systems)\\AJP_Workspace\\HouseSystem_Server\\icon-smart-house.png");
Tray tray = display.getSystemTray();
if (tray != null) {
TrayItem trayItm = new TrayItem(tray,SWT.NONE);
trayItm.setImage(image);
final Menu menu = new Menu(shlSmartHouseSystem, SWT.POP_UP);
MenuItem menuItem = new MenuItem(menu, SWT.PUSH);
menuItem.setText("Show");
menuItem.addListener (SWT.Selection, new Listener () {
public void handleEvent (Event e) {
System.out.println("Opened");
}
});
menuItem = new MenuItem(menu, SWT.PUSH);
menuItem.setText("Exit");
menuItem.addListener (SWT.Selection, new Listener () {
public void handleEvent (Event e) {
System.exit(0);
}
});
trayItm.addListener (SWT.MenuDetect, new Listener () {
public void handleEvent (Event event) {
menu.setVisible (true);
}
});
}
}

Open new tab in swt browser after button click

I used SWT browser. I opened page and there is a Button which verify that browser have option to open new browser window. Standard SWT browser have problem with it. Above is how button is defined.
<button class="btn btn-action btn-slim size-w-90pct" data-e2e="openDealerBtn" ng-if="igDefaultRowController.account.isPdSupported" ng-class="{'btn-disabled': igDefaultRowController.shouldDisableOpenPlatformButton}" ng-disabled="igDefaultRowController.shouldDisableOpenPlatformButton" ng-click="igDefaultRowController.openDealer()" ig-click-tracking="pureDealBtn-CFD" id="openDealerButton-XQ7JI"> <span class="btn-label" ig-i18n="" key="AccountOverview.openDealer"><span ng-bind-html="value">Open classic platform</span></span> </button>
[SOLVED!] How to expand SWT browser to open more than one tab ?
I used TabFolder for more tabs.
It is possible to catch URL after click on this button and open in new SWT browser tab ?
SWT uses one of the browsers that are available on the operating system and embeds the main "view" of the browser (the bit that displays the html) in your application. That does mean, however, that it doesn't come with all the fancy stuff like tabs.
As you already discovered yourself, you can get around this by using a TabFolder.
The question now is: how do you know when a tab should be opened. This code (adopted from Snippet270) should help you with this:
public static void main(String[] args)
{
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Main Window");
shell.setLayout(new FillLayout());
final Browser browser;
try
{
browser = new Browser(shell, SWT.NONE);
}
catch (SWTError e)
{
System.out.println("Could not instantiate Browser: " + e.getMessage());
display.dispose();
return;
}
initialize(display, browser);
shell.open();
browser.setUrl("http://www.w3schools.com/html/tryit.asp?filename=tryhtml_links_target");
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
/* register WindowEvent listeners */
static void initialize(final Display display, Browser browser)
{
browser.addOpenWindowListener(e ->
{
Shell shell = new Shell(display);
shell.setText("New Window");
shell.setLayout(new FillLayout());
Browser browser1 = new Browser(shell, SWT.NONE);
initialize(display, browser1);
e.browser = browser1;
});
browser.addVisibilityWindowListener(new VisibilityWindowListener()
{
#Override
public void hide(WindowEvent e)
{
Browser browser = (Browser) e.widget;
Shell shell = browser.getShell();
shell.setVisible(false);
}
#Override
public void show(WindowEvent e)
{
Browser browser = (Browser) e.widget;
final Shell shell = browser.getShell();
if (e.location != null) shell.setLocation(e.location);
if (e.size != null)
{
Point size = e.size;
shell.setSize(shell.computeSize(size.x, size.y));
}
shell.open();
}
});
browser.addCloseWindowListener(e ->
{
Browser browser1 = (Browser) e.widget;
Shell shell = browser1.getShell();
shell.close();
});
}
This will open the link in a new Shell with a new Browser. You can change this, so it creates a new tab and adds the new browser to the new tab.
EDIT
Here's a working example using TabFolder:
public static void main(String[] args)
{
Display display = new Display();
Shell shell = new Shell(display);
shell.setText("Main Window");
shell.setLayout(new FillLayout());
TabFolder tabFolder = new TabFolder(shell, SWT.BORDER);
addNewBrowser(tabFolder, "<a href='http://www.google.co.uk' target='_blank'>Click here!</a>");
shell.open();
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
private static Browser addNewBrowser(TabFolder folder, String html)
{
TabItem item = new TabItem(folder, SWT.NONE);
Composite c = new Composite(folder, SWT.NONE);
item.setControl(c);
c.setLayout(new FillLayout());
Browser browser = new Browser(c, SWT.NONE);
if (html != null)
{
browser.setText(html);
item.setText("Original tab");
}
else
{
item.setText("New tab");
}
browser.addOpenWindowListener(e ->
{
e.browser = addNewBrowser(folder, null);
});
browser.addVisibilityWindowListener(new VisibilityWindowListener()
{
#Override
public void hide(WindowEvent e)
{
Browser browser = (Browser) e.widget;
Shell shell = browser.getShell();
shell.setVisible(false);
}
#Override
public void show(WindowEvent e)
{
Browser browser = (Browser) e.widget;
final Shell shell = browser.getShell();
if (e.location != null) shell.setLocation(e.location);
if (e.size != null)
{
Point size = e.size;
shell.setSize(shell.computeSize(size.x, size.y));
}
shell.open();
}
});
browser.addCloseWindowListener(e ->
{
Browser browser1 = (Browser) e.widget;
Shell shell = browser1.getShell();
shell.close();
});
folder.setSelection(item);
return browser;
}

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 Spinner - Disabling Keyboard Editing

On SWT spinner (or maybe some other similar SWT widget), how can I force the user to use the UI buttons instead of edit the text from the keyboard. thanks.
SWT.READ_ONLY will prevent the user from entering values. To disable arrow keys as well, you can do something like this:
public static void main(String args[])
{
Display display = new Display();
final Shell shell = new Shell(display);
shell.setText("StackOverflow");
shell.setLayout(new FillLayout());
Spinner spinner = new Spinner(shell, SWT.READ_ONLY);
spinner.addListener(SWT.Verify, new Listener()
{
#Override
public void handleEvent(Event e)
{
if(e.keyCode == SWT.ARROW_UP || e.keyCode == SWT.ARROW_DOWN)
{
e.doit = false;
}
}
});
shell.pack();
shell.setSize(100, shell.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
shell.open();
while (!shell.isDisposed())
{
if (!shell.getDisplay().readAndDispatch())
shell.getDisplay().sleep();
}
}
This will make sure that the only way to change the Spinner value is using the buttons.

Hide ON_TOP shell in SWT on Display minimimized

I'm trying to hide a SWT shell when the Display is minimized. I'm missing something and would be most thankful for any help.
Additional Info: This shell is actually a popup that gets drawn when the user clicks on a composite. In the end, my goal is to hide this popup-shell when the composite is not visible (user minimized the window or switched between windows, say with Alt+Tab for example).
Here's my code:
static Shell middleClickNodeInfoShell ;
static Label nodeIdLabel ;
void init(){
...
/** Focused node on middle click*/
middleClickNodeInfoShell = new Shell(Display.getDefault(), SWT.BORDER | SWT.MODELESS);
middleClickNodeInfoShell.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, true, false));
middleClickNodeInfoShell.setLayout(createNoMarginLayout(1, false));
nodeIdLabel = new Label(middleClickNodeInfoShell, SWT.NONE);
Display.getDefault().addListener(SWT.Iconify,new Listener() {
#Override
public void handleEvent(Event arg0) {
// TODO Auto-generated method stub
middleClickNodeInfoShell.setVisible(false);
}
});
}
#Override
public boolean onMouseClicked(Button button, ScreenPosition screenPos,
final GeoPosition arg2) {
...
nodeIdLabel.setText("Node Id: "+node.getId());
middleClickNodeInfoShell.setLocation(pos.getX()+displayX,pos.getY()+displayY+30);
middleClickNodeInfoShell.setVisible(true);
middleClickNodeInfoShell.pack();
}
Here is sample code that will help you do figure out what you are looking for
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setSize(300, 200);
shell.setText("Shell Example");
shell.setLayout(new RowLayout());
final Button button = new Button(shell, SWT.PUSH);
button.setText("Click Me");
final Shell tip = new Shell(shell,SWT.MODELESS);
tip.setLayout(new FillLayout());
Label lbl = new Label(tip, SWT.NONE);
lbl.setText("***tooltip***");
tip.pack();
shell.addControlListener(new ControlListener() {
#Override
public void controlResized(ControlEvent e) {
changeTipLocation(display, button, tip);
}
#Override
public void controlMoved(ControlEvent e) {
changeTipLocation(display, button, tip);
}
});
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
changeTipLocation(display, button, tip);
tip.open();
}
});
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
private static void changeTipLocation(final Display display, final Button button, final Shell tip) {
Rectangle bounds = button.getBounds();
Point loc = button.getLocation();
tip.setLocation(display.map(button, null, new Point(loc.x+bounds.width, loc.y+bounds.height)));
}

Categories

Resources