GWT: How to dynamically load a new image? - gwt

I want to fetch an image from a remote server (not my app's server, but I don't think that matters) and display it in an existing Image widget. The existing widget displays its original content, from a ClientBundle ImageResource , OK.
In UiBinder template:
<g:Image ui:field='myImage' resource='{res.anImage}'/>
In code:
#UiField Image myImage;
...
int width = Window.getClientWidth();
int height = Window.getClientHeight();
String url = ...;
myImage.addErrorHandler(new ErrorHandler() {
public void onError(ErrorEvent event) {
Window.alert("Error getting image data: " + event);
}
});
myImage.addLoadHandler(new LoadHandler() {
public void onLoad(LoadEvent event) {
Window.alert("LoadEvent: " + event);
}
});
myImage.setUrlAndVisibleRect(url, 0, 0, width, height);
As far as I can tell setUrlAndVisibleRect is a no-op. FireBug reports no network activity -- no request to the server specified by the URL. What am I overlooking? In my extended thrashing about trying to get this working I have inferred that it may have something to do with myImage not being "logically attached", but I'm not entirely sure what that means and I've no idea how to correct it if that is the problem.
EDIT with SUMMARY of SOLUTION:
My initial hunch was right. Because I had chosen to implement the image code within a second pseudo-widget (...extends Composite) that shared my UiBinder template with the main pseudo-widget that implements most of my app's UI, I got into trouble. I neglected to add this second pseudo-widget to the RootPanel as is normally done in the class that implements EntryPoint. This left my Image widget unattached to the widget chain, because its parent, the second pseudo-widget, was unattached. And an Image widget must be attached to work. What I ended up doing is moving the Image code back into my main app/GUI class, i.e., into the first and now only pseudo-widget and abandoning the special class for the Image code. I did that because it's simpler and the Image code turns out not to be as long as I had originally thought.

Adding image to the DOM is little tricky,the below code which supports all the browsers(setVisibility trick added to support IE also,as It has a different way to image rendering).
I did'nt use setUrlAndVisibleRect before and AFAIK,Image must render to the DOM inorder to resize it.Just try the below codes.
image.addLoadHandler(new LoadHandler() {
#Override
public void onLoad(LoadEvent event) {
//Do your operations on image .//resize ..etc
image.getElement().getStyle().setVisibility
(Style.Visibility.Visible);
}
});
image.getElement().getStyle().setVisibility(Style.Visibility.HIDDEN);
RootPanel.get().add(image);
image.setUrl(url);

You are using ClientBundle ImageResource which is compile time. You cannot change it unless you replace the new image with exact name in the exact position of prev one. One of the possible hack which is possible is, place the image in a div with its ID set ( getElement().setId("your ID") ). Once you get you new image you use RootPanel.get("Your Id") and do your job.

Related

Setting background image dynamically in wicket application

In my wicket application there are pages for users depending upon their role and on different criteria. In my database I am storing the path of image to be used as a background for that user. Every user has a unique page. I know I can add read image if I do something like this :
<img wicket:id="img">
and corresponding to this I am writing the code which will get image for me .
But how can I set the image as body background dynamically .I am pretty much new to wicket .Can anybody have a clue how to do that ?
In your page you can do it with some header contribution:
#Override
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
response.render(CssHeaderItem.forCSS("body{ background-image: url('" + getBackgroundBodyImagePath() + "');};", "uniqueBodyBackground"));
}
Or you could assign a wicket id to your <body> element and add an AttributeModifier like this:
#Override
protected void onInitialize() {
super.onInitialize();
bodyElement.add(AttributeModifier.replace("style", "background-image: url(" + getBackgroundBodyImagePath() + \"');"));
}

GWT MAP 3.8 (Google API) - Is onResize() needed to hide the "grey background"?

My problem:
- I display a map inside a popup and I have unloaded tiles (grey background).
- If I zoom out or in, then the map will fill the entire space (no grey background anymore).
My question:
- Have you any idea about my problem (Should I need to resize to hide the "grey background") ?
- I do not know if I should call onResize() inside the Runnable callback (code is above) or not ?
Thanks you,
My actual code: (I am using the javaxLoaderAPI)
// ENTRY POINT
GoogleMap map;
#UiField LayoutPanel gmap;
public void AjaxLoader_MAP() {
AjaxLoaderOptions options = AjaxLoaderOptions.newInstance();
options.setOtherParms("key=***&sensor=false&language=es");
Runnable callback = new Runnable() {
public void run() {
gmap.onResize(); // Should I call onResize() here ?
map = GoogleMap.create(gmap.getElement());
};
}
AjaxLoader.loadApi("maps", "3", callback, options);
}
May be related to the following post - GWT Google Map Api V3 - broken when changing it
I just posted an answer to that unanswered post as well. I believe it answers and sheds insight on this one as well.
I know this is an old post, but let me know if helps!
When calling mapWidget.triggerResize(), it's important to call it with some delay (Timer.schedule()) so that all the widget have been reset and then the map is resized.
This is how I trigger it:
#Override
protected void onReset() {
super.onReset();
Timer timer = new Timer() {
#Override
public void run() {
triggerResize();
}
};
timer.schedule(100);
}
Without timer, I was still getting grey tiles. Hope someone still finds it useful.

second call of google maps does not show the map in correct size

using gwt-maps-3.8.0 i display a route in a gwt popup. Works when called once but does not work on second call.
What should i do ... some advice to refresh the mapWidget?
When you display the map, trigger its resize event.
From the documentation:
Developers should trigger this event on the map when the div changes size: google.maps.event.trigger(map, 'resize')
It appears the way to do this in GWT is
Event.trigger(mapWidget.getMap(), "resize");
At the moment, the map has zero size as far as the API is concerned, so it's just displaying the buffer of tiles around the single pixel at (0,0). Triggering the resize event causes the API to get the correct size from the browser so the right tiles are fetched for display.
I had the same issue (map shown in a popup; reload the popup and the map was no longer centered).
In the end I managed to fix my problem using the triggerResize method from the GoogleMap class. However it worked only after I triggered this method from an Idle event.
triggerResize will notify the map to show the correct tiles.
setCenter will make sure the map is centered once again.
gMap.addIdleListenerOnce(new IdleHandler() {
#Override
public void handle() {
gMap.triggerResize();
gMap.setCenter(myLatLng);
}
});
Using the GWT-V3-Maps-API it would be done as follows for a case where a div or window resizes:
/*
* Example of how to dynamically resize the map to fit the window - add
* your events
*/
Window.addResizeHandler(new ResizeHandler() {
#Override
public void onResize(ResizeEvent event) {
MapHandlerRegistration.trigger(mapWidget, MapEventType.RESIZE);
GWT.log("Window has been resized!");
}
});
mapWidget.addResizeHandler(new ResizeMapHandler() {
#Override
public void onEvent(ResizeMapEvent event) {
GWT.log("Map has been resized!");
}
});

Overlay images in gxt Tree Panel

I'm developing a gxt application that provides a view for svn-like versioning: A TreePanel that displays a file system structure with files and folders having different states (new, modified, deleted, etc.).
I want to display a small overlay icon on each of the items to reflect its state. What I could do, is to create an icon for each state, but I don't want to do that, because I would end up in creating a large bundle of redundant images.
What would be the best way to implement overlay icon capabilities in trees or grids?
After checking the dom of the tree structure, I figured out that a tree icon is displayed using the background-url css attribute. To ensure the image is being displayed with correct size, the src attribute of the element is filled with a placeholder image url.
The trick is, to replace the placeholder image with the overlay icon, since it is displayed above the actual image.
To accomplish this, I extended ClippedImagePrototype to inject the url of the overlay image:
public class OverlayImagePrototype extends ClippedImagePrototype {
protected String overlayImageUrl = null;
public static AbstractImagePrototype create(ImageResource resource, String overlayUrl) {
return new OverlayImagePrototype(resource.getSafeUri(),
resource.getLeft(), resource.getTop(), resource.getWidth(),
resource.getHeight(), overlayUrl);
}
private OverlayImagePrototype(SafeUri url, int left, int top, int width,
int height, String overlayUrl) {
super(url, left, top, width, height);
this.overlayImageUrl = overlayUrl;
}
public ImagePrototypeElement createElement() {
ImagePrototypeElement imgEl = super.createElement();
if (overlayImageUrl != null) {
imgEl.setAttribute("src", overlayImageUrl);
}
return imgEl;
}
}
This is how I use OverlayImagePrototype in the IconProvider implementation:
tree.setIconProvider(new ModelIconProvider<ModelData>() {
public AbstractImagePrototype getIcon(ModelData model) {
return OverlayImagePrototype.create(model.get("icon"), model.get("overlayIconUrl"));
}
});

How to add a GWT click listener to an Image?

I want to click on an image and therefore want to register (e.g.) a ClickHandler. The image I get from a ClientResource. This works so far to set the image into a table cell:
MyResources.INSTANCE.css().ensureInjected();
Image colorImage = new Image( MyResources.INSTANCE.colorImage() );
Element colorImageElement = colorImage.getElement();
colorImage.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
System.out.println( event );
}
} );
TableElement table = Document.get().createTableElement();
TableRowElement headRow = table.insertRow(-1);
headRow.insertCell(-1).appendChild( colorImageElement );
RootPanel.get().getElement().appendChild( table );
How can I add a listener to the icon? I tried ClickHandler and to put the image on a PushButton and get the Element from this PushButton but all don't work.
But mind, if I add the widget (Image is a Widget) to a panel it works!
RootPanel.get().add( colorImage );
But I am not working with widgets here but with the Element. So the handler disappears and that's the point I don't get how to preserve this added handler information.
In the end I would like to build a table with different rows where I can click on the icon I get a popup menu and thereby change the colour of the row.
You should be able to just add a ClickHandler (or a MouseDownHandler if that fits your needs better).
Like this:
colorImage.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
// Do something....
}
});
Don't unwrap your widget and append only the DOM elements. The Widget class allows your code to refer to both elements and events at the same time, and deals with possible memory leaks, as well as grouping your code in logical ways.
This might make sense for other frameworks, but in GWT you almost always want to work with the Widgets directly, adding them together, then appending them to the RootPanel.
If you really want to use a html table to build this up, look at the com.google.gwt.user.client.ui.HTMLTable subclasses, com.google.gwt.user.client.ui.Grid and com.google.gwt.user.client.ui.FlexTable. This probably should never be necessary, unless you are adding multiple items to the table - when trying to specify layouts, use actual layout classes.
did you tried to add image.sinkEvents( Event.ONCLICK | Event.MOUSEEVENTS )?
The image has to be inside a focus widget. I don't know why that is, but somewhere the events don't get propagated right and the DOM events don't fire.