How to write message to status line from handler class in Eclipse RCP programming - eclipse-rcp

I need to change status line message from a handler class. After reading the RCP tutorial and eclipse FAQ, I finally did something like this:
HandlerUtil.getActiveWorkbenchWindow(event).getActivePage().findView(AView.ID).getViewSite().getActionBars().getStatusLineManager().setMessage( "Ha, I'm finished");
What a long invoking chain!
Am I doing it the right way? Thanks.

From the threads I see in the forums, that looks about right.
Beware though if you have asynchronous feedback to put in this status line.
See this thread for instance.
UIJob job = new UIJob() {
public IStatus run(IProgressMonitor monitor) {
//do the long running work here
Runnable results = new Runnable() {
public void run(){
// update UI elements here;
getViewSite().getActionBars().getStatusLineManager().
setMessage("End Pasting");
}
};
display.asyncExec(results);
}
};
job.schedule();
(Note: that may be not your case, but I add this code snippet just for information)

Related

How to make wait some time in GWT after the Async call

In my code, I am making async call to do validation. Depeding upon return value of the validation, I need to execute some lines.
But I am not able to put that lines in the callback method of Async = public void success(Boolean valid).
Since one of the line is super.onDrop(context) which is method of another class that can't be called inside Async callback method.
Please see the below line. I need super.onDrop(context) will be executed after async call is completed.
stepTypeFactory.onDropValidation(stepTypeFactory,new AsyncCallbackModal(null) {
public void success(Boolean valid) {
if(valid==Boolean.TRUE){
//super.onDrop(context);
}
};
});
//condition is here
super.onDrop(context);
Is there any way, i will tell gwt wait 1 or 2 seconds before super.onDrop(context) is executed. Right now what happening is,
super.onDrop(context) is executed before the call back method is completed.
You can do:
stepTypeFactory.onDropValidation(stepTypeFactory,new AsyncCallbackModal(null) {
public void success(Boolean valid) {
if(valid==Boolean.TRUE){
drop();
}
};
});
private void drop() {
super.onDrop(context);
}
An alternative solution would be, like mentioned from Thomas Broyer in the comments:
stepTypeFactory.onDropValidation(stepTypeFactory,new AsyncCallbackModal(null) {
public void success(Boolean valid) {
if(valid==Boolean.TRUE){
ContainingClass.super.onDrop(context);
}
};
});
Eclipse does not suggests this solution when using the code completion, but it works.
Also i would possibly reconsider your design, because it can get very tricky (by experience) when you have many Callbacks which are connecting/coupling classes. But this is just a quick thought, i neither know the size of your project nor the design.

Eclipse Plug-In developement, long running task

I have several UI-Components which have listeners. All these listeners invoke method dialogChanged(). My goal is to make some long processing in this method and don't let the UI freeze. According to Lars Vogel it is possible to do this with help of UISynchronize being injected during runtime. But it fails for me, field of this type is not being injected and i get a NullPointerException. Here's relevant part of my code:
#Inject UISynchronize sync;
Job job = new Job("My Job") {
#Override
protected IStatus run(IProgressMonitor arg0)
{
sync.asyncExec(new Runnable()
{
#Override
public void run()
{
updateStatus("Checking connection...");
if (bisInstallDirSelected)
bisSettingsChanged();
else
jarSettingsChanged();
}
});
return Status.OK_STATUS;
}
};
protected void dialogChanged()
{
job.schedule();
}
The methods updateStatus(String s), bisSettingsChanged() and jarSettingsChanged() interact with UI, to be presice, they use method setErrorMessage(String newMessage) of superclass org.eclipse.jface.wizard.WizardPage
I'd appreciate if somebody could tell me what I am doing wrong or suggest a better way to handle this problem.
You can only use #Inject in classes that the e4 application model creates (such as the class for a Part or a Command Handler).
You can also use ContextInjectionFactory to do injection on your own classes.
For classes where injection has not been done you can use the 'traditional' way of running code in the UI thread:
Display.getDefault().asyncExec(runnable);

Eclipse is forcing everything to be static

For some reason after I had added and removed a static vairable from my code, eclipse started giving me errors on all functions that I call, saying that these functions must be static. However, if I let the program run with these errors, the program runs just as I intended it to do. My Code:
package main;
public class Main implements Runnable {
public void start() {
Thread thread = new Thread(this);
thread.start();
System.out.println("Running...");
Ball.test(); <--- Giving me an error
}
public void run() {
}
public void stop() {
System.out.println("Exiting...");
}
}
and when I create a method in ball called test it gives me:
public static void test() {
// TODO Auto-generated method stub
}
Well yes - you're calling the method as if it were a static method:
Ball.test()
If you want to call an instance method, you need to call it on an instance, e.g.
Ball ball = new Ball();
ball.test();
It's important to understand the difference between static members and instance members. Have you read the appropriate chapter of the Java tutorial? Do you have a good Java book which would help you? (Stack Overflow is great for specific questions, but not good for learning a language from scratch. Explaining language concepts well takes a lot of space and time.)

SWTbot tests not behaving as expected

So I'm testing an eclipse plugin with SWTbot and I'm not getting the result I'm expect - when I cut the test down it turns out that the problem isn't with the bot it's with some code that I've copied accross from another part of the program (where it was fully functional)
The following code...
#RunWith(SWTBotJunit4ClassRunner.class)
public class Tests {
private static SWTWorkbenchBot bot;
#BeforeClass
public static void beforeClass() throws Exception {
bot = new SWTWorkbenchBot();
bot.viewByTitle("Welcome").close();
}
#Test
public void maybeThisWillWork(){
IWorkbenchWindow activeWorkbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
System.out.println("A");
IWorkbenchPage activePage = activeWorkbenchWindow.getActivePage();
System.out.println("B");
}
#AfterClass
public static void sleep() {
System.out.println("In the sleep function");
bot.sleep(10000);
}
}
Gives me the output -
A
In the sleep function
Rather than the expected
A
B
In the sleep function
Any ideas?
you may need to run your test as JUnit plugin test. Have you tried that?
So it turns out that the answer is thus (also a nice advantage of stackoverflow is that I actually solved this somewhere else, remembered I'd had a similar problem and then had to come back to stackoverflow to remind myself of the details)
SWTBot isn't running in the UI thread proper hence the null pointer errors, what I had to do was use effectively:
Display display = bot.getDisplay();
display.syncExec(objectThatdoesthethingiwanttogetdoneintheUIthread);
System.out.println(objectThatdoesthethingiwanttogetdoneintheUIthread.results);
...and that got things working...

What's the best way to get a return value out of an asyncExec in Eclipse?

I am writing Eclipse plugins, and frequently have a situation where a running Job needs to pause for a short while, run something asynchronously on the UI thread, and resume.
So my code usually looks something like:
Display display = Display.getDefault();
display.syncExec(new Runnable() {
public void run() {
// Do some calculation
// How do I return a value from here?
}
});
// I want to be able to use the calculation result here!
One way to do it is to have the entire Job class have some field. Another is to use a customized class (rather than anonymous for this and use its resulting data field, etc.
What's the best and most elegant approach?
I think the Container above is the "right" choice. It could be also be genericized for type safety. The quick choice in this kind of situation is the final array idiom. The trick is that a any local variables referenced from the Runnable must be final, and thus can't be modified. So instead, you use a single element array, where the array is final, but the element of the array can be modified:
final Object[] result = new Object[1];
Display display = Display.getDefault();
display.syncExec(new Runnable()
{
public void run()
{
result[0] = "foo";
}
}
System.out.println(result[0]);
Again, this is the "quick" solution for those cases where you have an anonymous class and you want to give it a place to stick a result without defining a specific Container class.
UPDATE
After I thought about this a bit, I realized this works fine for listener and visitor type usage where the callback is in the same thread. In this case, however, the Runnable executes in a different thread so you're not guaranteed to actually see the result after syncExec returns. The correct solution is to use an AtomicReference:
final AtomicReference<Object> result = new AtomicReference<Object>();
Display display = Display.getDefault();
display.syncExec(new Runnable()
{
public void run()
{
result.set("foo");
}
}
System.out.println(result.get());
Changes to the value of AtomicReference are guaranteed to be visible by all threads, just as if it were declared volatile. This is described in detail here.
You probably shouldn't be assuming that the async Runnable will have finished by the time the asyncExec call returns.
In which case, you're looking at pushing the result out into listeners/callbacks (possibly Command pattern), or if you do want to have the result available at a later in the same method, using something like a java.util.concurrent.Future.
Well, if it's sync you can just have a value holder of some kind external to the run() method.
The classic is:
final Container container = new Container();
Display display = Display.getDefault();
display.syncExec(new Runnable()
{
public void run()
{
container.setValue("foo");
}
}
System.out.println(container.getValue());
Where container is just:
public class Container {
private Object value;
public Object getValue() {
return value;
}
public void setValue(Object o) {
value = o;
}
}
This is of course hilarious and dodgy (even more dodgy is creating a new List and then setting and getting the 1st element) but the syncExec method blocks so nothing bad comes of it.
Except when someone comes back later and makes it asyncExec()..