Creating a Custom UI Widget
This page attempts to describe the code needed to create a new UI Widget using the Ext GWT (GXT) toolkit. Our widgets follow a Model-View-Presenter format that isolates business logic of the widget in a Presenter and the view implementation in a ViewImpl. You will need to create three files, prefereably in an appropriate sub package of org.sagebionetworks.web.client.widget
To use a widget like this, follow these steps:
Steps
- Create your widget classes using the templates below.
- Write a test for your Presenter if you write business logic into it.
- In the PortalGinModule class, force your ViewImpl to be a Singleton and bind the ViewImpl to its View
//EntityChildBrowser bind(EntityChildBrowserViewImpl.class).in(Singleton.class); bind(EntityChildBrowserView.class).to(EntityChildBrowserViewImpl.class);
- Inject the Presenter class into the class that you're using. This automatically injects the ViewImpl into the presenter, and you have a fully ready object. When you want to add this to a UiBinder class, simply add it to a SimplePanel
- In your UiBinder (ui.xml) file
<g:SimplePanel ui:field="editorPanel" />
- In your ViewImpl class
@UiField SimplePanel adminPanel; @Inject public SomeViewImpl(..., EntityChildBrowser broswer) { adminPanel.add(datasetEditor); }
Widget MVP Templates
Presenter
The presenter stores the business logic. This is where your widget would, say, make calls to a remote service. Often the Presenter will also have several pass through methods for the view like "setTitle(...)".
package org.sagebionetworks.web.client.widget.entity.children; import org.sagebionetworks.web.client.PlaceChanger; import org.sagebionetworks.web.client.widget.SynapseWidgetPresenter; import com.google.gwt.event.shared.HandlerManager; import com.google.gwt.user.client.ui.Widget; import com.google.inject.Inject; public class EntityChildBrowser implements EntityChildBrowserView.Presenter, SynapseWidgetPresenter { private EntityChildBrowserView view; private PlaceChanger placeChanger; private HandlerManager handlerManager = new HandlerManager(this); @Inject public EntityChildBrowser(EntityChildBrowserView view) { this.view = view; view.setPresenter(this); } @SuppressWarnings("unchecked") public void clearState() { view.clear(); } @Override public Widget asWidget() { return view.asWidget(); } public void setPlaceChanger(PlaceChanger placeChanger) { this.placeChanger = placeChanger; } @Override public PlaceChanger getPlaceChanger() { return placeChanger; } }
View
The view interface defines the view and the Presenter interface--the view's method to make conceptual business logic calls like "saveValues(...)"
package org.sagebionetworks.web.client.widget.editpanels; package org.sagebionetworks.web.client.widget.entity.children; import org.sagebionetworks.web.client.PlaceChanger; import org.sagebionetworks.web.client.widget.SynapseWidgetView; import com.google.gwt.user.client.ui.IsWidget; public interface EntityChildBrowserView extends IsWidget, SynapseWidgetView { /** * Set the presenter. * @param presenter */ public void setPresenter(Presenter presenter); /** * Presenter interface */ public interface Presenter { PlaceChanger getPlaceChanger(); } }
ViewImpl
The ViewImpl implements its view and extends LayoutContainer. LayoutContainer is Ext GWT's base container (widget) class. You should generally instantiate view objects in the constructor, and add the main content-containing element for this view in the onRender(...) method with a simple add(myContent) call.
package org.sagebionetworks.web.client.widget.entity.children; import com.google.inject.Inject; public class EntityChildBrowserViewImpl extends LayoutContainer implements EntityChildBrowserView { private Presenter presenter; private SageImageBundle sageImageBundle; private IconsImageBundle iconsImageBundle; @Inject public EntityChildBrowserViewImpl(SageImageBundle sageImageBundle, IconsImageBundle iconsImageBundle) { this.sageImageBundle = sageImageBundle; this.iconsImageBundle = iconsImageBundle; this.setLayout(new FitLayout()); } @Override public Widget asWidget() { return this; } @Override public void setPresenter(Presenter presenter) { this.presenter = presenter; } @Override public void showErrorMessage(String message) { DisplayUtils.showErrorMessage(message); } @Override public void showLoading() { } @Override public void showInfo(String title, String message) { DisplayUtils.showInfo(title, message); } @Override public void clear() { } }