How to write completely custom widgets recognizable by GWT Designer? - gwt

When I add let's say, a standard GWT VerticalPanel, with GWT Designer I can add widgets to this panel by drag and dropping them. GWT Designer provides a red line indicating I am adding a widget to my VerticalPanel.
Suppose that I want to create my own panel from scratch, and I don't want to extend standard GWT panels. I want GWT Designer to recognize my panel and provide the same functionality it provides when I use standard gwt panels.
As far as I know frameworks such as Ext-GWT wrote their widget libraries from scratch and yet they work in unison with GWT Designer. Do I need to implement certain methods in my custom panel to achieve this functionality? Any guidance or ideas are well appreciated.
Thank you

To summarize, support for a new component requires adding special support for this component into GWT Designer. Assume I have a custom component which I want it to act like a VerticalPanel but which infact is type composite :
public class CustomPanel extends Composite implements HasWidgets{
private VerticalPanel panel = new VerticalPanel();
public CustomPanel() {
initWidget(panel);
}
#Override
public void add(Widget w) {panel.add(w);}
#Override
public void clear() {panel.clear();}
#Override
public Iterator<Widget> iterator() {return panel.iterator();}
#Override
public boolean remove(Widget w) {return panel.remove(w);}
}
This will work as a VerticalPanel, but when you are looking from the Designers perspective this still is a Composite. As a result you can not drop widgets inside it. In the simplest case, what you should do to make it designer friendly is to create a CustomPanel.wbp-component.xml in the same package of CustomPanel following given name convention. A simple one to give flow like widget adding behaviour would be,
<?xml version="1.0" encoding="UTF-8"?>
<component xmlns="http://www.eclipse.org/wb/WBPComponent">
<description>This is a simple Composite acting like VerticalPanel</description>
<!-- CREATION -->
<creation>
<source><![CDATA[new org.test.client.CustomPanel()]]></source>
</creation>
<parameters>
<parameter name="flowContainer">true</parameter>
<parameter name="flowContainer.horizontal">false</parameter>
<parameter name="flowContainer.association">%parent%.add(%child%)</parameter>
</parameters>
</component>
After adding this step your composite should be treated like a vertical panel (dropping widgets inside support) by the gwt designer as well. When this XML alone is not enough, meaning you need some behavior more of a complex nature, you need to start writing java model classes that defines custom behaviour of your component to Designer and reference it in your component xml using <model> tag. In this case you need to write a plugin to host your models and policies.
Here are the references for this summary and useful links:
Google groups question answered by WindowBuilder team
http://code.google.com/intl/tr-TR/javadevtools/wbpro/DesignerCustomizationAPI.pdf
http://code.google.com/intl/tr-TR/javadevtools/wbpro/NewComponentsTutorial.pdf
http://en.wikipedia.org/wiki/MVEL

GWT Designer documentation have a page about custom composites and panels but these pertain to Swing and SWT components. As for GWT, the documentation recommends using GWT's layout managers for maximum portability.

Related

Using mgwt for desktop and mobile applications

I have an application written in GWT. I want to be able to provide a subset of the same application for use when the site is opened in mobile browsers, and have been looking at mgwt as a way of achieving this.
The way I am expecting it to work is that I will augment my existing GWT application project with mgwt code (with some logic sharing) resulting in two entry points. My question is how to manage this given a single html page? I have seen the approach described in this article and was wondering whether that will work well with mgwt or whether there should be another pattern I should be considering?
I don't think you need 2 entry points. As kiran said above, you should reuse all the code except the view components. In case you used the GWT Activities and Places module, the view components should be completely decoupled from the rest of the code.
In this case you can use the the GWT.create method associated with the correct definitions in the module xml definition:
//in your entry point:
private IClientFactory clientFactory = GWT.create(IClientFactory.class);
//in your module xml definition:
<replace-with class="com.vv.xui.client.DesktopClientFactory">
<when-type-is class="com.vv.xui.client.IClientFactory" />
<when-property-is name="formfactor" value="desktop"/>
</replace-with>
<replace-with class="com.vv.xui.client.MobileClientFactory">
<when-type-is class="com.vv.xui.client.IClientFactory" />
<when-property-is name="formfactor" value="mobile"/>
</replace-with>
The form formfactor property can be defined as in this example:
https://code.google.com/p/gwt-cx/source/browse/trunk/gwtcx/gwtcx-core/gwtcx-core-client/src/main/resources/com/gwtcx/FormFactor.gwt.xml
In your IClientFactory you will have something like this:
public interface IClientFactory {
IHomeView getHomeView();
ISearchView getSearchView();
...
}
Where IHomeView and ISearchView are the view interfaces implemented by the desktop and the mobile versions. In my case the View implementations are UiBinder components that implement the associated view interface.
In your DesktopClientFactory you will have something like this:
public class DesktopClientFactory implements IClientFactory {
private static final ISearchView searchView = new com.vv.xui.client.view.desktop.SearchView.SearchView();
#Override
public ISearchView getSearchView() {
return searchView;
}
...
}
In this way you don't need different entry points for mobile and desktop and can share all the code except the view components.
That pattern in the link pointing to MobileWebApp on googlecode is correct. Basically you have UI view interfaces in GWT which stick to MVP pattern recommended on GWT. Then you can do different implementations of the UI Views based on the screen resolutions available. Obviously you don't want the same screen lay outs on desktop and mobile. So you will need to redesign your views for different form factors and then call the correct implementations based on the form factor the device. Since you already have a gwt application, you can create views for mobile using mgwt and reuse the code that you already created. But still you will have to create new views for mobile using mgwt, it wont be a straight forward replace.

GWT: formfactor dependent editor

I'm developing a web app for different formfactors. Each has its own client factory to create formfactor dependent views. Everythings works fine so far but I'm stuck when it comes to the Editor Framework.
To make use of the framework I have to declare a marker interface like so:
interface Driver extends SimpleBeanEditorDriver<User, UserEditor> {}
Since this happens in my formfactor agnostic activity I want the type UserEditor to refer to the actual implementation based on the formfactor, i.e. UserEditorPhone, UserEditorTablet, UserEditorYouNameIt.
To no avail I tried using deferred binding in module.gwt.xml:
<replace-with class="com.example.client.desktop.UserEditorDesktop">
<when-type-is class="com.example.client.view.UserEditor"/>
</replace-with>
Any ideas on what I'm missing and how to avoid having a one-to-one-relationship between formfactors and UserEditor-activities?
You'll want your formfactor-agnostic activity to only know about SimpleBeanEditorDriver<User, ?>, and move the Driver interface into each one of UserEditorDesktop, UserEditorTable and UserEditorPhone.
The activity will then ask a formfact-dependent object (e.g. its view, if you use MVP and the activity is the presenter) for an instance of the editor driver rather than using GWT.create() directly.
(I can give code sample if you detail how your code is organized: are you using MVP? is the editor your view? how's it instantiated? etc.)

SWT Controls with predefined styles

I want to have in my SWT project controls (Button-s, Text-s, etc) with predefined styles. My first idea was to extend for example org.eclipse.swt.widgets.Text class, set some settings and use that new classes instead of original, but get org.eclipse.swt.SWTException: Subclassing not allowed exception. How to do that right ?
You have to override checkSubclass method to do nothing, otherwise it will complain that subclassing not allowed - because usually you shouldn't really override standard components.
#Override
protected void checkSubclass() {
// Disable the check that prevents subclassing of SWT components
}
You also should consider building custom widgets containing primitive controls using delegation. For example you can build MyText which will contain Text widget inside with custom setup.
Thing to remember is SWT provides standard controls which looks natively on each on platform. Anyway polishing standard components is still allowed and even a must in production software.
See the SWT Faq for this concern. There you'll find also a link howto write custom widgets

GWT integration with SmartGWT - Cant select text SectionStack->Section->Canvas->HTML

we've used a combination of GWT and smart gwt to add some features to an app we've built.
The problem I have is that we decided to make use of the accordion functionality (SectionStack's) that SmartGWT offers and we are nesting our stock gwt widget inside a canvas and then nesting that inside the section stack. E.G
SectionStack(SmartGWT)->Section(SmartGWT)->Canvas (SmartGWT)->VerticalPanel(GWT) -> Other GWT Widgets (HTML, labels etc)
Before we mixed GWT and SmartGWT it was possible to select text in the standard GWT widgets and then copy and paste etc. Nesting the GWT widgets in the SmartGWT canvas means this is now not possible. Can anyone offer an explanation why this is the case and/or a solution on how to fix it.
I've tried canvas.setCanSelectText(true); but this doesn't seem to do anything either.
We're using GWT 2.1 with SmartGWT 2.2. The demo app using SmartGWT2.2 seems to exhibit the same problem over at http://www.smartclient.com/smartgwt/showcase/#featured_gwt_integration . I've also tried GWT 2.0.x with SmartGWT 2.2
Any help appreciated.
For those interested I've managed to find a bug registered for this at : code.google.com/p/smartgwt/issues/…
Actually it is not an issue. You have to call the setCanSelectText method on the WidgetCanvas wich is wrapping your GWT widget. The WidgetCanvas is created in the addItem(Widget) method. One way to go is to override the addItem method like this:
#Override
public void addItem(Widget widget) {
if (widget instanceof Canvas) {
addItem((Canvas) widget);
} else {
WidgetCanvas wg = new WidgetCanvas(widget);
wg.setCanSelectText(true);
addItem(wg);
}
}

Adding Content to a GWT Horizontal Panel from another class

I am trying to populate the right-hand-side of a HorizontalPanel used in an onModuleLoad() method from another class (containing other widgets) so to keep the code separate.
What I am trying to achieve is similar to a PHP include where I can alter the code in another class and it will affect the right-hand panel only.
Does this other class have to be a composite widget? Or can I do a similar thing that I do when creating the Entry class?
I'm not sure if you mean you want to load a complete different GWT module on the right-hand panel or simply want to load a different class. I assume the latter.sense.
In such case a GWT TabPanel, but positioned Vertical. This is a combination of a DeckPanel and a TabBarPanel. In GWT there is standard VerticalTabPanel available, but you can find one in the open source cobogw library, see http://www.cobogw.org. An example including source code can be found on the demo page: http://cobogw.googlecode.com/svn/demo/WidgetsDemo.html#VerticalTabPanel
The example also uses a LazyPanel. This means each class is initialized only when the user clicks on the link, which makes startup a lot faster.
Just add the reference to the horizontalpanel to some other class (like a controller class or main panel class) and then call into this class from your right side panel. You can even have a controller class that holds this static horizontalpanel with a method like
HorizontalPanel hPanel; //set this from on module load, or controller.create method for instance
public static setRightContents(Panel panel){
hPanel.add(panel)
}
and just call this from the other class Controller.setRightContents(myNewRightPanel).
Really you just need to stop thinking this is a website and start thinking more of a thick client application using even driven programming.