how to load a svg in gwt widget from an url - gwt

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
}
});

Related

Show loading Screen while Image is loading in 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;
}
});

Inject css stylesheet in GWT RichTextArea head

is it possible to inject a stylesheet into the head of a GWT RichTextArea
Seems as if i place a style element in the body, some browser e.g. IE7 allows the user to delete the node.
I had the same problem, here's the solution to add in the class constructor:
richTextArea.addInitializeHandler(new InitializeHandler() {
public void onInitialize(InitializeEvent ie) {
document = IFrameElement.as(richTextArea.getElement()).getContentDocument();
StyleElement se = document.createStyleElement();
se.setType("text/css");
se.setInnerHTML("some CSS");
BodyElement body = document.getBody();
body.getParentNode().getChild(0).appendChild(se);
}
});
StlyeInjector can directly insert CSS if you don't want to use a CSS file. It gets put into the head as far as I can tell, but for the whole document.
Yes it is. But you need a library like gwtquery to manipulate the dom, or code some jsni.
I'd rather gquery because of its simplicity and it will work with all browsers.
import static com.google.gwt.query.client.GQuery.*;
// First attach the widget to the DOM
RootPanel.get().add(richTextArea);
// We only can manipulate the head, once the iframe document has been created,
// and this happens after it has been attached.
// Because richtTextArea uses a timeout to initialize we need a delay.
$(richTextArea).delay(1,
lazy()
.contents()
.find("head")
.append("<style> body{background: red} </style>")
.done());
With GWT + JSNI you have to do something like this (not tested in all browsers though):
// First attach the widget to the DOM
RootPanel.get().add(richTextArea);
// We only can manipulate the head, once the iframe document has been created,
// and this happens after it has been attached.
// Using a timer because richtTextArea uses a timeout to initialize.
Timer insertCss = new Timer() {
private native Element getHeadElement(Element iframe) /*-{
return iframe.contentWindow.document.head;
}-*/;
public void run() {
Element head = getHeadElement(richTextArea.getElement());
Element style = DOM.createElement("style");
style.setInnerText("body{background: yellow}");
head.appendChild(style);
}
};
// Schedule the timer
insertCss.schedule(1);

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: 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.

GWT Progress Bar while buffering PDF content before displaying on browser

In my GWT app I have written a servlet to download/stream a PDF file.
Following is the code.
protected void updateResponse(HttpServletResponse response, InputStream dataStream, long contentLength, KnownContentTypes contentType, String filename, int cacheSeconds) {
response.setHeader("Content-Type", contentType.getTypeString());
response.setHeader("Content-Length", String.valueOf(contentLength));
response.setHeader("Content-disposition", "inline;filename=" + filename);
response.setHeader("Cache-Control", "max-age=" + cacheSeconds);
byte[] buffer = new byte[BUFFER_SIZE];
try {
ServletOutputStream out = response.getOutputStream();
while ((dataStream.read(buffer)) != -1) {
out.write(buffer);
}
} catch (IOException e) {
sendError(response);
}
}
The pdf is successfully rendered on the browser.
The problem is some pdf's are really large in size and since this is called on window.open all I see is a blank browser.
I want to display a dynamic message like '1MB of 5MB downloaded' and display/render the entire PDF file once all bytes are streamed.
Please let me know how to do this.
I am new to GWT and any help will be appreciated.
Thanks.
This can not be done with synch request which we usually make by calling servlet with Window.open You have to make ajax request to calculate progress and display the response.
Take a look to this library: http://code.google.com/p/gwtupload/. It is really easy to to use and works fine in most of the browsers. It uses ajax requests to calculate progress.