GWT - connect two modules via EventBus - gwt

We use MVP with custom EventBus to navigate across the views. One of our GWT module loads an ebook within a view. We have a button named "Expand", which upon clicked, loads the ebook in expanded mode thereby hiding the header, footer, etc.
Let us say the view (UiBinder) with "Expand" button is named as "ShowEbookView". Upon clicking "Expand" button, the ClickEvent is captured and fired to the EventBus. The logic onExpand(final ExpandEvent expandEvent) is written in the same "ShowExpandedMod" class.
Everything is okay, but we have a button named "Popout" in the expanded mode, which when clicked, should open the Ebook in a NEW page! We need to abstract the "ShowExpandedMod" class so that it can operate with the EbookId and can be used in the new page.
We have created a new Module with EntryPoint class, HTML page and UiBinder page for this new popout window. I am not sure how to proceed now with the abstraction and to use EventBus across different modules to load the same content ... (with re-usability ofcourse)
I've explained to my best, but perhaps not very clear! Please let me know if you want more details.
Thanks!

When you open a new window in browser you basically get a new instance of your GWT app. You can not use EventBus across different browser windows, i.e. across different GWT module instances.
What you can do is:
Add an argument to the Popout page URL. This is easies done via "history tokens" (fragment identifiers), like this http://yourdomain.com/popout.html#theIdOfTheDocument. Then you can retrieve the token via History.getToken()
Use DOM to communicate between browser windows: window.open() in javascript opens a new window and returns a reference to DOM of the new window. You can then access properties and functions of the new window. This is all javascript, in order to make this work in GWT you'll need to wrap it in JSNI.

Try and use MVP4G, in specific - take a look at their multi-modules feature (which utilizes GWT's code splitting capabilities).
This should make things like multiple EventBus's and cross-module event triggers a lot easier to handle.

Related

How to hook GWT navigation from a userscript?

I'm writing a userscript for a GWT-based site.
My script uses URL of the page as input. It should be update each page of the site with additional information.
Unfortunately, as view changes in GWT are implemented via rerendering (only location anchor in browser address-bar is being changed), clicks on internal links are not recognized as page loads and Greasemonkey does not invoke my script, leaving new views unmodified.
Is there a way to hook in GWT-based navigation from an userscript? I need a way to modify each "change" Gerrit navigates to.
Complete workflow should look like:
User scans through the list of issues
User clicks on a link . (Address bar will assume a location of a change being clicked, for example https://git.eclipse.org/r/#/c/38781/)
Page is modified by userscript to contain information about new view (in our case /c/38781/)
Greasemonkey is only invoked at the first step of this workflow, and I don't know ho to detect second one to be able to trigger the third.
I've tried to observe DOM changes on the page, but my listeners are never called probably due to the fact GWT renders some parts via innerHTML property, without explicit child manipulation.

GWT UiBinders Interaction between modules

Im new to GWT, this should be a simple question i hope.
Imagine that i made two Uibinders Modules or two independent widgets.(this a simplify example to expose my problem)
one is a set of buttons (ButtonPanel) and the other image to been show when i press a button from the previous panel(ImagePAnel) with a label to be the title of the image.
How can i reach the wiget the imagePanel to actuate when there are a handler click from the buttons in the (ButtonPanel)
Thanks for the help.
I recommend you to use MVP Pattern for Development and add all events in the Presenter.
Or Else you can use the following technique within the UIBinder's Java File
#UiHandler(value={"openButton"})
public void onOpenButtonClick(ClickEvent clickEvent){
//ADD THE BUTTON LOGIC HERE
}
Just Create an Object of the Images & the ImagePanel to be loaded and add it on button click using this.
I can't say I understand exactly what you are trying to accomplish but in general the best way for different components in a GUI application to communicate is to use the eventbus pattern. There's one global Eventbus object in the application that lets components subscribe to a specified type of event that are fired from any place in your application. This way you avoid spaghetti code and your components are loosely coupled.
http://code.google.com/webtoolkit/articles/mvp-architecture.html#events
I typically create a third component that is the container for the Button and Image components you defined. This component sets itself as a callback for the two and contains logic to integrate the two.

Persistent Logging in Gnome-Shell-Extension development?

I'm trying around with the Javascript-based bindings to build an own Gnome-Shell-Extension which just embeds an webkitview.
But the following 3 lines let completely crash the gnome-shell (top panel disappears, need to re-login to start it again). therefore no way to look into the "Errors"-tab of LookingGlass to figure out, what was wrong.
WebKit = imports.gi.WebKit;
GtkClutter = imports.gi.GtkClutter;
Main.panel._rightBox.add(new GtkClutter.Actor({contents: new WebKit.WebView()}));
Is there any way to get some infos what's going wrong?
you cannot embed a WebKitGtk WebView inside gnome-shell, or any other GTK widget, include GtkClutterEmbed; this is actually a limitation of GTK.
if you want to embed a WebKitGtk WebView one option is to use a separate process, get the XID of the GtkWindow and use a ClutterX11TexturePixmap actor to display it inside an extension. you'll have to pass events from the Clutter actor to your application as well. you can use some form of IPC, like D-Bus, to pass the XID and the events.

GWT MVP - maintaining multiple displays that are separate of one another

I have a GWT App and I am using GWT MVP with Places / Activities.
My application layout is something like
MENU | CONTENT
The Menu and the Content displays will change dynamically and one changes separately from the other. What I mean by this is that when the Content display changes I do not want to have to update the Menu display and vice versa. Both displays need to be able to respond to PlaceChangeEvents and update themselves when these occur. The problem is that each display should only update in response to certain PlaceChangeEvents, ignoring PlaceChangeEvents that are directed at the other display. However this does not work using the 'standard' GWT MVP pattern because even when each display has it's own ActivityManager they will automatically pick up ALL PlaceChangeEvents because there is a single PlaceController listening on a single EventBus. The only way I can see to do this is by having two EventBus's and two PlaceControllers - one for the Menu and one for the Content. So my question is whether this is a good solution or is there a simpler/better way that I am missing? One problem with this solution is that the PlaceHistoryHandler can only be registered with one of the EventBus's.
Place changes are actually controlled by ActivityMappers. They get a Place and return the corresponding Activity. This is where you control how Places are mapped to Activities:
You need to create two ActivityMappers (MenuActivityMapper, ContentActivityMapper) and then instantiate two ActivityManagers each with it's own ActivityMappers. Then for each ActivityManager you call setDisplay(AcceptsOneWidget display) where for each you pass in an area (display) where it will show it's content.
For menu you will probably only use one Activity, since it's available in all Places. So MenuActivityMapper.getActivity() will always return the same instance of the MenuActivity. To enable MenuActivity to still adapt it's look based on place changes, MenuActivity should listen to PlaceChangeEvents.

Opening a new Window with a Widget in GWT

Before you start shooting me down i have checked for answers and i have googled till my fingers bled but i havent been able to find a simple, concise answer. So im asking again for all those that might have this problem.
Question: how to open a new window with a formpanel in side.
Context: i have an app that lists lots of items, i want someone to edit an entry, i want a new window to open so they can edit properties then hit save. A standard thing you find in a lot of applications.
Architecture:
I have one client module called UI, it has a dozen classes that draw widgets and fill a main area when selected from a menu. I have a single html page called UI.html which has the tag in the head. Thats it.
Options Ive Seen
Call Window.Open() but you need to define a html file. I dont have one. I can create an empty one but how do you inject a widget in to it ?
use jsni $wnd to create a new window and get a reference to it. But how do i inject a form panel into it ??
use a popuppanel. They look sucky - plus if opening a window through JS is quite simple i would expect it to be in gwt.
Maybe im miss understanding how to use GWT i dont know.
Any help would be appreciated
Thanks
The way i got this to work is as follows:
i wrote a jsni method to open a new window
public static native BodyElement getBodyElement() /*-{
var win = window.open("", "win", "width=940,height=400,status=1,resizeable=1,scrollbars=1"); // a window object
win.document.open("text/html", "replace");
i added a basic body to the new window and returned the body element
win.document.write("<HTML><HEAD>"+css1+css2+"</HEAD><BODY><div class=\"mainpanel\"><div style=\"width: 100%; height: 54px;\"><div id=\"mainbody\"class=\"mainbody\" style=\"width: 100%;\"></div></div></div></BODY></HTML>");
win.document.close();
win.focus();
return win.document.body;
}-*/;
i then called this method from my main java method
BodyElement bdElement = getBodyElement();
I then injected my panel which has lots of widgets into the returned body element
SystemConfiguration config = new SystemConfiguration(); bdElement.getOwnerDocument().getElementById("mainbody").appendChild(config.getElement());
I agree with Bogdan: Use a DialogBox.
If you can't, you Window.open() as you mentioned in option 1:
Create another GWT module, and form.html that will load it
Window.open("form.html?entry=54")
Have the form gwt module read from the URL, load the entry, allow it to be edited, and provide Save and Cancel buttons
Close the popup when Save or Cancel is clicked
Can't you just use a DialogBox?
Example