print capability in gwt - gwt

we have admin dashboard build in gwt and deployed on google app engine for java. On the dashboard there is a feature called "my card" where a blood donor can see his blood donor registration card with us.
Currently, we are creating and storing this card on google storage and when someone goes to "My Card" we render the card using iFrame in our dashboard.
We want to give the ability to print this card. Please tell how to do it?
just to add on i tried Print.it jar but seems like it is obsolete and does not play nice with gwt anymore

Add this script to the iframe content page's tag
<script type="text/javascript">
function printPage() {focus();print(); }
</script>
Add this native method to your GWT class
public native void printIframeContent(String id)/*-{
var iframe = $doc.getElementById(id);
var ifWin = iframe.contentWindow || iframe;
iframe.focus();
ifWin.printPage();
return false;
}-*/;
The action handler for print button's click event.
public void onClick(ClickEvent event) {
printIframeContent("printiframe"); // Use the correct id for your iframe
}
Code is derived from this discussion

Here is a simple Printer class for GWT. It prints out the page.
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.Element;
public class Printer {
public static native void it(String html) /*-{
var frame = $doc.getElementById('__printingFrame');
if (!frame) {
$wnd.alert("Error: Can't find printing frame.");
return;
}
frame = frame.contentWindow;
var doc = frame.document;
doc.open();
doc.write(html);
doc.close();
frame.focus();
frame.print();
}-*/;
public static void it(UIObject obj) {
it("", obj.getElement().toString());
}
public static void it(Element element) {
it("", element.toString());
}
public static void it(String style, String it) {
it("<it><header>"+style+"</header><body>"+it+"</body></it>");
}
public static void it(String style, UIObject obj) {
it(style, obj.getElement().toString());
}
public static void it(String style, Element element) {
it(style, element.toString());
}
}

Related

Pushing data from one user to another in Vaadin web app

I get the fact that it might take more than 10 lines of code (hopefully not more than 50), but I was wondering if you could help me anyway.
I'm trying to update one user's UI thread at runtime, based on another user's input. I've created a basic project which implements three predefined users (jim, tom and threeskin). I'd like to send a message from jim to tom and have it appear as a new Label object in tom's UI, without threeskin ever knowing about it, even though they're all logged in. Oh, and jim shouldn't have to refresh his page. The label should just spawn on screen out of it's own accord.
To say that I'd appreciate some help would be the understatement of the decade.
public class User {
public String nume;
public User(String nume) {
super();
this.nume = nume;
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
public class Engine implements ServletContextListener {
public static ArrayList<User>userbase;
public void contextDestroyed(ServletContextEvent arg0) { }
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("This code is running at startup");
userbase =new ArrayList<User>();
userbase.add(new User("jim"));userbase.add(new User("tom"));userbase.add(new User("threeskin"));
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
public class InfigeUI extends UI {
User us3r;
#WebServlet(value = "/*", asyncSupported = true)
#VaadinServletConfiguration(productionMode = false, ui = InfigeUI.class)
public static class Servlet extends VaadinServlet {}
protected void init(VaadinRequest request) {
VerticalLayout everything=new VerticalLayout();
setContent(everything);
if (us3r==null){everything.addComponent(auth());}else{everything.addComponent(main());}
}
ComponentContainer auth(){
final VerticalLayout layout = new VerticalLayout();
layout.setMargin(true);
TextField userField=new TextField();
Button login = new Button("Log in");
login.addClickListener(new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
us3r=login(userField.getValue());
if (us3r!=null){
saveValue(InfigeUI.this, us3r);
layout.removeAllComponents();
layout.addComponent(main());
}else{Notification.show("I only know jim, tom and threeskin. Which one are you?");}}
});
layout.addComponent(userField);
layout.addComponent(login);
return layout;
}
User login(String nume){
for (int i=0;i<Engine.userbase.size();i++){
if (nume.equals(Engine.userbase.get(i).nume)){return Engine.userbase.get(i);}
}
return null;
}
static void saveValue(InfigeUI ui,User value){
ui.us3r=value;
ui.getSession().setAttribute("something", value);
VaadinService.getCurrentRequest().getWrappedSession().setAttribute("something", value);
}
ComponentContainer main(){
VerticalLayout vl=new VerticalLayout();
Label label=new Label("This is the post-login screen");
String name=new String(us3r.nume);
Label eticheta=new Label(name);
TextField to=new TextField("Send to");
TextField message=new TextField("Message");
Button sendNow=new Button("Send now!");
vl.addComponent(eticheta);
vl.addComponent(label);
vl.addComponent(eticheta);
vl.addComponent(to);
vl.addComponent(message);
vl.addComponent(sendNow);
return vl ;
}
}
Basically you want three things
UI updates for a user which does no action himself, or in other words a message sent from the server to the browser. To enable this, you need to annotate the UI class using #Push. Otherwise, the update will only be shown when the user does something which causes a server visit, e.g. clicks a button
Some way of sending messages between UI instances (there is one UI instance per user). You can use some message bus implementation for this (CDI, Spring, ...) or you can make a simple on using a static field (static fields are shared between all users). See e.g. https://github.com/Artur-/SimpleChat for one way of doing it. It's also a good idea here to avoid all *.getCurrent methods as they in many cases will refer to another UI than you think (e.g. sender when you are in the receiver code), and you will do something else than you intend.
Safely update a UI when a message arrives. This is done using UI.access, also visible in the chat example.
First of all you need to enable the server push on your project help
based on Vaadin Documentation.
However, below code example will give what you want:
Create an Broadcast Listener Interface:
public interface BroadcastListener {
public void receiveBroadcast(final String message);
}
The Broadcaster Class:
public class Broadcaster {
private static final List<BroadcastListener> listeners = new CopyOnWriteArrayList<BroadcastListener>();
public static void register(BroadcastListener listener) {
listeners.add(listener);
}
public static void unregister(BroadcastListener listener) {
listeners.remove(listener);
}
public static void broadcast(final String message) {
for (BroadcastListener listener : listeners) {
listener.receiveBroadcast(message);
}
}
}
Your UI with Push Enalbed (via Annotation):
#Push
public class BroadcasterUI extends UI implements BroadcastListener {
#Override
protected void init(VaadinRequest request) {
final VerticalLayout layout = new VerticalLayout();
layout.setMargin(true);
setContent(layout);
final TextArea message = new TextArea("",
"The system is going down for maintenance in 10 minutes");
layout.addComponent(message);
final Button button = new Button("Broadcast");
layout.addComponent(button);
button.addClickListener(new Button.ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
Broadcaster.broadcast(message.getValue());
}
});
// Register broadcast listener
Broadcaster.register(this);
}
#Override
public void detach() {
Broadcaster.unregister(this);
super.detach();
}
#Override
public void receiveBroadcast(final String message) {
access(new Runnable() {
#Override
public void run() {
Notification n = new Notification("Message received",
message, Type.TRAY_NOTIFICATION);
n.show(getPage());
}
});
}
you can find the full link here.

Checking Internet Connection using SmartGWT or GWT?

How can we check if there is Internet connectivity in the application or not in SmartGWT or GWT? I have to determine that whether there is internet connection or not and based on that change the icon for Internet connectivity to either green or red so is there a way to do it in SmartGWT or GWT?
You can create a native method in which you create a new image object (new Image()) and attach handler to it's onload and onerror properties. You can point the image's src property to some URL that you feel indicates being online. Then from your onload and onerror methods you can call methods in your GWT component to update your connectivity indicator. You need to set img.src after you set img.onload and img.onerror.
For example:
native void checkConnectivity(Example obj) /*-{
var img = new Image();
img.onload = function() {
obj.#com.example.client.Example::online()();
}
img.onerror = function() {
obj.#com.example.client.Example::offline()();
}
img.src = "http://exampleapp.com/test.gif";
}-*/;
I think the navigator.onLine will help you:
http://html5demos.com/offline
http://www.html5rocks.com/en/features/offline
You may need to wrap the calls into JSNI and also implement an eventlistener.
public native Boolean isOnline()/*-{
return window.onLine;
}-*/;
Udeleng's solution is the closest i have come to a cross-browser approach. I have been testing it on FF 18 but i believe it will work in any browser.
However, note that the browser pre-loads the image when you call new Image(), caching it such that subsequent calls to the same URL don't make an HTTP call. This kills the effect we want to achieve i.e. transition from offline to online status works but as soon as the browser gets any connection, the image is cached, and end of story, even if you unplug your ethernet cable.
SOLUTION
Add a state parameter to the URL and give it a random number, the idea is to trick the browser into thinking its a new image such that the image is fetched from the server each time, rather than the cache.
Of course you need to add the timer. Here is my code:
import com.google.gwt.core.shared.GWT;
import com.google.gwt.user.client.Timer;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.Img;
import com.smartgwt.client.widgets.events.DrawEvent;
import com.smartgwt.client.widgets.events.DrawHandler;
public class WebConnChecker extends Img {
private static final String ONLINE="online_stat.jpg";
private static final String OFFLINE="offline_stat.jpg";
private static final int INTERVAL=10000;
private Timer timer;
public WebConnChecker(){
setSize(16);
timer=new Timer() {
#Override
public void run() {
checkConnectivity(WebConnChecker.this);
}
};
addDrawHandler(new DrawHandler() {
#Override
public void onDraw(DrawEvent event) {
timer.scheduleRepeating(INTERVAL);
}
});
}
private void online(){
log("online detected");
this.setSrc(ONLINE);
}
private void offline(){
log("offline detected");
this.setSrc(OFFLINE);
}
private native void checkConnectivity(WebConnChecker checker) /*-{
var img = new Image();
img.onload = function() {
window.alert("online");
checker.#com.telligent.smap.student.client.util.WebConnChecker::online()();
}
img.onerror = function() {
window.alert("offline");
checker.#com.telligent.smap.student.client.util.WebConnChecker::offline()();
}
img.src = "http://cdn.sstatic.net/stackoverflow/img/apple-touch-icon.png?v=41f6e13ade69&state="+Math.floor(Math.random() * 100);
}-*/;
}
Hope it works for you

GWT JSNI: pass js element to gwt Element will lose all children

I was trying to wrap some jquery function to GWT, run below js code, the size is 2.
var html="<div><p>paragraph</p><div>second</div></div>";
var size=$(html).get(0).children.length;
alert(size);
but run below GWT code
select(html).get(0).getChildCount();
just return 0, the select function is like below:
public class JQuery extends JavaScriptObject {
protected JQuery() {
}
public static final native JQuery select(String selector) /*-{
return $wnd.jQuery(selector);
}-*/;
public final native Element get(int index) /*-{
return this.get(index) || null;
}-*/;
}
I'd like to know why it just loses the children elements from JSNI method, and what's the right way to this wrapping to let it behave exactly same to native jquery?
Thanks.
-------------EDIT------------------------------------------------------------
I test above JSNI code in a real gwt project and it works fine, the children elements are returned from js to java. But in GwtTestCase problem exists.
public class JQueryTest extends GWTTestCase {
#Override
public String getModuleName() {
return "com.jsnitest.JsniTest";
}
public void testSelectHtml() {
ScriptInjector.fromUrl("http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js").setWindow(
ScriptInjector.TOP_WINDOW).setCallback(new Callback<Void, Exception>() {
#Override
public void onFailure(Exception reason) {
}
#Override
public void onSuccess(Void result) {
int childCount = select("<div><p>paragraph</p><div>second</div><ul></ul></div>").get(0).getChildCount();
//Fail! childCount=0
assertEquals(3, childCount);
}
}).inject();
}
}
gwtquery a.k.a. gQuery is a jQuery-like API written in GWT.
Following the principle of DRY, I would use this library instead of wrapping jQuery.
The only reason I see to wrap jQuery in GWT is that you needed very specific features in jQuery not present in gQuery, although gQuery has almost completed the jQuery API.

ClickHandler doesn't fire in jquery-mobile header & footer

after hours of searching and trying, I decided to ask here.
JqmHeader.java
public class JqmHeader extends ComplexPanel {
public JqmHeader() {
setElement(DOM.createDiv());
getElement().setAttribute("data-role", "header");
}
public void add(Widget widget) {
super.add(widget, getElement());
}
}
JqmPage.java
public class JqmPage extends ComplexPanel {
...
public JqmPage(String id) {
setElement(Document.get().createDivElement());
getElement().setAttribute("data-role", "page");
getElement().setAttribute("data-url", id);
RootPanel.get().add(page);
render(page.getId());
}
private native void render(String id) /*-{
$wnd.$("#" + id).page();
}-*/;
...
}
MyPage.java extends JqmPage.java
...
JqmHeader header = new JqmHeader();
Button b = new Button("TestButton");
b.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
Window.alert("TestButton clicked");
}
});
header.add(b);
this.add(header);
...
My Problem
So, my Problem is, that the ClickHandler from the Button in the header bar doesn't fire. If I add the Button not to the header, but to the "RootPage", like
this.add(b)
, everything works.
I think it must lie at the jquery-mobile header implementation. Are there any workarounds /ideas?
Thanks from Berlin,
Alex
JQuery Mobile swallows the events on headers so they are not propagated to GWT. What I did in solving this for jqm4gwt (https://github.com/sksamuel/jqm4gwt) was to have a general listener on the page level and then compare event source. If it was a button in the header then I fire that event on the button manually.
Take a look at bindHeaderEvents in https://github.com/sksamuel/jqm4gwt/blob/master/src/main/java/com/sksamuel/jqm4gwt/JQMPage.java
Also, the jqm4gwt project might be a good solution for you to save you having to invent all these widgets yourself.
If you want to take a look at a pure GWT solution for building mobile apps you could take a look at http://www.m-gwt.com

Using phonegap audio api in gwt

I am wanting to use the phonegap audio api in GWT using JSNI.I cannot figure out how to code the methods in JSNI.
Wondering if anyone know of any tutorials.They javascript methods are really pretty simple.
http://docs.phonegap.com/phonegap_media_media.md.html
Basically it sounds like it would be something like this:
public final class Media extends JavaScriptObject {
protected Media() {}
public static native final Media newInstance(String src, Command command) /*-{
var callback = function() { command.execute(); };
return new Media(src, callback);
}-*/;
public native final void getCurrentPosition(AsyncCallback<String> command) /*-{
var callback = function(position) { command.onSuccess('' + position); };
this.getCurrentPosition(callback);
}-*/;
public native final void play() /*-{
this.play();
}-*/;
//... more methods here
}
Usage:
Media m = Media.newInstance("http://www.example.com/src.mp3", new Command() {
#Override
public void execute() {
// Code executed after Media is created.
}
});
m.getCurrentPosition(new AsyncCallback<String>() {
#Override
public void onSuccess(String position) {
Window.alert(position);
}
});
m.play();
That's a rough sketch, if you know more about what the type being passed to the callback is you can do nicer things like have it be an int or another JS Overlay Type.
The API is kind of weird because everything is apparently asynchronous, but that's life.
Once you've gotten the hang of writing GWT JSNI bindings it's pretty straightforward.
If you end up getting further down this road, it would be awesome if you open-sourced your GWT wrapper library so other GWT developers could write some iPhone/Android apps.
I just need the play method really.I am not quite as knowledgeable to do this correctly I guess.That code looks really foreign to me :-)
Still cannot accept your answer.The site does not recognize me it is strange.
I get the following error when trying to use the media in my onModuleLoad
The constructor TESTPHONEGAP.Media(String, new Command(){}) is undefined
Media m = new Media("test.mp3", new Command() {
#Override
public void execute() {
}
});
m.play()
Using your class as an "inner class" in same file as my main onModuleLoad