I am using ITMill 5.3.0-rc12 under Ubuntu 8.04, and the browser is Firefox 3.05.
Can you confirm if the following is expected behavior:
When I call setEnabled(false) on a Window, it will store all of the enabled states for all of Components first (button 1 is disabled, and button 2, 3 are enabled), then disable them all. When I call setEnabled(true) later on, the states that were saved will be restored (button 1 is disabled again, and button 2, 3 are enabled). This is what I observe in my test case - but ONLY AFTER a browser refresh.
The need for a browser refresh looks like a bug: after the setEnabled() states are restored, there is NO change on the browser (all buttons remain disabled), UNTIL I do a REFRESH (F5).
Thanks
Andrew
package itmill.testcases;
import com.itmill.toolkit.Application;
import com.itmill.toolkit.ui.Button;
import com.itmill.toolkit.ui.Window;
import com.itmill.toolkit.ui.Button.ClickEvent;
import com.itmill.toolkit.ui.Button.ClickListener;
public class SetEnabledTestApplication extends Application
{
private Window mainWindow = new Window("SetEnabledTestApplication Window");
private Button button1;
private Button button2;
private Button button3;
@Override
public void init()
{
button1 = new Button("Button1");
button1.setEnabled(false);
button2 = new Button("Button2");
button2.setEnabled(true);
button3 = new Button("Button3");
button3.setEnabled(true);
button3.addListener(new ClickListener() {
private Thread thread;
public void buttonClick(ClickEvent event)
{
// This appears to store all button states, then disables ALL
// buttons
mainWindow.setEnabled(false);
thread = new Thread() {
@Override
public void run()
{
try
{
Thread.sleep(5000);
System.out.println("About to reenable window ...");
// Make sure we synchronize against Application to
// guarantee no thread contention with Browser
// originating function calls.
synchronized (SetEnabledTestApplication.this)
{
// This appears to restore ALL buttons back to
// their original setEnabled() state - it does
// NOT simply setEnabledd(true) ALL buttons.
// BUT, the browser is NOT updated until a
// manual refresh is done.
mainWindow.setEnabled(true);
}
System.out.println("Reenabled window.");
} catch (InterruptedException e)
{
}
}
};
thread.start();
}
});
mainWindow.getLayout().setSizeFull();
mainWindow.setSizeFull();
mainWindow.addComponent(button1);
mainWindow.addComponent(button2);
mainWindow.addComponent(button3);
setMainWindow(mainWindow);
}
}
it looks to me that the problem is because you’re calling setEnabled(true) in a separate server-side thread. In this case, server-side state changed but client (browser) does not know about it until the next roundtrip to the server which does not happen automatically.
Note, that you disable the window by the click event of a button - in this case changed state propagated to the client immideately, in the button click response from the server to client - this is why you see the change without the browser’s refresh.
If you want to reenable the window exactly from a background server-side thread you’ll need to implement a hidden progress indicator on a client, that will poll server on a specified interval basis, thus allowing all accumulated server-side state changes propagated to the client.
In relation to the polling indicator, will setEnabled(false) on the Window (or anything else) in an application disable polling, or is it guaranteed that polling will always be active ? Basically, I need to be sure that the browser will be updated when the server independently makes updates, no matter which Components are setEnabled(false). I found that when I tried to add a polling indicator with the modified code below, but I still get no automatic refresh - I still need to manually refresh the browser with F5. Can you see anything wrong in my example code ?
I also found this ticket (Ajax server push) for ITMill, which would be great to see included in the product:
package nstc.webx2.app.gui.main;
import com.itmill.toolkit.Application;
import com.itmill.toolkit.ui.Button;
import com.itmill.toolkit.ui.ProgressIndicator;
import com.itmill.toolkit.ui.Window;
import com.itmill.toolkit.ui.Button.ClickEvent;
import com.itmill.toolkit.ui.Button.ClickListener;
public class SetEnabledTestApplication extends Application
{
private Window mainWindow = new Window("SetEnabledTestApplication Window");
private Button button1;
private Button button2;
private Button button3;
@Override
public void init()
{
button1 = new Button("Button1");
button1.setEnabled(false);
button2 = new Button("Button2");
button2.setEnabled(true);
button3 = new Button("Button3");
button3.setEnabled(true);
// Poll for new messages once a second.
final ProgressIndicator pi = new ProgressIndicator();
pi.setIndeterminate(true);
pi.setVisible(true);
// pi.setStyleName("invisible");
mainWindow.addComponent(pi);
button3.addListener(new ClickListener() {
private Thread thread;
public void buttonClick(ClickEvent event)
{
// This appears to store all button states, then disables ALL
// buttons
mainWindow.setEnabled(false);
thread = new Thread() {
@Override
public void run()
{
try
{
Thread.sleep(5000);
System.out.println("About to reenable window ...");
// Make sure we synchronize against Application to
// guarantee no thread contention with Browser
// originating function calls.
synchronized (SetEnabledTestApplication.this)
{
// This appears to restore ALL buttons back to
// their original setEnabled() state - it does
// NOT simply setEnabledd(true) ALL buttons.
// BUT, the browser is NOT updated until a
// manual refresh is done.
mainWindow.setEnabled(true);
}
System.out.println("Reenabled window.");
} catch (InterruptedException e)
{
}
}
};
thread.start();
}
});
mainWindow.getLayout().setSizeFull();
mainWindow.setSizeFull();
mainWindow.addComponent(button1);
mainWindow.addComponent(button2);
mainWindow.addComponent(button3);
setMainWindow(mainWindow);
}
}
I tried adding the setPollingInterval in 1, then in 2 places (see code below), but still I get the same result - a manual refresh is needed. Any ideas on what I might be doing incorrectly ?
Could it be because I have the ProgressIndicator contained in the Window, and I am calling setEnabled(false) on the Window, and the Window is somehow disabling the polling of the ProgressIndicator it contains ?
Thanks
Andrew
package itmill.testcases;
import com.itmill.toolkit.Application;
import com.itmill.toolkit.ui.Button;
import com.itmill.toolkit.ui.ProgressIndicator;
import com.itmill.toolkit.ui.Window;
import com.itmill.toolkit.ui.Button.ClickEvent;
import com.itmill.toolkit.ui.Button.ClickListener;
public class SetEnabledTestApplication extends Application
{
private Window mainWindow = new Window("SetEnabledTestApplication Window");
private Button button1;
private Button button2;
private Button button3;
@Override
public void init()
{
button1 = new Button("Button1");
button1.setEnabled(false);
button2 = new Button("Button2");
button2.setEnabled(true);
button3 = new Button("Button3");
button3.setEnabled(true);
// Poll for new messages once a second.
final ProgressIndicator pi = new ProgressIndicator();
pi.setIndeterminate(false);
pi.setVisible(true);
pi.setPollingInterval(1000);
// pi.setStyleName("invisible");
mainWindow.addComponent(pi);
button3.addListener(new ClickListener() {
private Thread thread;
public void buttonClick(ClickEvent event)
{
// This appears to store all button states, then disables ALL
// buttons
mainWindow.setEnabled(false);
pi.setPollingInterval(1000);
thread = new Thread() {
@Override
public void run()
{
try
{
Thread.sleep(5000);
System.out.println("About to reenable window ...");
// Make sure we synchronize against Application to
// guarantee no thread contention with Browser
// originating function calls.
synchronized (SetEnabledTestApplication.this)
{
// This appears to restore ALL buttons back to
// their original setEnabled() state - it does
// NOT simply setEnabledd(true) ALL buttons.
// BUT, the browser is NOT updated until a
// manual refresh is done.
mainWindow.setEnabled(true);
}
System.out.println("Reenabled window.");
} catch (InterruptedException e)
{
}
}
};
thread.start();
}
});
mainWindow.getLayout().setSizeFull();
mainWindow.setSizeFull();
mainWindow.addComponent(button1);
mainWindow.addComponent(button2);
mainWindow.addComponent(button3);
setMainWindow(mainWindow);
}
}
You guessed it right. Disable progressindicator does not poll server. I think you could easily overcome this by overriding isEnabled method so that it does not become disabled when inside a disabled component. Try this:
myProgressIndicator = new ProgressIndicator() {
@Override
public boolean isEnabled() {
return true;
}
}
I tried Matti’s suggestion, and the browser is now automatically updated when there is any change in the client, by polling the server periodically. Not quite as good as server push, but it will certainly do the job for now.
The sample code is copied below for anyone to reference.
Many Thanks
Andrew
package itmill.testcases;
import com.itmill.toolkit.Application;
import com.itmill.toolkit.ui.Button;
import com.itmill.toolkit.ui.Panel;
import com.itmill.toolkit.ui.ProgressIndicator;
import com.itmill.toolkit.ui.Window;
import com.itmill.toolkit.ui.Button.ClickEvent;
import com.itmill.toolkit.ui.Button.ClickListener;
public class SetEnabledTestApplication extends Application
{
private Window mainWindow = new Window("SetEnabledTestApplication Window");
private Button button1;
private Button button2;
private Button button3;
@Override
public void init()
{
button1 = new Button("Button1");
button1.setEnabled(false);
button2 = new Button("Button2");
button2.setEnabled(true);
button3 = new Button("Button3");
button3.setEnabled(true);
// Poll for new messages once a second.
final ProgressIndicator pi = new ProgressIndicator() {
@Override
public boolean isEnabled()
{
return true;
}
};
pi.setIndeterminate(false);
pi.setVisible(false);
pi.setPollingInterval(1000);
// pi.setStyleName("invisible");
Panel panel = new Panel();
panel.addComponent(pi);
mainWindow.addComponent(panel);
button3.addListener(new ClickListener() {
private Thread thread;
public void buttonClick(ClickEvent event)
{
// This appears to store all button states, then disables ALL
// buttons
mainWindow.setEnabled(false);
pi.setVisible(true);
pi.setPollingInterval(1000);
thread = new Thread() {
@Override
public void run()
{
try
{
Thread.sleep(5000);
System.out.println("About to reenable window ...");
// Make sure we synchronize against Application to
// guarantee no thread contention with Browser
// originating function calls.
synchronized (SetEnabledTestApplication.this)
{
// This appears to restore ALL buttons back to
// their original setEnabled() state - it does
// NOT simply setEnabledd(true) ALL buttons.
// BUT, the browser is NOT updated until a
// manual refresh is done.
mainWindow.setEnabled(true);
}
System.out.println("Reenabled window.");
} catch (InterruptedException e)
{
}
}
};
thread.start();
}
});
mainWindow.getLayout().setSizeFull();
mainWindow.setSizeFull();
mainWindow.addComponent(button1);
mainWindow.addComponent(button2);
mainWindow.addComponent(button3);
setMainWindow(mainWindow);
}
}