Tom has posted 7 posts at DZone. View Full User Profile

E4 – A New Area For RCP/RIA Applications

07.03.2009
| 9605 views |
  • submit to reddit

I’m on the road to prepare my example for the E4 talk I’m delivering on the Eclipse-Developers-Day in Karlsruhe and I have to say that in my eyes E4 is going to open up a new world for Eclipse-RCP-Developers.

Though RCP-Applications written in 3.x might not look too bad no one can deny that the UI-Design is coming from an IDE background and compared to modern Web-UIs it looks boring (which is not a bad thing per se for business applications). The problem in 3.x is that it is very hard to impossible to change the L&F of your application.

E4 provides different multiple solutions to fix the L&F:

  1. Declarative-Styleing through CSS
  2. The possibility to define your own renderes to exchange Widget A through Widget B if CSS is not enough to theme your application

To demostrate what you can achieve when you combine the 1st and 2nd possibility I create a small screencast

where you see the famous E4-Photo-Application revamped

E4 Photo Demo

A second example application is our E4-Contacts-Demo created and maintained by Kai Tödter which shows advanced css-styles like radial gradients.

Contacts Demo

I use this application to show you another nice thing you can do with E4’s declarative styling support. You can adjust the styling of your application while it is running so that you can experiment with various font and color settings WITHOUT shutting down your application.

If all this would not be enough you can run the unmodified code (please take this literally) from the example application above in your browser using the RAP-Framework.

E4-Rap-Screenshot

If you are interested in E4 and what’s going on behind the scenes of the next major Eclipse-Release I hope to see you in Karlsruhe on Tuesday July 7th.

Published at DZone with permission of its author, Tom Schindl.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Ronald Miura replied on Fri, 2009/07/03 - 6:18am

So, in the end, SWT just turns into Swing? :P

Tom Schindl replied on Fri, 2009/07/03 - 6:36am

It gives the developer the possibility to customize it if he wants to. Please note that all shown above is done using the CURRENT SWT-API no extra stuff was added to make this work.

Rajat Gupta replied on Fri, 2009/07/03 - 11:43am

I don't understand the value of creating so many UI toolkits.  When we started creating PAW (a end-user focused product for data processing) using Eclipse ECP, we used all the normal SWT widgets and other Eclipse paradigms (perspectives, views, etc..).  The feedback I constantly received was it was too difficult to understand how to get started - the UI didn't guide the user towards anything. 

Ultimately, we started to think of the user experience from a web based paradigm and made the product a whole lot simpler.  In terms of UI,auto-expanding sections, flow layout, additional explanatory text - these things are much more natural in a web paradigm and users need it.  SWT doesn't provide good support for this and the effort in E4 with CSS is also an effort to fill some of these gaps.  We ended up using a web UI, with creating our own widget classes keeping to the APIs of the SWT classes (that we were using) but bound to browser based widgets using Mozilla XPCOM. 

I think ultimately with E4 (or E5) you're going to try to recreate all the layout flexibility that a browser provides.  My view is that it would be a better choice to model SWT widgets over the browser (allowing the platform developer to extend an HTML page) rather than creating another widget language and another widget framework.

 

Miller Roger replied on Fri, 2009/07/03 - 7:24pm

Hello, I will be at the Eclipse-Developers-Day in Karlsruhe and i am looking forward to your presentation. If e4 and RAP can collaborate to have a single way for css styling, it would be great. So we can use the same CSS file for RCP and RAP application.

Tom Schindl replied on Sat, 2009/07/04 - 3:55am in response to: Rajat Gupta

I think you didn't understood what I was trying to say:

  1. We are not creating a new UI-Toolkit
  2. We rewrite the Workbench-Framework to make it useable with every widget technology you want giving you the freedom to choose your favorite technology (SWT, Qt, Swing, you name it).
  3. The core Workbench-Framework provides services and stuff every application needs like:
    * Commands
    * Restoring the current workbench state on restart
    * glueing together the different parts of your application
    * ...
Out of curiosity is the SWT on XPCOM available to the public because it might interesting to see what one can do with it for example in a client-serversplit scenario

Chetan Sachdev replied on Mon, 2009/07/06 - 10:04am

@Tom

Can I make use of Flash/Flex content to create widgets. Is it possible to have a flash player integration with it ?

Tom Schindl replied on Mon, 2009/07/06 - 5:00pm in response to: Chetan Sachdev

You can in theory use any widget technology you want (At EclipseCon I demonstrated an application running on Qt) when it comes to an Flash/Flex application you need to make the cross compilation to ActionScript of the core bits who are written in Java or make all the stuff run in Java.

Rajat Gupta replied on Tue, 2009/07/07 - 1:44am

I'll try to post a snippet of what we ended up doing... The other thing that I realized along the way with PAW was that initially I was trying to be a standard Windows app, until I realized that there was no more a standard windows app (look at Windows Media Player, MS Office/ribbon UI, Yahoo Messenger, AOL Messenger, etc...).  So the idea behind SWT was to expose Windows widgets (with the window L&F) to the Java developer is no longer as desirable as it was when the UI across applications was still pretty standard. So my view is that perhaps we should pick the new 'best' UI toolkit and make that a first-class citizen - in any case, providing CSS styling means that we're extending the underlying UI toolkits or creating an entirely new one.

 

Here's an example of a SWT API like wrapper to a browser hosted control.

public class Text implements IBrowserBasedWidget {
    nsIDOMHTMLInputElement        input;
    nsIDOMEventListener            listener;
    ArrayList<IEventHandler>    changeListeners    = new ArrayList<IEventHandler>();
    ArrayList<IEventHandler>    focusListeners    = new ArrayList<IEventHandler>();
    Object                        data;

    public Text() {}
    public Text(nsIDOMElement elem) {
        init(elem);
    }
   
    public String getText() {
        return input.getValue();
    }

    public void setText(String text) {
        if (text == null)
            text = "";
        input.setValue(text);
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
   
    public String getId() {
        return input.getId();
    }


    @Override
    public void addListener(EventType type, IEventHandler handler) {
        if (listener == null) {
            listener = new nsIDOMEventListener() {
                @Override
                public void handleEvent(nsIDOMEvent event) {
                    EventData ed = new EventData();
                    ed.widget = Text.this;
                    if (event.getType().compareToIgnoreCase("change") == 0) {
                        ed.type = EventType.change;
                        for (IEventHandler handler : changeListeners)
                            handler.handleEvent(ed);
                    }
                    else if (event.getType().compareToIgnoreCase("focus") == 0){
                        ed.type = EventType.focus;
                        for (IEventHandler handler : focusListeners)
                            handler.handleEvent(ed);
                    }
                }

                @Override
                public nsISupports queryInterface(String classId) {
                    return Mozilla.queryInterface(this, classId);
                }
            };
            nsIDOMEventTarget eventTarget = (nsIDOMEventTarget) input
                    .queryInterface(nsIDOMEventTarget.NS_IDOMEVENTTARGET_IID);
            eventTarget.addEventListener("change", listener, false);
            eventTarget.addEventListener("focus", listener, false);
        }

        if (type == EventType.change)
            changeListeners.add(handler);
        else if (type == EventType.focus)
            focusListeners.add(handler);
    }
   
    public void dispose() {
        nsIDOMEventTarget eventTarget = (nsIDOMEventTarget) input
                .queryInterface(nsIDOMEventTarget.NS_IDOMEVENTTARGET_IID);
        eventTarget.removeEventListener("change", listener, false);
        eventTarget.removeEventListener("focus", listener, false);

        changeListeners.clear();
        focusListeners.clear();
    }

    @Override
    public boolean init(nsIDOMElement element) {
        this.input = (nsIDOMHTMLInputElement) element
                .queryInterface(nsIDOMHTMLInputElement.NS_IDOMHTMLINPUTELEMENT_IID);
        return false;
    }

    @Override
    public void removeListener(EventType type, IEventHandler handler) {
        if (type == EventType.change)
            changeListeners.remove(handler);
        else if (type == EventType.focus)
            focusListeners.remove(handler);
    }
 }

 

Here's an example of a viewer (note that themethods aren't exactly the same but very similar).

public class ListViewerAdapter {
    int numColumns;
    IStructuredContentProvider contentProvider;
    LabelProvider labelProvider;
    List list;
    Object input;
   
    public ListViewerAdapter(List list) {
        this.list = list;
    }
   
    public void setContentProvider (IStructuredContentProvider provider) {
        this.contentProvider = provider;
    }

    public void setLabelProvider(LabelProvider provider) {
        this.labelProvider = provider;
    }
   
    public void setInput(Object input) {
        this.input = input;
        refresh();
    }
   
    public ISelection getSelection() {
        nsIDOMNodeList items = list.getUnderlyingList().getChildNodes();
        Object[] dataItems = contentProvider.getElements(input);
        if (dataItems == null)
            return null;
       
        for (int i = 0; i < items.getLength(); i++) {
            nsIDOMNode node = items.item(i);
            nsIDOMNode selector = node.getFirstChild();
            nsIDOMHTMLInputElement selectElem = (nsIDOMHTMLInputElement) selector.queryInterface(nsIDOMHTMLInputElement.NS_IDOMHTMLINPUTELEMENT_IID);
            if (selectElem.getChecked()) {
                if (dataItems.length > i)
                    return new StructuredSelection(dataItems[i]);
                else
                    return null;
            }
        }
        return null;       
    }
   
    public void refresh() {
        list.removeAll();
       
        Object[] items = contentProvider.getElements(input);
        if (items == null || items.length == 0)
            return;
   
        for (int i = 0; i < items.length; i++) {
            String value = labelProvider.getText(items[i]);
            list.add(value);
        }
    }

}
 

I'll be happy to share more if it's useful, this isn't the core of our product.

Thanks,
Rajat

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.