Show loading Screen while Image is loading in wicket - wicket

I'am populating a ListView with images.
In pseudocode:
populateItem(model){
load base64 from database
image.setDefaultModel(base64)
The image is just a webcomponent and in html it is just <img src="">
How can i show a indicator while the image is loaded?.
I first thought of adding IAjaxIndicatorAware but this triggers the indicator when the image is doing an AjaxRequest.

Since you seem to load and display the image as a Base64 src it will directly get send in the html response and not loaded later (in contrast to images with a src that links to another URI).
You could wrap the image in an AjaxLazyLoadPanel.
This will first display an AjaxIndicator while the content is generated and get later replaced by the actual loaded content once it is done loading/generating:
edit
I got an Exception : Component must be applied to a tag of type [img].
i didn't consider that problem. AjaxLazyLoadPanel allways uses a <div> as a html tag to display the component it loads. To display a base 64 image you would need to wrap it in another Panel:
public class Base64ImagePanel extends Panel {
public Base64ImagePanel(String wicketId, String base64Data, String contentType) {
super(wicketId);
WebMarkupContainer image = new WebMarkupContainer("image") {
protected void onComponentTag(ComponentTag tag) {
super.onComponentTag(tag);
checkComponentTag(tag, "img");
tag.put("src", "data:" + contentType + ";base64," + base64Data);
}
}
add(image);
}
}
Base64ImagePanel.html:
<wicket:panel>
<img wicket:id="image"></img>
</wicket:panel>
And then use that wrapper Panel in the AjaxLazyLoadPanel:
add(new AjaxLazyLoadPanel("imageLazyLoad") {
#Override
public Component getLazyLoadComponent(String id) {
//load your actual base64 from database, i use some example Strings for demonstration in the following line
Base64ImagePanel imagePanel = new Base64ImagePanel(id, "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==", "image/png");
return imagePanel;
}
});

Related

Lazily Initialize/Load a GXT Widget When Its Parent Becomes Visible

I am very new to GXT (and GWT/GWTP for that matter). I want to know if I can lazily load a GXT (4.0) [custom] widget when a modal Dialog that contains its panel is displayed (dialog initially not shown and only appears when a button is clicked).
The reason I want this behavior is that this widget needs to load an applet HTML code which is not available when the page initially instantiates all the other field widgets/panels/dialogs. Therefore, I need to delay obtaining the applet code from another application until the dialog is explicitly appears.
Is this possible?
Lazy loading of images and urls loaded into a GWT Frame (IFrameElement). You can catch the event once say the image/url is loaded using the LoadHandler event.
private void loadLoginPage() {
final Frame frame = new Frame(url_base + url_login); // set the frames url
frame.addLoadHandler(new LoadHandler() {
#Override
public void onLoad(LoadEvent event) {
// Get the document from the loaded frame (similar to RootPanel on main page)
Document doc = IFrameElement.as(frame.getElement()).getContentDocument();
// From here you can wrap widgets in the frame like this
final TextBox username = TextBox.wrap(doc.getElementById("username")); // from the html doc using id="username"
// grab a div element
DivElement div = DivElement.as(doc.getElementById("mydiv"));
// Create content to be added to the doc
ButtonElement button_elem = doc.createPushButtonElement();
Button button = Button.wrap(button_elem);
// attach to the document
div.appendChild(button.getElement());
}
});
// Attach to DOM
RootPanel.get("mything").add(frame);
}
And similar for image loading.
Image image = new Image(image_url);
image.addLoadHandler(new LoadHandler() {
#Override
public void onLoad(LoadEvent event) {
// image is ready to be used.
}
});
// attach to DOM to initiate loading of the image
Hope this helps...

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() + \"');"));
}

Dynamic image tooltip

I try to figure out how can I display dynamically a tooltip containing image from byte array.
I don't want to put image href or base64 content on start. It should work dynamically: if user hover something the tooltip will display and obtain image I have in byte array.
You need DynamicImageResource. Map it to an URL and override byte[] getImageData(IResource.Attributes attributes) abstract method that generates image data.
In your WebApplication class:
mount(new MountMapper("/images/my-tooltip", new DynamicImageResource("png") {
#Override
protected byte[] getImageData(IResource.Attributes attributes) {
// TODO your array with data
return new byte[];
}
}));

GWT: How to dynamically load a new image?

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.

how to load a svg in gwt widget from an url

I have a servlet that delivers png and svg images. With png i have no problem:
Image image = new Image(GWT.getHostPageBaseURL() + token);
But how to get svg to work? I already added "lib-gwt-svg" to my dependencies. There is a SVGImage class:
SVGImage svg = new SVGImage(OMSVGParser.parse(???));
The parse takes a string. Is there a way to load a raw String from an URL?
Or how to get it to work (with or without "lib-gwt-svg")?
Update:
thx to Andrei Volgin: he pointed out that it should work with "Image" and it does (i just had to correct the mime type to "image/svg+xml"). But the scripts within svg-image don't work this way (it looks like the images is rendered as a normal bitmap image).
I need the image rendered as svg (with scripts).
If you use a URL to load an image, you don't need any libraries at all. And you don't need a servlet to deliver them. Just add images to your /war/images folder. Then, in your GWT code:
Image image = new Image();
image.setUrl("images/myImage.svg");
myPanel.add(image);
You may want to add some logic for browsers that do not support svg files.
I found a solution that works without any external library (like Andrei's Solution) but keeps also the embedded scripts working. I used the info from here - i used a HTMLPanel and loaded the image via "RequestBuilder":
String url = GWT.getHostPageBaseURL() + link.getToken();
RequestBuilder rB = new RequestBuilder(RequestBuilder.GET, url);
rB.setCallback(new RequestCallback() {
#Override
public void onResponseReceived(Request request, Response response) {
//create Widget
chartImage = new HTMLPanel(response.getText());
//add to layout
layout.add(chartImage);
}
#Override
public void onError(Request request, Throwable exception) {
// TODO Auto-generated method stub
}
});