Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Tuesday, October 9, 2012

HttpServer - The Oracle JDK 1.6 Hidden Feature

I have seen this class many a times, but never encountered a scenario to use it. Recently in one of my application I needed to embedded a HTTP server. So I thought, Why not give this class a try !!

HTTP server infrastructure/framework is very simple to implement and is bundled only with the Oracle JDK 1.6. Following are the main classes:
  1. HttpServer
  2. HttpContext
  3. HttpExchange
See this link for sun.* package discussions.

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.URLDecoder;
import java.util.List;
import java.util.concurrent.Executors;

import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

public class JavaServer 
{
 public static final String nl = System.getProperty("line.separator");

 public static void main(String[] args) throws Exception 
 {
  if(args.length != 2)
  {
   printUsage();
   System.exit(-1);
  }
  String strPort = null;
  String strAddress = null;

  for (int i = 0; i < args.length; i++) 
  {
   if(args[i].startsWith("-p")){
    strPort = args[i].substring(2, args[i].length()).trim();
   }else if(args[i].startsWith("-a")){
    strAddress = args[i].substring(2, args[i].length()).trim();
   }else
    throw new IllegalArgumentException("Unknown command '" + args[i]+ "'");
  }

  if(strAddress.length() == 0 || strPort.length() == 0)
   throw new IllegalArgumentException("Port = " + strPort + ", IP = " + strAddress);

  int port = Integer.parseInt(strPort);
  InetSocketAddress address = new InetSocketAddress(strAddress, port);

  System.out.println("Going to run server on '" + address + "'");

  new JavaServer().start(address);
 }

 private static void printUsage() {
  System.out.println("$JavaServer -p<Port> -a<IP Address>");
 }

 private HttpServer server;

 public void start(InetSocketAddress address) throws IOException
 {
  server = HttpServer.create(address, 0); 
  server.setExecutor(Executors.newCachedThreadPool());
  server.createContext("/", new RootHandler());
  server.start();
 }
}

class RootHandler implements HttpHandler 
{
 private static final int BUFFER_SIZE = 1024;

 public void handle(HttpExchange exchange) throws IOException
 {
  String method = exchange.getRequestMethod();

  if(method.equalsIgnoreCase("get"))
  {
   String request = "";
   ByteArrayOutputStream baos = new ByteArrayOutputStream(BUFFER_SIZE);
   InputStream is = exchange.getRequestBody();

   byte[] buff = new byte[BUFFER_SIZE];
   while (true) 
   {
    int out = is.read(buff);
    if(out == -1)
     break;
    baos.write(buff, 0, out);
   }

   is.close();

   if (baos.size() > 0) {
    request = URLDecoder.decode(baos.toByteArray().toString(), "UTF-8");
   } else {
    request = null;
   }

   StringBuilder buf = new StringBuilder();
   buf.append("<html><head><title>Simple HTTP Server !!</title></head><body>");
   buf.append("<p><pre>");
   buf.append(exchange.getRequestMethod() + " " + exchange.getRequestURI() + " " + exchange.getProtocol() + JavaServer.nl);

   Headers headers = exchange.getRequestHeaders();

   for (String name : headers.keySet()) {
    List<String> values = headers.get(name);
    for (String value : values) {
     buf.append(name + " --> " + value + JavaServer.nl);
    }
   }
   if (request != null) {
    buf.append(JavaServer.nl);
    buf.append(request);
   }

   buf.append("</pre></p>");
   buf.append("</body></html>\n");

   String response = buf.toString();

   Headers responseHeaders = exchange.getResponseHeaders();
   responseHeaders.set("Content-Type", "text/html");
   exchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, response.length());

   OutputStream res = exchange.getResponseBody();
   res.write(response.getBytes());
   res.close();
  }else
  {
   String response = "Bad request method !!";
   exchange.sendResponseHeaders(HttpURLConnection.HTTP_BAD_METHOD, response.length());
   OutputStream res = exchange.getResponseBody();
   res.write(response.getBytes());

   res.close();
  }
  exchange.close();
 }
}

Steps to run the above code

  1. Compile it using Oracle JDK 1.6
  2. Then execute this command on console (without quotes) 'Java JavaServer -p<port number> -a<ipaddress or localhost>' . For example, java JavaServer  -p5463 -a127.0.0.1
  3. Open your browser and type the URL. For example, http://127.0.0.1:5463/

You should see something like this (depends on the browser):


Monday, October 1, 2012

How to open a Java file in read-only mode?

In one of my eclipse plugin based application I wanted to open Java files in read only mode. One option was to use org.eclipse.jface.text.source.SourceViewer , where I could have used JavaSourceViewerConfiguration
for providing Java highlighting and all. But there were two problems:
  1. Source viewer won't inherit the Java editor settings (and if you have modified eclipse Java editor theme), which means your background and foreground in the SourceViewer gets completely messed up.
  2. Secondly you would lose all the markup and bookmarking facilities available with editors
So, I decided to extend the existing Java editor. The steps are extremely simple,
  1. Create an editor extension
  2. Extend the extension class with org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor
  3. Override some of the methods
  4. Open your file with this editor

Code

Editor Code

import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor;

@SuppressWarnings("restriction")
public class ReadonlyEd extends CompilationUnitEditor 
{
 public static final String ID = "read.only";
 public ReadonlyEd() {
 }
 @Override
 public boolean isEditable() {
     return false;
 }
 @Override
 public boolean isEditorInputModifiable() {
     return false;
 }
 @Override
 public boolean isEditorInputReadOnly() {
     return true;
 }
 @Override
 public boolean isDirty() {
     return false;
 }
}

Code for Invoking the Editor

IFile file = ...; // Get the Java file instance
IWorkbenchPage page = ...; // Get the workbench page
  
FileEditorInput input = new FileEditorInput(file);
try {
 IDE.openEditor(window.getActivePage(), input, ReadonlyEd.ID);
} catch (PartInitException e) {
 e.printStackTrace();
}

Tuesday, September 18, 2012

3 easy steps to self-sign a Applet Jar file

Found this link that explains how to self-sign an applet in 3 easy steps:
  1. keytool -genkey -keystore myKeyStore -alias me
  2. keytool -selfcert -keystore myKeyStore -alias me
  3. jarsigner -keystore myKeyStore jarfile.jar me

Thursday, August 23, 2012

Firebug Lite for SWT Browser on Windows

Recently I came across this question on stackoverflow 'Eclipse swt browser and firebug lite'. The solution seemed very obvious. I answered the question there also, you can always upvote it ;).

The output:


The code for the same is as follows:

import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class FirebugLite 
{
 public static void main(String[] args) {
  new FirebugLite().start();
 }
 
 public void start()
 {
  Display display = new Display();
  Shell shell = new Shell(display);
  shell.setLayout(new GridLayout(1, false));
  GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
  gridData.widthHint = SWT.DEFAULT;
  gridData.heightHint = SWT.DEFAULT;
  shell.setLayoutData(gridData);
  shell.setText("Firebug Lite for SWT ;)");
  
  final Browser browser = new Browser(shell, SWT.NONE);
  GridData gridData2 = new GridData(SWT.FILL, SWT.FILL, true, true);
  gridData2.widthHint = SWT.DEFAULT;
  gridData2.heightHint = SWT.DEFAULT;
  browser.setLayoutData(gridData2);
  
  Button button = new Button(shell, SWT.PUSH);
  button.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
  button.setText("Install");
  button.addSelectionListener(new SelectionAdapter() {
   public void widgetSelected(SelectionEvent e) {
    browser.setUrl("javascript:(function(F,i,r,e,b,u,g,L,I,T,E){if(F.getElementById(b))return;E=F[i+'NS']&&F.documentElement.namespaceURI;E=E?F[i+'NS'](E,'script'):F[i]('script');E[r]('id',b);E[r]('src',I+g+T);E[r](b,u);(F[e]('head')[0]||F[e]('body')[0]).appendChild(E);E=new%20Image;E[r]('src',I+L);})(document,'createElement','setAttribute','getElementsByTagName','FirebugLite','4','firebug-lite.js','releases/lite/latest/skin/xp/sprite.png','https://getfirebug.com/','#startOpened');");
   }
  });
  
  browser.setUrl("http://stackoverflow.com/questions/12003602/eclipse-swt-browser-and-firebug-lite");

  shell.open();
  while (!shell.isDisposed()) {
   if (!display.readAndDispatch())
    display.sleep();
  }
  display.dispose();
 }
}

Tuesday, July 31, 2012

SWT Browser and Image Capture

Recently I was playing with the SWT-COM bridge and its Win32 APIs. Believe me or not, but the SWT Browser is the best SWT based UI control I have seen (you can argue but without any success). 

One of the experimental feature I tried accomplishing was to print the full HTML page as Image, and the result was superb !!

See the below images for the embedded browser control and the output of the image capturing utility !! Cool right ;)

Modified Browser Control:




Captured Image:


Tuesday, May 1, 2012

SWT - Capturing Control Screen-Shot

SWT code for capturing control screen-shot.

public class ScreenCaptureTest 
{
 public static void main(String[] args) 
 {
  String[] names  = {"Harry", "Sally", "Jhon", "Tim", "Scott"};
  String[] msg = {"Hello World!", "Today is a nice day to walk", "I am bored", "This is how you take widget capture", "Ha Ha Ha!! That's funny !"}; 
  
  final Display display = new Display();
  final Shell shell = new Shell(display);
  shell.setText("Screen Capture");
  shell.setLayout(new GridLayout(1, true));
  
  final Composite composite = new Composite(shell, SWT.BORDER);
  composite.setLayout(new GridLayout(2, true));
  composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
  
  Table table = new Table(composite, SWT.BORDER|SWT.V_SCROLL|SWT.H_SCROLL|SWT.FULL_SELECTION);
  
  table.setLinesVisible(true);
  table.setHeaderVisible(true);
  
  table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
  
  TableColumn columnName = new TableColumn(table, SWT.LEFT);
  columnName.setText("Name");
  columnName.setWidth(100);
  
  TableColumn columnMsg = new TableColumn(table, SWT.LEFT);
  columnMsg.setText("Message");
  columnMsg.setWidth(200);
  
  for (int i = 0; i < 5; i++) 
  {
   TableItem item = new TableItem(table, SWT.NONE, 0);
   item.setText(0, names[i]);
   item.setText(1, msg[i]);   
  }
  
  StyledText text = new StyledText (composite, SWT.BORDER);
  text.setText("0123456789 ABCDEFGHIJKLM NOPQRSTUVWXYZ");
  text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
  
  StyleRange style1 = new StyleRange();
  style1.start = 0;
  style1.length = 10;
  style1.fontStyle = SWT.BOLD;
  text.setStyleRange(style1);
  
  StyleRange style2 = new StyleRange();
  style2.start = 11;
  style2.length = 13;
  style2.foreground = display.getSystemColor(SWT.COLOR_RED);
  text.setStyleRange(style2);
  
  StyleRange style3 = new StyleRange();
  style3.start = 25;
  style3.length = 13;
  style3.background = display.getSystemColor(SWT.COLOR_BLUE);
  text.setStyleRange(style3);
  
  Button button = new Button(shell, SWT.PUSH);
  button.setText("Capture");
  button.pack();

  button.addListener(SWT.Selection, new Listener()
  {
   public void handleEvent(Event event) 
   {
    GC gc = new GC(display);
    final Image image = new Image(display, shell.getBounds());
    gc.copyArea(image, shell.getBounds().x, shell.getBounds().y);
    gc.dispose();

    Shell popup = new Shell(shell);
    popup.setText("Captured Image");
    popup.addListener(SWT.Close, new Listener() {
     public void handleEvent(Event e) {
      image.dispose();
     }
    });

    Canvas canvas = new Canvas(popup, SWT.NONE);
    canvas.setBounds(0,0,image.getImageData().width, image.getImageData().height);
    canvas.addPaintListener(new PaintListener() {
     public void paintControl(PaintEvent e) {
      e.gc.drawImage(image, 0, 0);
     }
    });
    popup.pack();
    popup.open();
   }
  });
  
  shell.pack();
  shell.open();
  
  while (!shell.isDisposed()) {
   if (!display.readAndDispatch())
    display.sleep();
  }
  
  display.dispose();
 }
}

Original Composite:


Captured Image:

Wednesday, April 18, 2012

Programmatically create eclipse Java project

Following is a brief code snippet for creating an eclipse Java project using core JDT API.

private IJavaProject createProject() throws Exception
{
    IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
    String projName = getProjectName();

    if(projName == null || projName.trim().length() == 0)
        return null;

    //create eclipse project
    IProject project = root.getProject(projName);
    if(project.exists())
        project.delete(true, null);

    project.create(null);
    project.open(null);

    //set the java project nature
    IProjectDescription description = project.getDescription();
    description.setNatureIds(new String[] { JavaCore.NATURE_ID});
    project.setDescription(description, null);

    //create java project
    IJavaProject javaProject = JavaCore.create(project);

    //add bin/ouput folder
    IFolder binFolder = project.getFolder("bin");
    binFolder.create(false, true, null);
    javaProject.setOutputLocation(binFolder.getFullPath(), null);

    //add libs to project class path
    List<IClasspathEntry> entries = new ArrayList<IClasspathEntry>();
    IVMInstall vmInstall = JavaRuntime.getDefaultVMInstall();
    LibraryLocation[] locations = JavaRuntime.getLibraryLocations(vmInstall);
    for (LibraryLocation element : locations) {
        entries.add(JavaCore.newLibraryEntry(element.getSystemLibraryPath(), null, null));
    }
    
    javaProject.setRawClasspath(entries.toArray(new IClasspathEntry[entries.size()]), null);

    //create source folder
    IFolder sourceFolder = project.getFolder("src");
    sourceFolder.create(false, true, null);

    IPackageFragmentRoot srcRoot = project.getPackageFragmentRoot(sourceFolder);
    IClasspathEntry[] oldEntries = project.getRawClasspath();
    IClasspathEntry[] newEntries = new IClasspathEntry[oldEntries.length + 1];
    System.arraycopy(oldEntries, 0, newEntries, 0, oldEntries.length);
    newEntries[oldEntries.length] = JavaCore.newSourceEntry(srcRoot.getPath());
    project.setRawClasspath(newEntries, null);

    return javaProject;
}

private String getProjectName()
{
    String init_value = "project_" + System.currentTimeMillis();
    InputDialog dialog = new InputDialog(getShell(), "Java Project", "Provide project name ..", init_value, new IInputValidator() {
        public String isValid(String newText)
        {
            char[] array = newText.toCharArray();
            for (int i = 0; i < array.length; i++)
            {
                if(!Character.isJavaIdentifierPart(array[i]))
                    return "Cannot contain special characters !!";
            }

            IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
            IProject[] projs = root.getProjects();
            for (int i = 0; i < projs.length; i++) {
                if(projs[i].getName().equalsIgnoreCase(newText))
                    return "Project already exist !!";
            }

            /*
                Not checking for special Win32 names like con etc.
            */
            return null;
        }
    });

    if(dialog.open() == Dialog.CANCEL)
        return null;

    return dialog.getValue();
}

Wednesday, April 20, 2011

Testing SWT application with SWTBot

SWTBot is open-source Java based UI/functional testing tool for testing SWT and Eclipse based applications.

SWTBot provides APIs that are simple to read and write. The APIs also hide the complexities involved with SWT and Eclipse. This makes it suitable for UI/functional testing by everyone, not just developers. SWTBot also provides its own set of assertions that are useful for SWT. You can also use your own assertion framework with SWTBot.

There are many articles present for SWTBot for Eclipse Plug-in and RCP applications. Refer the following links for more details:
As the title suggest, the intention of this article to demonstrate the testing of a stand-alone SWT UI. There was a question asked  on the Stackoverflow with the same problem. You can checkout my answer there also. For completeness purpose I am posting it here too.

Well it is very much possible to test simple SWT application with SWTBot. Follow the step as mentioned below.
  1. Download SWTBot for SWT Testing
  2. Put it in the <eclipsehome>/dropins folder (although not required for non-plug-in projects)
  3. Restart your eclipse (not required if you adding the SWTBot jars in a simple Java project)
Now at this point you are ready to play with SWTBot.

For the demo purpose I have written a small Login dialog for you and it will look like this:


>>Code
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

public class SampleSWTUI 
{
   public Shell showGUI(final Display display)
   {
       Shell shell = new Shell(display);
       shell.setLayout(new GridLayout(3,true));
       shell.setText("Sample SWT UI");

       new Label(shell, SWT.NONE).setText("User Name: ");
       final Text nameText = new Text(shell, SWT.BORDER);
       nameText.setText ("");
       GridData data = new GridData(SWT.FILL, SWT.FILL, true, false);
       data.horizontalSpan = 2;
       nameText.setLayoutData(data);

       new Label(shell, SWT.NONE).setText("Password: ");
       final Text passwordText = new Text(shell, SWT.BORDER|SWT.PASSWORD);
       passwordText.setText ("");
       data = new GridData(SWT.FILL, SWT.FILL, true, false);
       data.horizontalSpan = 2;
       passwordText.setLayoutData(data);

       Button loginButton = new Button (shell, SWT.PUSH);
       loginButton.setText ("Login");
       data = new GridData(SWT.FILL, SWT.FILL, true, false);
       data.horizontalSpan = 3;
       loginButton.setLayoutData(data);
       loginButton.addSelectionListener(new SelectionAdapter(){
           public void widgetSelected(SelectionEvent e) {
                String user = nameText.getText();
                String password = passwordText.getText();

                System.out.println("\n\n\n");
                if(user.equals("Favonius") && password.equals("abcd123")){
                    System.out.println("Success !!!");
                }else {
                    System.err.println("What the .. !! Anyway it is just a demo !!");
                }                   
           }
       });

       shell.pack();
       shell.open();
       return shell;
   }

   public static void main(String [] args) 
   {
       Display display = new Display();
       Shell shell = new SampleSWTUI().showGUI(display);
       while (!shell.isDisposed()) {
           if (!display.readAndDispatch()) display.sleep();
       }

       display.dispose();
   }
}
Now create a JUnit test case (google for it if you are new to it) . Also add all the jar files present in SWTBot (the one you have downloaded) in your classpath.

Now first create a display (because application needs one). Also get the handle of container in which your widgets/controls are present. In my case it is the Shell. Although the below code is self descriptive, still, I will suggest you to refer its Javadoc.

>>SWTBot Code
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swtbot.swt.finder.SWTBot;
import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotButton;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotText;
import org.junit.Test;

import junit.framework.Assert;

public class SWTBotDemo 
{
    @Test
    public void test() 
    {
        SWTBotPreferences.PLAYBACK_DELAY = 100; // slow down tests...Otherwise we won't see anything
  
        Display display = new Display();
        Shell shell = new SampleSWTUI().showGUI(display);
        SWTBot bot = new SWTBot(shell);
  
        SWTBotButton loginButton = bot.button("Login");
        SWTBotText userText = bot.textWithLabel("User Name: ");
        SWTBotText passwordText = bot.textWithLabel("Password: ");
  
        userText.setFocus();
        userText.setText("Superman");
  
        Assert.assertEquals(userText.getText(),"Superman");
  
        passwordText.setFocus();
        passwordText.setText("test123");
  
        Assert.assertEquals(passwordText.getText(),"test123");
  
        loginButton.setFocus();
        loginButton.click(); 
  
  
        userText.setFocus();
        userText.setText("Favonius");
  
        Assert.assertEquals(userText.getText(), "Favonius");
  
        passwordText.setFocus();
        passwordText.setText("abcd123");
  
        Assert.assertEquals(passwordText.getText(), "abcd123");
  
        loginButton.setFocus();
        loginButton.click();
        
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) display.sleep();
        }

        display.dispose();
    }
}
Now all the SWTBot methods and variables are well defined in the source and the source is bundled within the SWTBot jars. So you can always go ahead and hack its source code.

>>Further Reading
  1. SWTBot FAQ

Monday, April 18, 2011

Detecting change in SWT Table's scrollbar visibility

Recently on stackoverflow there was a question asked related to this. The requirement was simple ‘resize all the columns as soon as scrollbar appears or disappears’. Now, if you look deep into the SWT table API then you will notice that there is no direct solution for this because:
  1. There is no way to get the scrollbar handle
  2. Scrollbar does not support any event related to visibility
One can solve this problem by implementing a simple hack. I am using the concept presented in this SWT snippet compute the visible rows in a table. Along with that I am also using SWT Paint Event.

The basic concept is as follows:
  1. Calculate the number of visible rows (items).
  2. Compare it with total number of rows (items).
  3. Do all this in some event which occurs with the addition of rows (items). I have chosen the SWT Paint Event
>> Code
import org.eclipse.swt.*;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

public class TableScrollVisibilityTest 
{
    private static int count;

    public static void main(String [] args) 
    {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setBounds(10,10,300,300);
        shell.setLayout(new GridLayout(2,true));

        final Table table = new Table(shell, SWT.NONE);
        GridData data = new GridData(GridData.FILL_BOTH);
        data.horizontalSpan = 2;
        table.setLayoutData(data);

        count = 0;

        final Button addItem = new Button (shell, SWT.PUSH);
        addItem.setText ("Add Row");
        data = new GridData(SWT.FILL, SWT.FILL, true, false);
        data.horizontalSpan = 2;
        addItem.setLayoutData(data);

        final Text text = new Text(shell, SWT.BORDER);
        text.setText ("Vertical Scroll Visible - ");
        data = new GridData(SWT.FILL, SWT.FILL, true, false);
        data.horizontalSpan = 2;
        text.setLayoutData(data);


        addItem.addListener (SWT.Selection, new Listener () 
        {
            public void handleEvent (Event e) 
            {
                new TableItem(table, SWT.NONE).setText("item " + count);
                count++;
            }
        });


        table.addPaintListener(new PaintListener() {
            public void paintControl(PaintEvent e) {
                Rectangle rect = table.getClientArea ();
                int itemHeight = table.getItemHeight ();
                int headerHeight = table.getHeaderHeight ();
                int visibleCount = (rect.height - headerHeight + itemHeight - 1) / itemHeight;
                text.setText ("Vertical Scroll Visible - [" + (table.getItemCount()>= visibleCount)+"]");

                      // YOUR CODE HERE
            }
        });


        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) display.sleep();
        }

        display.dispose();
    }

}

>> Output
For itemcount < numberofvisible rows


For itemcount >= numberofvisible rows


Note - If you are going to use the paint event then try keep the calculations minimum as it is called frequently.

Saturday, April 16, 2011

SWT Browser and Javascript

Sometime we feel the need of modifying SWT browser content dynamically. Using getText and modifying it is not the advisable way of changing HTML content. I will suggest you to use execute() method of org.eclipse.swt.browser.Browser. It allows you to fire javascripts on the DOM object of the page.

>> Example
Here in this code I am allowing the page to fully load and then looking for all the links item and then creating a red border around them.

import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.LocationEvent;
import org.eclipse.swt.browser.LocationListener;
import org.eclipse.swt.browser.ProgressEvent;
import org.eclipse.swt.browser.ProgressListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;

public class BrowserTest 
{
 private static Browser browser;

 public static void main(String [] args) 
 {
  Display display = new Display();
  final Shell shell = new Shell(display);
  GridLayout gridLayout = new GridLayout();
  gridLayout.numColumns = 3;
  shell.setLayout(gridLayout);

  createBrowser(shell);

  browser.addProgressListener(new ProgressListener() 
  {
   public void changed(ProgressEvent event) {
   }
   public void completed(ProgressEvent event) {
    changeSomething();
   }
  });

  shell.open();
  browser.setUrl("http://google.com");

  while (!shell.isDisposed()) {
   if (!display.readAndDispatch())
    display.sleep();
  }
  display.dispose();
 }

 protected static void changeSomething() 
 {
  String s = "var allLinks = document.getElementsByTagName('a'); " +
    "for (var i=0, il=allLinks.length; i<il; i++) { " +
     "elm = allLinks[i]; elm.style.border = 'thin solid red';" +
    "}";

  System.out.println(browser.execute(s));
 }

 private static void createBrowser(Shell shell) 
 {
  ToolBar toolbar = new ToolBar(shell, SWT.NONE);
  ToolItem itemGo = new ToolItem(toolbar, SWT.PUSH);
  itemGo.setText("Go");

  GridData data = new GridData();
  data.horizontalSpan = 3;
  toolbar.setLayoutData(data);

  Label labelAddress = new Label(shell, SWT.NONE);
  labelAddress.setText("Address");

  final Text location = new Text(shell, SWT.BORDER);
  data = new GridData();
  data.horizontalAlignment = GridData.FILL;
  data.horizontalSpan = 2;
  data.grabExcessHorizontalSpace = true;
  location.setLayoutData(data);

  try {
   browser = new Browser(shell, SWT.NONE);
  } catch (SWTError e) {
   System.out.println("Could not instantiate Browser: " + e.getMessage());
   //display.dispose();
   return;
  }
  data = new GridData(SWT.FILL, SWT.FILL, true, true);
  data.horizontalSpan = 3;
  browser.setLayoutData(data);

  /* event handling */
  Listener listener = new Listener() 
  {
   public void handleEvent(Event event) 
   {
    ToolItem item = (ToolItem)event.widget;
    String string = item.getText();
    if (string.equals("Go")) browser.setUrl(location.getText());
   }
  };

  browser.addLocationListener(new LocationListener() {
   public void changed(LocationEvent event) {
    if (event.top) location.setText(event.location);
   }
   public void changing(LocationEvent event) {
   }
  });


  itemGo.addListener(SWT.Selection, listener);
  location.addListener(SWT.DefaultSelection, new Listener() {
   public void handleEvent(Event e) {
    browser.setUrl(location.getText());
   }
  });  
 }
}
>>Output


>> Further Reading
  1. Eclipse Article
  2. SWT Snippets