Problem with GWT Widget Printing

803 views
Skip to first unread message

HommeDeJava

unread,
Apr 3, 2009, 2:53:44 PM4/3/09
to Google Web Toolkit
Greetings folks,

I have an application developed in GWT and I would like to print tall
GWT widgets (i.e. taller than one page).
I found a method that works with Safari and Chrome browsers but it
didn't work with FireFox.
Maybe, it's related to the fact that Safari and Chrome are based on
the Webkit html rendering technology while Firefox is based on Gecko.

Anyway, I have tried to find a new approach.

So, I have just tested the Print class from Andre Freller (the latest
version) in order to print GWT widgets.

http://groups.google.com.my/group/Google-Web-Toolkit/browse_thread/thread/5bf6997b00dca94a?hl=en

I don't know why but in all my tests trying to print any widget (even
a short one) result in printing a frustratng (toString()) type of
message like [object HTMLDivElement] or [object]

Many people seems to succeed using this code, so I'm wondering what I
could missed...

So, I'm posting on the GWT Google Group, maybe someone else has
encountered the same problem and found a solution.

I've done my test using Windows XP, GWT 1.5.3 and FireFox 3.0.8,
Chrome, IE 7 and Safari 3

So below, you will find the code have wrote to benchmark along with
the printing class

Thanks fo any help you can provide

Claude Coulombe
OpenSyllabus project
Montreal

--------------------------------------------------------------------------------------------
the PrintTest.html file
--------------------------------------------------------------------------------------------

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html;
charset=UTF-8">
<!-- -->
<!-- Any title is fine -->
<!-- -->
<title>PrintTest</title>

<!-- -->
<!-- This script loads your compiled module. -->
<!-- If you add any GWT meta tags, they must -->
<!-- be added before this line. -->
<!-- -->
<script type="text/javascript" language="javascript"
src="br.com.freller.tool.PrintTest.nocache.js"></script>
</head>

<!-- -->
<!-- The body can have arbitrary html, or -->
<!-- you can leave the body empty if you want -->
<!-- to create a completely dynamic UI. -->
<!-- -->
<body>

<!-- Test Andre Freller Printing Class -->
<iframe id="__printingFrame" style="width:0;height:0;border:0"></
iframe>
<div id="printPageButton"></div>
<div id="printWidgetButton"></div>
<div id="printDOMByIdButton"></div>
<div id="printStyleWidgetButton"></div>
<div id="tallWidget"></div>

</body>
</html>

--------------------------------------------------------------------------------------------
the PaperPrintTest.css file
--------------------------------------------------------------------------------------------

body {
float:none;
position:relative;
background-color: white;
overflow: visible;
}

.TallWidgetStyle {
background-color: #C3D9FF;
padding: 2px;
margin: 2px;
font-size: 10px;
font-weight: normal;}

.TallWidgetPaperStyle {
float:none;
position:relative;
background-color: white;
overflow: visible;
font-weight: bold;
}

--------------------------------------------------------------------------------------------
the PrintTest.gwt.xml file
--------------------------------------------------------------------------------------------
<module>

<!-- Inherit the core Web Toolkit stuff.
-->
<inherits name='com.google.gwt.user.User'/>

<!-- Inherit the default GWT style sheet. You can change
-->
<!-- the theme of your GWT application by uncommenting
-->
<!-- any one of the following lines.
-->
<inherits name='com.google.gwt.user.theme.standard.Standard'/>
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/>
-->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/>
-->

<!-- Other module inherits
-->

<!-- Specify the app entry point class.
-->
<entry-point class='br.com.freller.tool.client.PrintTest'/>

<!-- Specify the application specific style sheet.
-->
<stylesheet src='PaperPrintTest.css' />

</module>
--------------------------------------------------------------------------------------------
the Print.java file (the Printing class from Andre Freller)
--------------------------------------------------------------------------------------------

package br.com.freller.tool.client;

/**
* <pre>
* Generic printing class
* can be used to print the Window it self, DOM.Elements, UIObjects
(Widgets) and plain HTML
* package br.com.freller.tool.client;
* Usage:
* You must insert this iframe in your host page:
* <iframe id="__printingFrame" style="width:0;height:
0;border:0"></iframe>
*
* Window:
* Print.it();
*
* Objects/HTML:
* Print.it(RootPanel.get("myId"));
* Print.it(DOM.getElementById("myId"));
* Print.it("Just <b>Print.it()</b>!");
*
* Objects/HTML using styles:
* Print.it("<link rel='StyleSheet' type='text/css'
media='paper' href='/paperStyle.css'>", RootPanel.get('myId'));
* Print.it("<style type='text/css'
media='paper'> .newPage { page-break-after: always; } </style>", "Hi<p
class='newPage'></p>By");
* </pre>
*/

import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.UIObject;

public class Print {

public static native void it() /*-{
$wnd.print();
$wnd.alert("I am printing a page.");
}-*/;

public static native void buildFrame(String html) /*-{
var frame = $doc.getElementById('__printingFrame');
if (!frame) {
$wnd.alert("Error: Can't find printing frame.");
return;
}
var doc = frame.contentWindow.document;
doc.open();
doc.write(html);
doc.close();
$wnd.alert("I have build a printing frame.");
}-*/;

public static native void printFrame() /*-{
var frame = $doc.getElementById('__printingFrame');
frame = frame.contentWindow;
frame.focus();
frame.print();
$wnd.alert("I am printing the frame.");
}-*/;

public static class PrintFrame implements Command {
public void execute() {
printFrame();
}
}

public static PrintFrame printFrameCommmand = new PrintFrame();

public static void it(String html) {
try {
buildFrame(html);
DeferredCommand.addCommand(printFrameCommmand);
} catch (Throwable exc) {
Window.alert(exc.getMessage());
}
}

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("<html><head>"+style+"</head>\n<body>"+it+"</body></html>");
}

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

Greetings folks,

I have an application developed in GWT and I would like to print tall
GWT widgets (i.e. taller than one page).
I found a method that works with Safari and Chrome browsers but it
didn't work with FireFox.
Maybe, it's related to the fact that Safari and Chrome are based on
the Webkit html rendering technology while Firefox is based on Gecko.

Anyway, I have tried to find a new approach.

So, I have just tested the Print class from Andre Freller (the latest
version) in order to print GWT widgets.

http://groups.google.com.my/group/Google-Web-Toolkit/browse_thread/thread/5bf6997b00dca94a?hl=en

I don't know why but in all my tests trying to print any widget (even
a short one) result in printing a frustratng (toString()) type of
message like [object HTMLDivElement] or [object]

Many people seems to succeed using this code, so I'm wondering what I
could missed...

So, I'm posting on the GWT Google Group, maybe someone else has
encountered the same problem and found a solution.

I've done my test using Windows XP, GWT 1.5.3 and FireFox 3.0.8,
Chrome, IE 7 and Safari 3

So below, you will find the code have wrote to benchmark along with
the printing class

Thanks fo any help you can provide

Claude Coulombe
OpenSyllabus project
Montreal

--------------------------------------------------------------------------------------------
the PrintTest.html file
--------------------------------------------------------------------------------------------

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html;
charset=UTF-8">
<!-- -->
<!-- Any title is fine -->
<!-- -->
<title>PrintTest</title>

<!-- -->
<!-- This script loads your compiled module. -->
<!-- If you add any GWT meta tags, they must -->
<!-- be added before this line. -->
<!-- -->
<script type="text/javascript" language="javascript"
src="br.com.freller.tool.PrintTest.nocache.js"></script>
</head>

<!-- -->
<!-- The body can have arbitrary html, or -->
<!-- you can leave the body empty if you want -->
<!-- to create a completely dynamic UI. -->
<!-- -->
<body>

<!-- Test Andre Freller Printing Class -->
<iframe id="__printingFrame" style="width:0;height:0;border:0"></
iframe>
<div id="printPageButton"></div>
<div id="printWidgetButton"></div>
<div id="printDOMByIdButton"></div>
<div id="printStyleWidgetButton"></div>
<div id="tallWidget"></div>

</body>
</html>

--------------------------------------------------------------------------------------------
the PaperPrintTest.css file
--------------------------------------------------------------------------------------------

body {
float:none;
position:relative;
background-color: white;
overflow: visible;
}

.TallWidgetStyle {
background-color: #C3D9FF;
padding: 2px;
margin: 2px;
font-size: 10px;
font-weight: normal;}

.TallWidgetPaperStyle {
float:none;
position:relative;
background-color: white;
overflow: visible;
font-weight: bold;
}

--------------------------------------------------------------------------------------------
the PrintTest.gwt.xml file
--------------------------------------------------------------------------------------------
<module>

<!-- Inherit the core Web Toolkit stuff.
-->
<inherits name='com.google.gwt.user.User'/>

<!-- Inherit the default GWT style sheet. You can change
-->
<!-- the theme of your GWT application by uncommenting
-->
<!-- any one of the following lines.
-->
<inherits name='com.google.gwt.user.theme.standard.Standard'/>
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/>
-->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/>
-->

<!-- Other module inherits
-->

<!-- Specify the app entry point class.
-->
<entry-point class='br.com.freller.tool.client.PrintTest'/>

<!-- Specify the application specific style sheet.
-->
<stylesheet src='PaperPrintTest.css' />

</module>
--------------------------------------------------------------------------------------------
the PrintTest.java file (my testing class)
--------------------------------------------------------------------------------------------

package br.com.freller.tool.client;

import br.com.freller.tool.client.Print;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class PrintTest implements EntryPoint {

private static class TallWidget extends Composite {

public TallWidget() {
super();
VerticalPanel container = new VerticalPanel();
container.setHorizontalAlignment
(HasHorizontalAlignment.ALIGN_CENTER);
container.add(new Label("Andre Freller Class Printing Test"));
TextArea textContainer = new TextArea();
textContainer.setHeight("10000px");
String veryLongText =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Phasellus laoreet sollicitudin leo. " +
"Suspendisse erat enim, lacinia et, aliquet ut, dictum sit amet,
nisl. Integer fermentum dolor " +
"sed augue. Nam suscipit, felis eu consequat rutrum, urna lorem
pellentesque velit, ut sollicitudin " +
"ante neque in felis. Suspendisse pharetra, tellus eget malesuada
dignissim, lectus velit feugiat " +
"augue, facilisis convallis ante felis id urna. Ut non sem. Fusce
vestibulum auctor enim. Donec " +
"vestibulum dui eu nulla. Sed nibh. Integer feugiat pharetra
urna. Integer tempus tellus condimentum " +
"risus. Maecenas viverra nunc eget massa. Nullam libero felis,
vestibulum id, sollicitudin eu, congue " +
"vitae, lorem. Nullam urna arcu, faucibus at, condimentum eu,
semper quis, erat. Vivamus ultrices nunc " +
"vitae lorem. Duis vehicula mauris quis libero. Integer elit.
Proin id justo. Donec eget ipsum." +
" copy and paste as many times as needed the above paragraph ";
textContainer.setText(veryLongText);
container.add(textContainer);
container.setBorderWidth(2);
initWidget(container);
this.addStyleName("TallWidgetStyle");
}
}

public void onModuleLoad() {
final TallWidget myWidget = new TallWidget();

RootPanel.get("tallWidget").add(myWidget);

Button printPageButton = new Button("Print Page");
printPageButton.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
myWidget.addStyleName("TallWidgetPaperStyle");
Print.it();
myWidget.removeStyleName("TallWidgetPaperStyle");
}
});
RootPanel.get("printPageButton").add(printPageButton);

Button printWidgetButton = new Button("Print TallWidget");
printWidgetButton.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
myWidget.addStyleName("TallWidgetPaperStyle");
Print.it(RootPanel.get("tallWidget"));
myWidget.removeStyleName("TallWidgetPaperStyle");
}
});
RootPanel.get("printWidgetButton").add(printWidgetButton);

Button printDOMByIdButton = new Button("Print DOM TallWidget");
printDOMByIdButton.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
myWidget.addStyleName("TallWidgetPaperStyle");
Print.it(DOM.getElementById("tallWidget"));
myWidget.removeStyleName("TallWidgetPaperStyle");
}
});
RootPanel.get("printDOMByIdButton").add(printDOMByIdButton);

Button printStyleWidgetButton = new Button("Print TallWidget with
Style");
printStyleWidgetButton.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
myWidget.addStyleName("TallWidgetPaperStyle");
Print.it("<link rel=StyleSheet type=text/css media=paper
href=PaperPrintTest.css>",RootPanel.get("tallWidget"));
myWidget.removeStyleName("TallWidgetPaperStyle");
}
});
RootPanel.get("printStyleWidgetButton").add
(printStyleWidgetButton);
}
}



jay

unread,
Apr 3, 2009, 5:27:29 PM4/3/09
to Google Web Toolkit
It seems that prior to GWT 1.5, element.toString() did the right
thing. When I moved to GWT 1.5.3, I had to switch to using
"DOM.toString( elem );"

jay

On Apr 3, 11:53 am, HommeDeJava <claude.coulo...@gmail.com> wrote:
> Greetings folks,
>
> I have an application developed in GWT and I would like to print tall
> GWT widgets (i.e. taller than one page).
> I found a method that works with Safari and Chrome browsers but it
> didn't work with FireFox.
> Maybe, it's related to the fact that Safari and Chrome are based on
> the Webkit html rendering technology while Firefox is based on Gecko.
>
> Anyway, I have tried to find a new approach.
>
> So, I have just tested the Print class from Andre Freller (the latest
> version) in order to print GWT widgets.
>
> http://groups.google.com.my/group/Google-Web-Toolkit/browse_thread/th...
> http://groups.google.com.my/group/Google-Web-Toolkit/browse_thread/th...

HommeDeJava

unread,
Apr 3, 2009, 5:56:54 PM4/3/09
to Google Web Toolkit
Hi Jay,

Using DOM.toString(obj.getElement()) I get something more usable.
no more [object HTMLDivElement] or [object]

There's still some problems but I'm out of the dark age!

Thank you so much!

Claude
> ...
>
> read more »

Freller

unread,
Apr 5, 2009, 12:31:39 PM4/5/09
to Google Web Toolkit

The beauty of open source! I haven't migrated to 1.5 yet, so this
error is new to me.
We will jump directly to 1.6. The Print class boil down to :

public static void it(String html) {
try {
buildFrame(html);
DeferredCommand.add(printFrameCommmand);
} catch (Throwable exc) {
Window.alert(exc.getMessage());
}
}

public static void it(String style, String it) {
it("<html><head>"+style+"</head>\n<body>"+it+"</body></
html>");
}

I did that so we could print both DOM elements and strings.
Perhaps I should treat DOM elements diferently adding them to the DOM
instead
of using the toString method? Anybody know if this will render faster
and/or more
correct prints?

Jay, does this work for both 1.4 and 1.5 or it'll only work on 1.5?

Regards,
Freller

HommeDeJava

unread,
Apr 6, 2009, 10:50:01 AM4/6/09
to Google Web Toolkit
Greetings,

How about replacing DeferredCommand.add(printFrameCommmand); which is
deprecated
by DeferredCommand.addCommand(printFrameCommmand);

Claude

jay

unread,
Apr 6, 2009, 1:42:23 PM4/6/09
to Google Web Toolkit
I'm not sure what you're asking... If you're asking if you can pass a
DOM element to your "it" method and have it work, then in 1.5 the
answer is no...the implicit toString() call won't do what it does in
1.4. Which is why in 1.5 you need to use the DOM.toString() method...

(If you're asking something else, then I apologize for not answering
it.)

jay

HommeDeJava

unread,
Apr 6, 2009, 2:31:50 PM4/6/09
to Google Web Toolkit
Hi Jay,

It's working fine now with the DOM.toString() method you have
suggested

I was speaking about the deprecated method DeferredCommand.add...

Sorry if I had been confusing!

Thanks a lot for your great solution!

Claude

Andre Freller

unread,
Apr 7, 2009, 10:44:16 AM4/7/09
to Google-We...@googlegroups.com

Hi Jay,

I was wondering if DOM.toString() works too on 1.4, I tested and it does work.

I'll post a new version so it will work on 1.5 too.

Regards,
Freller

Freller

unread,
Apr 8, 2009, 2:07:45 PM4/8/09
to Google Web Toolkit

So here you can find the last version of Print.it. It works for both
1.4 and 1.5.
You can supply a DOCTYPE do be used to render the printing frame
and you can alter the way the printing frame is generated and printed
on slow machines,

http://code.google.com/p/gwt-print-it/source/browse/trunk/src/br/com/freller/tool/client/Print.java

/**
* <pre>
*
* Description:
*
* Generic printing class
* Can be used to print the Window it self, DOM.Elements,
UIObjects (Widgets) and plain HTML
*
* Usage:
*
* You must insert this iframe in your host page:
* <iframe id="__printingFrame" style="width:0;height:
0;border:0"></iframe>
*
* Window:
* Print.it();
*
* Objects/HTML:
* Print.it(RootPanel.get("myId"));
* Print.it(DOM.getElementById("myId"));
* Print.it("Just <b>Print.it()</b>!");
*
* Objects/HTML using styles:
* Print.it("<link rel=StyleSheet type=text/css
media=paper href=/paperStyle.css>", RootPanel.get("myId"));
* Print.it("<style type=text/css media=paper> .newPage
{ page-break-after: always; } </style>",
* "Hi<p class=newPage></p>By");
*
* Objects/HTML using styles and DocType:
* Print.it("<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML
4.01//EN' 'http://www.w3.org/TR/html4/strict.dtd'>",
* "<link rel=StyleSheet type=text/css
media=paper href=/paperStyle.css>",
* RootPanel.get("myId"));
*
* OBS:
*
* Warning: You can't use \" in your style String
*
* Obs: If your machine is to slow to render the page and you
keep getting blank pages, change USE_TIMER to true and
* play with TIMER_DELAY
*
* Obs: If you try to print Form elements, like TextArea and
ListBox they will show default status
*
* </pre>
*/

mel

unread,
Jun 4, 2009, 3:22:09 PM6/4/09
to Google Web Toolkit
Slightly different problem than one being discussed above but I think
fits under the heading.

I am using a slight variation of Andre Feller's Print class for
printing EPL text codes to a printer. Here is the code:

<code>
public static native void printTextPlain(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('text/plain', 'replace');
doc.write(html);
doc.close();
for (var cii=0; cii < 100000; cii++){}
frame = $doc.getElementById('__printingFrame');
frame = frame.contentWindow;
frame.focus();
frame.print();
}-*/;
</code>

What I Am Printing:
I am sending a text string containing EPL codes for printing barcodes.
Example shown below:


Code starts below -- This line not for printing

N
A100,0,0,1,1,1,N,"Line 1"
A100,20,0,1,1,1,N,"Line2"
b100,30,D,h5,"Line3"
P1

Code ends above -- This line not for printing


How:
Server generates the EPL codes shown above and sends it back to the
browser.

I receive the string (as plain text using US-ASCII character set) and
pass it on the printing function shown above. As you can see the text
string includes CRLF characters or \n characters.


The Problem:
What is supposed to happen is that the printer (specific brand is
ZEBRA) interprets the codes and prints a combination of text and
barcodes. If I copy the above codes into a text editor (e.g. notepad)
and hit print, the barcodes are printed just fine.

If I send the above string to a printer that does not know how to
interpret the EPL, it prints the plan text as seen, which is what I
expect.

If however I send the same string above to the ZEBRA printer using the
printing function and a hidden frame, nothing is printed and the
printer does not respond. To me this is an indication that the browser
is adding addtional characters to the string that causes
the printer to be unable to interpret the codes as EPL and so it does
not print.

***Note that I make certain to make open the DOM document as text/
plain so that it does not interpret the text as html.

Also when I send the text string from the server, I set the content
type to "text/plain;charset=us-ascii");

What I don't know is whether the new document I open uses the same
charset set in the server response header?

I also dont know (nor do I know how to check) whether additional
characters are being added to the text string by the browser before
submitting the print job to the printer. I think it is adding addition
characters since if I copy the string into a text editor, everything
works just fine.

Any ideas.


Thanks,


Melody
Reply all
Reply to author
Forward
0 new messages