I am trying to add a widget to a panel using UIBinder but the composite simply doesn't load, here is my xml:
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:my='urn:import:com.abc.client.test.ui'>
<g:HTMLPanel ui:field="mainLayoutPanel">
<g:SimplePanel ui:field="menuPanel" >
<my:MainMenuViewImpl ui:field="mainMenu"/>
</g:SimplePanel>
<!-- the widget causing the issue -->
<my:FinancialsNav ui:field="nav"/>
<g:SimplePanel ui:field="mainPanel" />
</g:HTMLPanel>
</ui:UiBinder>
The corresponding java class:
public class AppLayoutImpl extends Composite implements AppLayout{
#UiField
HTMLPanel mainLayoutPanel;
interface AppLayoutUiBinder extends UiBinder<Widget,AppLayoutImpl>{}
private static AppLayoutUiBinder binder=GWT.create(AppLayoutUiBinder.class);
#UiField
SimplePanel menuPanel;// nav at the top
#UiField(provided=true)
FinancialsNav nav;// nav on the side
#UiField
SimplePanel mainPanel;// center
#UiField(provided=true)
MainMenuViewImpl mainMenu;
public AppLayoutImpl(ClientFactory clientFactory){
mainMenu=clientFactory.getMainMenuView();
nav=clientFactory.getNav();
initWidget(binder.createAndBindUi(this));
}
#Override
public Widget asWidget(){
return this;
}
}
And the Widget causing the issue:
public class FinancialsNav extends Composite implements ClickHandler{
private VerticalPanel nav=new VerticalPanel();
// Operations
private DisclosurePanel operationsWrapper=new DisclosurePanel(Proto2.constants.financials_navigation_operations());
private NavButton product=new NavButton(Proto2.constants.financials_navigation_products(),
SharedUtilities.PRODUCT_TOKEN);
private NavButton generalOptions=new NavButton(Proto2.constants.financials_navigation_generalOptions(),"");
private ArrayList<NavButton[]> buttons;
private NavButton[] operationsButtons={product,vc,fc,emp,others};
//...
private NavButton[] optionsButtons={generalOptions};
private final EventBus bus;
public FinancialsNav(EventBus bus){
this.bus=bus;
buildNav();
initWidget(nav);
}
private void buildNav(){
buttons=new ArrayList<NavButton[]>();
buttons.add(operationsButtons);
//...
buttons.add(optionsButtons);
int n=buttons.size();
int nn;
for(int i=0;i<n;i++){
nn=buttons.get(i).length;
for(int j=0;j<nn;j++){
(buttons.get(i)[j]).addClickHandler(this);
(buttons.get(i)[j]).setStylePrimaryName(NAV_BUTTON_STYLE);
if(i==0){
operationsWrapper.add(buttons.get(i)[j]);
//...
}else if(i==4){
optionsWrapper.add(buttons.get(i)[j]);
}
}
}
nav.add(operationsWrapper);
// ...
nav.add(optionsWrapper);
}
The FinancialsNav widget works fine when not used with UIBinder and the rest of AppLayout works as expected when the FinancialsNav isn't there.
I spent hours on this looking at various tutorials and examples but simply could not find what is wrong with the code. I also tried various workaround such as declaring a panel in the UIBinder instead of the FinancialsNav and the adding the nav to the panel.
Also everything is in the same package so it shouldn't be an import issue.
Any help would be much appreciated...
Here is the clientFactory
public class ClientFactoryImpl implements ClientFactory{
private static final EventBus eventBus=new SimpleEventBus();
private static final PlaceController placeController=new PlaceController(eventBus);
private static final CreatePlanServiceAsync createPlanService=GWT.create(CreatePlanService.class);
private static final FinancialsNav navView=new FinancialsNav(eventBus);
private static final MainMenuViewImpl mainMenuView=new MainMenuViewImpl();
#Override
public EventBus getEventBus(){
return eventBus;
}
#Override
public PlaceController getPlaceController(){
return placeController;
}
#Override
public FinancialsNav getNav(){
return navView;
}
#Override
public MainMenuViewImpl getMainMenuView(){
return mainMenuView;
}
#Override
public CreatePlanServiceAsync getCreatePlanService(){
return createPlanService;
}
}
FinancialsNav widgets has constructor with arguments. So create no argument constructor.
The entry <my:FinancialsNav ui:field="nav"/> is equals to new FinancialsNav().
In most cases this means that they must be default instantiable; that is, they must provide a zero-argument constructor. you have to pass argument
/** Used by MyUiBinder to instantiate FinancialsNav */
#UiFactory FinancialsNav makeFinancialsNav() { // method name is insignificant. do start with make
return new FinancialsNav(eventBus);
}
Refer Using a widget that requires constructor args
Can you show clientFactory code!!
Ok I found the error, actually not directly related to UIBinder.
Simultaneously to implementing UIBinder I was trying to reduce the number of tables used by the panels in my app.
As I noticed that the disclosure panel is based on a table I removed an intermediary vertical panel I had in the FinancialsNav.
Hence having DisclosurePanel --> Buttons instead of DisclosurePanel --> VerticalPanel --> Buttons. And that is causing the entire block not to show.
#adenoyelle and #bumika: thank you for help
Related
It's very hard to find questions about GWTP (GWT Platform).
Ok, Here is my Story. I am using GWTP & eclipse to create the Presenter-View structure automatically.
Example, I created a TestPresenter in eclipse, & it created 3 files: TestPresenter.java, TestView.java, TestView.xml
In TestView.xml, i have:
<g:RadioButton ui:field="firstRadioButton" value="false" text="1st" />
<g:RadioButton ui:field="secondRadioButton" value="false" text="2nd" />
<g:RadioButton ui:field="bothRadioButton" value="true" text="Both" />
Now I want to set the GroupName automatically for each TestView, so in TestView.java
public class TestView extends ViewImpl implements
TestPresenter.MyView {
private final Widget widget;
#UiField RadioButton firstRadioButton;
#UiField RadioButton secondRadioButton;
#UiField RadioButton bothRadioButton;
private String groupName;
#UiFactory
RadioButton makeRadioButton() {
return new RadioButton(groupName);
}
public interface Binder extends UiBinder<Widget, TestView> {
}
#Inject
public TestView(final Binder binder) {
widget = binder.createAndBindUi(this);
}
#Override
public Widget asWidget() {
return widget;
}
public RadioButton getFirstRadioButton() {
return firstRadioButton;
}
public RadioButton getSecondRadioButton() {
return secondRadioButton;
}
public RadioButton getBothRadioButton() {
return bothRadioButton;
}
}
In TestPresenter.java,
public class TestPresenter extends
PresenterWidget<TestPresenter.MyView> {
public interface MyView extends View {
public RadioButton getFirstRadioButton();
public RadioButton getSecondRadioButton();
public RadioButton getBothRadioButton();
}
}
Ok, finally I want to use many TestPresenter (by using setInLot) in MainPresenter.java
So, in MainPresenter.java, I have:
public static final Object SLOT1=new Object();
public static final Object SLOT2=new Object();
public static final Object SLOT3=new Object();
public static final Object SLOT4=new Object();
//...... more lot
#Inject TestPresenter testPresenter1;
#Inject TestPresenter testPresenter2;
#Inject TestPresenter testPresenter3;
#Inject TestPresenter testPresenter4;
//.. more test presenter
in MainView.java, i have setInSlot
#UiField HTMLPanel mainHtmlPanel;
#Override
public void setInSlot(Object slot, Widget content){
if(slot==MainPresenter.SLOT1){
mainHtmlPanel.clear();
if(content!=null){
mainHtmlPanel.add(content);
}
}
else if(slot==MainPresenter.SLOT2){
mainHtmlPanel.clear();
if(content!=null){
mainHtmlPanel.add(content);
}
}
//... more else if here
}
Now, if i just do like that then I can not pass the groupName separately for each TestPresenter & that is not good. So I want to pass the groupName string for each TestPresenter so that each will have their own groupName. SOmething like this
#Inject TestPresenter testPresenter1 ("group1");
#Inject TestPresenter testPresenter2 ("group2");
#Inject TestPresenter testPresenter3 ("group3");
#Inject TestPresenter testPresenter4 ("group4");
...
but I don't know how to it properly, so please tell me how to it properly in GWTP?
If you want to specify a groupName in constructors of TestPresenter why you might need to use is assisted injection".
Then you would probably end up with something like this (I have not tested the code):
public interface TestPresenterFactory {
TestPresenter create(String groupName);
}
and in your Gin Module:
#Override
protected void configure() {
...
install(new GinFactoryModuleBuilder().build(TestPresenterFactory.class));
}
Then instead of:
#Inject TestPresenter testPresenter1 ("group1");
#Inject TestPresenter testPresenter2 ("group2");
#Inject TestPresenter testPresenter3 ("group3");
#Inject TestPresenter testPresenter4 ("group4");
...
you would inject the TestPresenterFactory in the constructor of ParentPresenter to create all TestPresenters:
private TestPresenter testPresenter1;
private TestPresenter testPresenter2;
private TestPresenter testPresenter3;
private TestPresenter testPresenter4;
#Inject
public ParentPresenter(final EventBus eventBus, final ParentView view, final ParentProxy proxy, final TestPresenterFactory factory)
{
...
testPresenter1 = factory.create("group1");
testPresenter2 = factory.create("group2");
testPresenter3 = factory.create("group3");
testPresenter4 = factory.create("group4");
}
And the #Assisted annotation in the TestPresenter.java:
public interface MyView extends View {
...
public void setRadioButtonsGroupName(String groupName);
}
#Inject
public TestPresenter(final EventBus eventBus, final MyView view, #Assisted String groupName)
{
...
view.setRadioButtonsGroupName(groupName);
}
And TestView.java:
public class TestView extends ViewImpl implements TestPresenter.MyView {
private final Widget widget;
#UiField RadioButton firstRadioButton;
#UiField RadioButton secondRadioButton;
#UiField RadioButton bothRadioButton;
...
public void setRadioButtonsGroupName(String groupName) {
firstRadioButton.setName(groupName);
secondRadioButton.setName(groupName);
bothRadioButton.setName(groupName);
}
}
But do you really need your TestPresenters to be aware of the groupName used by the RadioButtons in their views ?
Ok, I haven't test Alexis' solution, but his idea of "setGroupName" trigger my mind so I can adjust my code abit & it works fine.
In TestPresenter.java, I have this method
public void setGroupName(String groupName) {
getView().getFirstRadioButton().setName(groupName);
getView().getSecondRadioButton().setName(groupName);
getView().getBothRadioButton().setName(groupName);
}
in MainPresenter.java
#Inject TestPresenter testPresenter1;
#Inject TestPresenter testPresenter2;
....
#Override
protected void onReset() {
super.onReset();
setInSlot(SLOT1, testPresenter1);
setInSlot(SLOT2, testPresenter2);
.....
testPresenter1.setGroupName("group1");
testPresenter2.setGroupName("group2");
....
}
I am constructiong an webapp with Google Web Toolkit using GWT-Platform and GWT-Bootstrap frameworks. Mostly it has been almost flawless until I tried to implement a popup. These frameworks' undestanding of popups seems to be quite different.
GWT-Platform expects a popup widget itself to be an instance of com.google.gwt.user.client.ui.PopupPanel when using the GWTP's RevealRootPopupContentEvent.fire(source, content) or a presenter's addToPopupSlot(child) method.
GWT-Bootstrap's Modal is used like any other widget that is added to the underlying panel but my goal is it to have a separate presenter and view and to possibly fetch it asynchrously with AsyncProvider.
I have tried to make it as a PresenterWidget and using addToSlot(slot, content) to reveal it but it doesn't look quite right. Not all of the styles are applied this way and the close icon (×), doesn't work for example.
I think I am not the first one trying to do something like that so maybe someone has figured out a proper way to make it work.
Thanks!
You have to create a view:
public class MyPopupView extends PopupViewImpl implements MyView {
protected Widget widget;
public interface MyPopupViewUiBinder extends
UiBinder<Widget, MyPopupView> {
}
#UiField(provided = true)
Modal dialogBox;
private MyPresenter presenter;
#Inject
public MyPopupView(final MyPopupViewUiBinder uiBinder,
final EventBus eventBus) {
super(eventBus);
setUpDialog(); // Provides UiField => Before initWidgets
initWidget(uiBinder.createAndBindUi(this));
}
// DialogBox must be overridden to let the presenter handle changes onUnload
private void setUpDialog() {
dialogBox = new Modal() {
#Override
protected void onUnload() {
MyPopupView.this.hide();
}
};
dialogBox.setTitle("Some title");
}
#Override
public void setPresenter(final MyPresenter presenter) {
this.presenter = presenter;
}
#Override
public final void hide() {
dialogBox.hide();
presenter.hide();
}
#Override
public void setAutoHideOnNavigationEventEnabled(final boolean autoHide) {
// TODO Auto-generated method stub
}
#Override
public void setCloseHandler(
final PopupViewCloseHandler popupViewCloseHandler) {
// TODO Auto-generated method stub
}
#Override
public void setPosition(final int left, final int top) {
// TODO Auto-generated method stub
}
#Override
public void show() {
dialogBox.show();
}
#Override
public void center() {
dialogBox.show();
}
#Override
public Widget asWidget() {
return widget;
}
protected final void initWidget(final Widget widget) {
this.widget = widget;
}
}
And a UIBinder file:
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:b='urn:import:com.github.gwtbootstrap.client.ui'>
<b:Modal title="Some Title" ui:field="dialogBox">
<!-- Your content -->
</b:Modal>
</ui:UiBinder>
Your gwtp popup presenter has a view that extends PopUpViewImpl which implements PopupView, and uses a lot of the methods of that interface for displaying the popup (asPopupPanel(), show(), center(), etc).
I'm just starting to get to know gwt-bootstrap (looks great +caalos0), but it seems that Modal doesn't implement PopupView, and therefore cannot be passed to addToPopupSlot in a way it would be displayed automatically by gwtp.
as for the addToSlot() issue, are you using RootLayoutPanel or RootPanel?
it could be the reason for addToSlot not working properly, since the gwt-bootstrap Modal widget is attached to the RootPanel on initialization, this can cause weird layout behavior along with an application using RootLayoutPanel as base.
I would try to extend the Modal component, let it implement PopUpView, add it as a field on the PopUpViewImpl attached to your popup presenter, and override the PopUpViewImpl asPopupPanel() function to return the new extended Modal.
Based on the answer by #dominik I did some improvements, see my Gist. It contains some abstract base classes that can be used for any Modal/PopupView implementation. It's a bit more complex but also cleaner because we don't pass the whole Presenter to the View. The interface for the View to interact with the Presenter when the modal is closed is HasModalUnbind.
You would use these classes as follows. Example presenter:
public class ErrorModalPresenter extends ModalPopupPresenter<ErrorModalPresenter.MyView> {
public interface MyView extends ModalPopupView {
DivElement getErrorMessage();
}
private final ErrorEvent error;
#Inject
public ErrorModalPresenter(final EventBus eventBus,
final MyView view,
#Assisted final ErrorEvent error) {
super(eventBus, view);
this.error = error;
}
#Override
public void unbindModal() {
ErrorDismissEvent.fire(this, this);
}
#Override
protected void onBind() {
super.onBind();
//noinspection ThrowableResultOfMethodCallIgnored
getView().getErrorMessage().setInnerText(error.getCause().getMessage());
}
}
Example view:
public class ErrorModalView extends ModalPopupViewImpl implements ErrorModalPresenter.MyView {
#UiField(provided = true)
Modal errorModal;
#UiField
DivElement errorMessage;
interface Binder extends UiBinder<Widget, ErrorModalView> {}
#Inject
public ErrorModalView(final EventBus eventBus,
final Binder uiBinder) {
super(eventBus);
errorModal = initModal();
initWidget(uiBinder.createAndBindUi(this));
}
#Override
public DivElement getErrorMessage() {
return errorMessage;
}
}
And the UiBinder XML just for the record:
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:b='urn:import:com.github.gwtbootstrap.client.ui'>
<b:Modal ui:field='errorModal' title='Error'>
<g:HTML>
<div ui:field='errorMessage'/>
</g:HTML>
<b:ModalFooter>
<b:Button text='Close' dismiss='MODAL'/>
</b:ModalFooter>
</b:Modal>
</ui:UiBinder>
In unbindModal() of ErrorModalPresenter I fire an event which is caught by the parent presenter of ErrorModalPresenter. There the modal presenter is removed from a container and then unbind() is called on the presenter. Of course any other solution is possible in unbindModal().
The base classes assume that modals are one-shot modals that will be removed once they're hidden. This behaviour can be changed in initModal() of ModalPopupViewImpl.
I believe you will have to made some Glue Code to made it works.
I never used GWT-Platform popups, so I dont know exactly how, but I believe you will have to made a new Class extending PopupPresenter, and made what's needed to made it work.
Also, I was thinking about GWT-Platform days ago... and I'm pretty sure that when first release of GWT-Platform is out, I'll create a new project to made these necessary glue codes.
If you need any help with this, please contact me.
Thanks, sorry about the poor gwt-platform support.
I dived to the gwt world a few monthes ago and now am trying to use the gwt-query library.
I followed this tutorial: http://code.google.com/p/gwtquery/wiki/GettingStarted
Because I am working in Modle-View-Presenter, I tried implementing the above tutorial in my View (that is bound to the ..View.ui.xml), But it dosent seems to work.
I tried creating a lable, and then run the code:
List allGwtLabels = $(".gwt-Label").widgets();
but it selects nothing!
I think I have to point somehow where I want the qwtQuery to search for the widgets (point to my specific ui.xml file)
What am I doing wrong?
Thanks in advance. Below is my code of my Presenter + View + xml that dosent work:
//================================Presenter=================================:
public class QueryPresenter extends
Presenter<QueryPresenter.MyView, QueryPresenter.MyProxy> {
public interface MyView extends View {
}
#ProxyCodeSplit
#NameToken(NameTokens.query)
public interface MyProxy extends ProxyPlace<QueryPresenter> {
}
#Inject
public QueryPresenter(final EventBus eventBus, final MyView view,
final MyProxy proxy) {
super(eventBus, view, proxy);
}
#Override
protected void revealInParent() {
RevealRootContentEvent.fire(this, this);
}
#Override
protected void onBind() {
super.onBind();
}
}
//====================================View============================================:
public class QueryView extends ViewImpl implements QueryPresenter.MyView {
private final Widget widget;
public interface Binder extends UiBinder<Widget, QueryView> {
}
#Inject
public QueryView(final Binder binder) {
widget = binder.createAndBindUi(this);
List<Widget> allGwtLabels = $(".gwt-Label").widgets(); //Doesn't Work!!
//Also doesn't work!!
Label label = new Label("Click on me and I will disappear");
$(label).click(new Function() {
#Override
public void f(Widget w) {
//fade out the label
$(w).fadeOut(1000);
}
});
_html.add(label);
//retrieve all attached gwt labels
}
#Override
public Widget asWidget() {
return widget;
}
#UiField Label _label;
#UiField HTMLPanel _html;
}
//==================xml file===============================
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
ui:generateKeys='com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator'
ui:generateLocales='default'>
<g:HTMLPanel ui:field="_html">
<script type="text/javascript" language="javascript" src="gquerytest/gquerytest.nocache.js"></script>
<g:Label text="hey" ui:field="_label"/>
</g:HTMLPanel>
</ui:UiBinder>
try : List allGwtLabels = $(".gwt-Label", widget).widgets();
You have to specify the container of your elements as the elements are not attached to the dom when you try to query them.
I am trying to make a basic cellbrowser widget work in my App. For now just the Structure so that I can replace it later with something meaningfull.
I looked up the samples and implemented one however when I try integarting it in my Application, it wont work!
Here is the part of code. What is the problem? Why cant I see the widget?
public class ListViewImpl extends Composite implements ListView
{
private static ListViewImplUiBinder uiBinder = GWT
.create(ListViewImplUiBinder.class);
interface ListViewImplUiBinder extends UiBinder<Widget, ListViewImpl>
{
}
private Presenter presenter;
#UiField(provided=true)
CellBrowser cellbrowser;
public ListViewImpl()
{
TreeViewModel model = new ListTreeViewModel();
cellbrowser=new CellBrowser(model,null);
cellbrowser.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
cellbrowser.setAnimationEnabled(true);
initWidget(uiBinder.createAndBindUi(this));
}
#Override
public void setPresenter(Presenter presenter)
{
this.presenter=presenter;
}
#Override
public Widget asWidget() {
return this;
}
}
The Uibinder file goes as -->
<ui:style>
.browser {
border: 1px solid #ccc;
}
.out
{
outline:#ccc solid thick;
}
</ui:style>
<g:HTMLPanel styleName='{style.out}' >
<c:CellBrowser addStyleNames='{style.browser}' defaultColumnWidth='300' ui:field='cellbrowser' />
</g:HTMLPanel>
The ListTreeView model class is perfect as when I use the code in a standalone application and add CellBrowser to RootLayoutPanel. It works!
CellBrowser is a RequiresResize widget (it uses a SplitLayoutPanel internally), so just like with all RequiresResize widget, you have to either put it within a ProvidesResize widget, or give it explicit dimensions.
I'm trying to access some objects inside a ui:binder component, but not sure of how to access the eventBus, requestFactory, etc without writing nasty code that will keep me awake at night (also take note that I'm completely new to JAVA, background is in Perl/Python/PHP).
My ui.xml file:
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:ig='urn:import:com.ig.client.scaffold.ui.widget'>
<ui:style>
...
</ui:style>
<g:HorizontalPanel>
...
</g:HorizontalPanel>
</ui:UiBinder>
Injecting the eventBus this way fails with
com.ig.client.scaffold.ui.widget.R has no default (zero args) constructor.
public class R extends Composite {
interface MyUiBinder extends UiBinder<Widget, R> {}
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
private final EventBus eventBus;
#UiField SimplePanel fieldA, ...;
#Inject
public R(EventBus eventBus){
this.eventBus = eventBus;
initWidget(uiBinder.createAndBindUi(this));
}
}
So, as per the error message, I create a UIFactory and then I get an error
... '{style.entityComponent}'> missing required attribute(s): eventBus Element ... (seems like it is trying to find the eventBus in the ui:binder stylesheet.
public class R extends Composite {
interface MyUiBinder extends UiBinder<Widget, R> {}
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
private final EventBus eventBus;
#UiField SimplePanel fieldA, ...;
public #UiConstructor R(EventBus eventBus){
this.eventBus = eventBus;
initWidget(uiBinder.createAndBindUi(this));
}
#Inject
#UiFactory R makeR(){
return new R(eventBus);
}
}
From reading and reading and more reading for the past couple of days, I haven't seen anyone accessing the eventBus, requestFactory and historyController directly in the view binding to the ui:binder widget which led to the conclusion that it's probably not a best practice
anyway.
Let's say I have an oject, let's call it Proxy, proxy contains handleButtonClick which then calls eventBus.doSomething(). How do I link this Proxy object to the ui:binder widget without having to instantiate it or without having to pass it around to every widget?
Is it possible to do GIN injection on an interface and then implement that interface via class R which will then somehow contain the objects I'm looking for?
Any solution that work is welcome, just looking for a sample (that a Java n00b can understand) that will basically allow me to connect my front-end with the rest of the services created by ROO.
Thanks
J
Check out the Model, View, Presenter pattern - it solves
this problem. Generally all non-display logic should be kept out
of your views so that 1) the non-display logic can be unit tested without
running inside a (slow to instantiate) browser and 2) different
displays can be plugged into the same application without duplicating
the non-display logic.
Here's an MVP example exhibiting the
behavior you're looking for (note that the style is slightly
different than the Activities & Places implementation).
MyPresenter.java:
public class MyPresenter {
public interface Display extends IsWidget {
void setButtonClickHandler(ClickHandler buttonClickHandler);
}
private final Display display;
private final EventBus eventBus;
#Inject
public MyPresenter(EventBus eventBus,
Display display)
{
this.display = display;
this.eventBus = eventBus;
bind();
}
private void bind() {
display.setButtonClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
eventBus.fireEvent(new MyButtonClickedEvent());
}
});
}
public void go(HasWidgets container) {
container.add(display.asWidget());
}
}
MyView.ui.xml:
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:ig='urn:import:com.ig.client.scaffold.ui.widget'>
<g:Button ui:field="myButton"/>
</ui:UiBinder>
MyView.java
public class MyView extends Composite implements MyPresenter.Display {
interface MyViewUiBinder extends UiBinder<Widget, MyView> {}
private static MyViewUiBinder uiBinder = GWT.Create(MyViewUiBinder.class);
private ClickHandler buttonClickHandler = null;
public MyView() {
initWidget(uiBinder.createAndBindUi(this));
}
#UiHandler("myButton")
void onButtonClick(ClickEvent event) {
if (buttonClickHandler != null) {
buttonClickHandler.onClick(event);
}
}
#Override
public void setButtonClickHandler(ClickHandler buttonClickHandler) {
this.buttonClickHandler = buttonClickHandler;
}
}
And in your GIN module: bind(MyPresenter.Display.class).to(MyView.class);