Jump to: navigation, search

Difference between revisions of "Albireo Documentation"

m
m (Multiple Event Threads)
 
Line 149: Line 149:
 
With Albireo, just as with the SWT_AWT bridge, application code that deals with the SWT part of the UI must be executed in the SWT event thread, and code that touches the Swing part of the UI must be executed in the AWT/Swing event thread.
 
With Albireo, just as with the SWT_AWT bridge, application code that deals with the SWT part of the UI must be executed in the SWT event thread, and code that touches the Swing part of the UI must be executed in the AWT/Swing event thread.
  
As explained in the [http://www.eclipse.org/articles/article.php?file=Article-Swing-SWT-Integration/index.html#sec-event-threads Eclipse Corner article], <tt>Display.syncExec</tt> and <tt>SwingUtilities.invokeLater</tt> should be avoided, because they have a high probability of introducing deadlocks. Use <tt>Display.asyncExec</tt> (or its convenience wrapper <tt>ThreadingHandler.asyncExec</tt>) and <tt>SwingUtilities.invokeLater</tt> (or equivalently, <tt>java.awt.EventQueue.invokeLater</tt>) instead.
+
As explained in the [http://www.eclipse.org/articles/article.php?file=Article-Swing-SWT-Integration/index.html#sec-event-threads Eclipse Corner article], <tt>Display.syncExec</tt> and <tt>SwingUtilities.invokeAndWait</tt> should be avoided, because they have a high probability of introducing deadlocks. Use <tt>Display.asyncExec</tt> (or its convenience wrapper <tt>ThreadingHandler.asyncExec</tt>) and <tt>SwingUtilities.invokeLater</tt> (or equivalently, <tt>java.awt.EventQueue.invokeLater</tt>) instead.

Latest revision as of 11:52, 23 June 2008

The Basics

How do you create an SWT control that encapsulates a Swing component? If you use the SWT_AWT bridge by hand, you have to deal with too many details. With Albireo, you instantiate one class, implementing abstract methods, and that's it.

The simplest example is this:

import org.eclipse.albireo.core.SwingControl;
...
Control c =
  new SwingControl(parent, SWT.NONE) {
    protected JComponent createSwingComponent() {
      return new JLabel("hi, i'm swinging");
    }
    public Composite getLayoutAncestor() {
      return parent;
    }
  };

SwingControl is the class that does all the work. In this example, our subclass of SwingControl is an anonymous inner class.

SwingControl's constructor takes two arguments, like most SWT components do: The parent control, to which the new control is added as child when it is created, and a set of ORed flags. In the flags, you need not pass SWT.EMBEDDED; just pass the flags that are relevant to you (usually SWT.NONE will do).

You need to implement at least two methods: createSwingComponent and getLayoutAncestor.

createSwingComponent is the method which creates the Swing component. You don't pass a ready-made Swing component as a constructor argument; instead you create it here. The SwingControl class takes care to call this creation method in the right thread (the AWT event thread) and to attach it in the right place of the control/component hierarchy.

getLayoutAncestor is the method with which you designate which control should be layout()ed when the preferred size of the Swing component changes. Usually it us the parent argument that you passed as first constructor argument. But it can also be the parent's parent.

Using Albireo in your application

You can use Albireo while developing both Eclipse plug-ins (for the IDE or the Rich Client Platform) and standalone SWT applications. The current version of Albireo is available from the Albireo Download page. Zip files available for both modes of development.

Eclipse plug-in development

The Albireo code and some examples are available from the download page as Eclipse plug-ins so it is easy to use it as part a plug-in based application. After downloading the org.eclipse.albireo.rcp distribution, install it to either your workspace or PDE target as described on the Albireo Installation page.

Once the Albireo core plug-in is part of your runtime environment, you can add dependencies to it from your own plug-ins. (Open your plugin.xml or MANIFEST.MF file, click on the Dependencies tab, and add org.eclipse.albireo.core.)

Then, for example, if you want to create a simple Eclispe view that embeds a Swing Table, your view's implementation would look something like this.

public class MyView extends ViewPart {

    private SwingControl swingControl;
    
    public void createPartControl(final Composite parent) {
        swingControl = new SwingControl(parent, SWT.NONE) {
            protected JComponent createSwingComponent() {
                Vector rows = new Vector();
                Vector columns = new Vector();
                
                ... fill in the rows and columns
                
                JTable table = new JTable(rows, columns);
                table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
                table.createDefaultColumnsFromModel();
                
                JScrollPane scrollPane = new JScrollPane(table);
                scrollPane.setBorder(new EmptyBorder(0,0,0,0));
                
                return scrollPane;
            }

            public Composite getLayoutAncestor() {
                return parent;
            }
            
        };
    }

    public void setFocus() {
        swingControl.setFocus();
    }

}

The Albireo RCP distribution includes an examples plug-in, org.eclipse.albireo.examples.plugin with several examples of views with embedded Swing controls.

Standalone SWT application development

Albireo is also available from the download page as as a Java project archive so it can be used as part of a standalone, SWT-based application. After downloading the org.eclipse.albireo.standalone distribution, import it to your workspace as described on the Albireo Installation page.

To use Albireo in your standalone application, simply add it to the project dependencies of your Java project. (Right-click on your project, select Build Path -> Configure Build Path..., click on the Projects tab, and add org.eclipse.albireo.core.) From your Java project you can then write code to embed Swing controls in your application. Here's a simple example:

public class EmbeddedJTable {

    /**
     * @param args
     */
    public static void main(String[] args) {
        final Display display = new Display();
        final Shell shell = new Shell(display);
        shell.setLayout(new FillLayout());

        SwingControl control = new SwingControl(shell, SWT.NONE) {
            protected JComponent createSwingComponent() {
                return createTable();
            }

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

    private static JComponent createTable() {
        /* Creating components */
        int nrows = 1000, ncolumns = 10;
        Vector rows = new Vector();
        for (int i = 0; i < nrows; i++) {
            Vector row = new Vector();
            for (int j = 0; j < ncolumns; j++) {
                row.addElement("Item " + i + "-" + j);
            }
            rows.addElement(row);
        }
        Vector columns = new Vector();
        for (int i = 0; i < ncolumns; i++) {
            columns.addElement("Column " + i);
        }
        JTable table = new JTable(rows, columns);
        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        table.createDefaultColumnsFromModel();
        JScrollPane scrollPane = new JScrollPane(table);
        return scrollPane;
    }

}

The Albireo Standalone distribution includes an examples project, org.eclipse.albireo.examples with an example similar to the one above. We hope to add more in the future.

Customizing ...

TBD

Multiple Event Threads

With Albireo, just as with the SWT_AWT bridge, application code that deals with the SWT part of the UI must be executed in the SWT event thread, and code that touches the Swing part of the UI must be executed in the AWT/Swing event thread.

As explained in the Eclipse Corner article, Display.syncExec and SwingUtilities.invokeAndWait should be avoided, because they have a high probability of introducing deadlocks. Use Display.asyncExec (or its convenience wrapper ThreadingHandler.asyncExec) and SwingUtilities.invokeLater (or equivalently, java.awt.EventQueue.invokeLater) instead.