Archive

Archive for October, 2012

Adding Project Nature Programmatically in Eclipse

October 17, 2012 Leave a comment

In this post we are going to see how can we add a custom project nature programmatically.

I found a nice post

which precisely tells us how should we create a java project programmatically. Now what if I want to have a custom project nature for my project?

Every project created inside eclipse will be associated with natures.
You can find this in the .project file. An example is shown below.

Now in sometimes , we may require to add custom nature to our project. The extension point org.eclipse.core.resources.natures helps us to do that.

Add org.eclipse.core.resources as a dependency in plugin.xml.
Then add org.eclipse.core.resources.natures extension point. It may look like below


<extension
         id="myplugin.myprojnature"
         point="org.eclipse.core.resources.natures">
      <runtime>
         <run
               class="myplugin.MyProjNature">
         </run>
      </runtime>
 </extension>

Now , create a MyProjNature class which implements IProjectNature interface.


public class MyProjNature implements IProjectNature {

	public static final String NATURE_ID = "com.mycomp.myproject.myprojnature";
	
	@Override
	public void configure() throws CoreException {
		// TODO Auto-generated method stub

	}

	@Override
	public void deconfigure() throws CoreException {
		// TODO Auto-generated method stub

	}

	@Override
	public IProject getProject() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setProject(IProject arg0) {
		// TODO Auto-generated method stub

	}

}

The below piece of code will do the job of adding the custom nature,


             try {
			IProjectDescription desc = myProj.getDescription();
			String[] prevNatures = desc.getNatureIds();
			String[] newNatures = new String[prevNatures.length + 1];
			System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length);
			newNatures[prevNatures.length] = MyProjNature.NATURE_ID;
			desc.setNatureIds(newNatures);
			myProj.setDescription(desc, new NullProgessMonitor());
		} catch (CoreException e) {
			e.printStackTrace();
		}

That’s it. Hope this is helpful.
Happy coding. 🙂

Advertisements

Scheduled Notifications in Eclipse RCP Applications

October 6, 2012 1 comment

As a busy developers we tend to miss little things day to day, forget to filing out effort sheet is one great example 😉 😛 , So for these reminders/notifications are helpful.
Mylyn notifications is a really good solution for including notifications in RCP applications.
Now in realtime most of us would need a scheduled notifications, Lately for a POC I did we were in a need of such a scheduled notification for the RCP app. In this post we are going to see how can we schedule notifications using ‘quartz job’.

As a regular news reader , I use to check google news after my lunch almost everyday. Lets schedule a notification at 13:30 everyday to say “News time” . So our notification will be having a link to news.google.com. 🙂

In your plug-in project add “org.eclipse.mylyn.commons.ui“ as a dependency. Now to create the notification popup , create a class called NotificationPopUI and extend “org.eclipse.mylyn.internal.provisional.commons.ui.AbstractNotificationPopup” class.


import java.net.MalformedURLException;
import java.net.URL;
import org.eclipse.mylyn.internal.provisional.commons.ui.AbstractNotificationPopup;
import org.eclipse.mylyn.internal.provisional.commons.ui.CommonFonts;
import org.eclipse.mylyn.internal.provisional.commons.ui.CommonImages;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.browser.IWebBrowser;
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;

@SuppressWarnings("restriction")
public class NotificationPopUpUI extends AbstractNotificationPopup
{

  @SuppressWarnings("restriction")
public NotificationPopUpUI(Display display)
  {
    super(display);
  }

  @Override
  protected void createContentArea(Composite composite)
  {
    composite.setLayout(new GridLayout(1, true));
    Link linkGoogleNews = new Link(composite, 0);
    String googlenewsLink = "This is a link to <a href=\"https://news.google.com\">Google News</a>";
    linkGoogleNews.setText(googlenewsLink);
    linkGoogleNews.setSize(400, 100);

    linkGoogleNews.addSelectionListener(new SelectionAdapter()
    {
      public void widgetSelected(SelectionEvent e) {
        try {
          PlatformUI.getWorkbench().getBrowserSupport()
            .getExternalBrowser().openURL(new URL(e.text));
        } catch (PartInitException e1) {
          e1.printStackTrace();
        } catch (MalformedURLException e1) {
          e1.printStackTrace();
        }
      }
    });
  }

  
  @Override
  protected String getPopupShellTitle()
  {
    return "It's News Time!";
  }
 
  @Override 
  protected Image getPopupShellImage(int maximumHeight)
  {
    return null;
  }
}

The method protected void createContentArea(Composite composite){} should be overrided to add the content which we want to display.
If we want to customize the title area also, then we should consider overriding
protected void createTitleArea(Composite parent){}.

Now we are done with creating the content of our notification popup , we need two other things to get this whole thing done.

1. A Quartz Job class where we will invoke the notification popup.
2. A place where we will be triggering/scheduling the quartz job.

Task#1 – Invoking the notification
Create a class called InvokeNotificationJob which implements org.quartz.Job interface.


import org.eclipse.swt.widgets.Display;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class InvokeNotificationJob
  implements Job
{
  public void execute(JobExecutionContext context)
    throws JobExecutionException
  {
    Runnable runnable = new Runnable()
    {
      public void run()
      {
        NotificationPopUpUI popup = new  NotificationPopUpUI(NotificationQuartzJobHelper.getInstance().getCurrentDisp());
        popup.open();
      }
    };
    NotificationQuartzJobHelper.getInstance().getCurrentDisp().syncExec(runnable);
  }
}

As you could see from the above code I am using a helper class, I will explain the use of it little later when we accomplish our task#2.
Note :
With the invocation shown by default the notification will fadeout after certain delay. If in case you do not need the fadeout (forcing the notification to stay until it get closed) we have to set ,


popup.setFadingEnabled(false);
popup.setDelayClose(0L);

Task#2 – Scheduling the notification job

We are not going to have any dedicated action for this triggering, so we are going to make use of startup extension point.

Create a class called StartUpClass which implements org.eclipse.ui.IStartup interface.
The method public void earlyStartup() will be called when the plugin is activated.


import org.eclipse.ui.IStartup;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PlatformUI;
import org.quartz.CronExpression;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;

public class StartUpClass
  implements IStartup
{
  public void earlyStartup()
  {
    if (PlatformUI.isWorkbenchRunning())
     NotificationQuartzJobHelper.getInstance().
       setCurrDisplay(PlatformUI.getWorkbench().getDisplay());
    try
    {
      scheduleNotification();
    } catch (SchedulerException e) {
      e.printStackTrace();
    }
  }

  public void scheduleNotification()
    throws SchedulerException
  {
    SchedulerFactory schedulerFactory = new StdSchedulerFactory();

    Scheduler scheduler = schedulerFactory.getScheduler();


    JobDetail jobDetail = new JobDetail("jobDetail", "jobDetailGroup", InvokeNotificationJob.class);

    CronTrigger cronTrigger = new CronTrigger("cronTrigger", "triggerGroup");
    try
    {
      CronExpression cexp = new CronExpression("0 30 13 ? 1-12 ?");

      cronTrigger.setCronExpression(cexp);
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }

    scheduler.scheduleJob(jobDetail, cronTrigger);

    scheduler.start();
  }
}

There are two things which u could notice here ,
First a helper class is being used to set the current display , which is being used in task#1 code.
Why we need this Display is as notification popup class involves UI stuff we have to do the invoking inside Display thread and since we are using another runnable there what I found it if we use “Display.getDefault()” directly then it will be null . So at the startup we are setting up the Current display and make use of it when we need. There are always better way to do this , but as of now I am going to stick with this.
Now the helper class looks like this ,


import org.eclipse.swt.widgets.Display;

public class NotificationQuartzJobHelper
{
  private static NotificationQuartzJobHelper notificationQuartzJobHelper;
  private Display currentDisp;

  public static NotificationQuartzJobHelper getInstance()
  {
    if (notificationQuartzJobHelper == null) {
      notificationQuartzJobHelper = new NotificationQuartzJobHelper();
    }
    return notificationQuartzJobHelper;
  }

  public void setCurrDisplay(Display currentDisp)
  {
    this.currentDisp = currentDisp;
  }

  public Display getCurrentDisp()
  {
    return this.currentDisp;
  }
}

Second is the scheduleNotification() method on which we are actually performing the scheduling logic.
We are making use of CronExpression to schedule the notification as we needed , the little screenshot below explains the cron expression.

To see a detailed link how to use quartz job and cron expressions click here.

If you run the plugin you could see a notification at the scheduled time as shown below,

Imp Tip: To just test the notification popup , you could invoke it via any one of the view class or actions.

That’s it we are done here.
I hope this is useful.
Happy coding. 🙂

Inline Validations in Eclipse RCP – Field Assists

October 4, 2012 1 comment

Inline validations has been there quite a while now , and in eclipse rcp applications too we can achieve that using control decorators.
What are we going to see in this post is a control decoration , which helps to notify the user if somethings goes wrong when some action is triggered on a control.
Let us consider a real time example , let us take a pincode text field.
If an user is typing in a non-numeric field , then an error icon should be shown to the user.
Let us create a text field on which we ll be adding the decoration.


Label label = new Label(parent, SWT.NONE);
label.setText("Please Enter Pincode:");
label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
		
Text  txtPincode = new Text(parent , SWT.NONE);
txtPincode.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
		
//Adding the decorator
final ControlDecoration txtDecorator = new ControlDecoration(txtPincode, SWT.TOP|SWT.RIGHT);
FieldDecoration fieldDecoration = FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry .DEC_ERROR);
Image img = fieldDecoration.getImage();
txtDecorator.setImage(img);
txtDecorator.setDescriptionText("Pls enter only numeric fields");
// hiding it initially
txtDecorator.hide();
		
txtPincode.addKeyListener(new KeyAdapter() {
			
  @Override
 public void keyReleased(KeyEvent e) {
     Text text = (Text)e.getSource();			
     String string = text.getText();
     char[] chars = new char[string.length()];
     string.getChars(0, chars.length, chars, 0);
      for (int i = 0; i < chars.length; i++)
        {
            if (!('0' <= chars[i] && chars[i] <= '9'))
            {
           	txtDecorator.show();
            }
            else
            {
            	txtDecorator.hide();
            }

        }
		       
}
});
		

Sample screenshot:

On a short note just giving a quick reference for decorators here.
Decorators are often used for other purposes with views also.
The above reference link and this eclipse article will help you cover that.

Happy coding… 🙂

Categories: eclipse rcp, Jface Tags: ,