PDA

View Full Version : Support for Printers



powerj
15 Sep 2008, 7:10 AM
Hi all.

I found ext-gwt and found it to be lovely, but there is a last little detail before i can present it to my boss.

It miss the feature of printing!

Every table, tab, textbox in our application shud be able to print out on paper, but if i print a table made by gwt, i just get a really bad output and the full page always follows.

SOLUTION:

The way to do this must be by adding another onRender(Element t) function on Components class, add onRenderPrint(Element t) that defaults call to onRender(t) that you could overwrite and add custom rendering functions when the page is built up for printing.

The print will follow these steps.

1, The user pushes a print button on a panel that he wants to print.
2, The panel then creates a hidden iframe in page body.
3, Then the empty iframe will be filled by calling that panels all elements onRenderPrint() instead of onRender(), this will make component makers have a choise of diffrent renders for screen and print, and can make table rendering for example, printer friendly, remove all buttons and interactive elements, use printer-stylesheets and so on...
4, window.print() is executed
5, and when done, the iframe is removed.

Whit this solution, every panel or object can be printed, so you can print tabs not only the full page.

Can anyone give me a tip, on how to get started?

Regards
Jimmy Wennlund

darrellmeyer
15 Sep 2008, 10:05 AM
Another approach would be to create some utility code that can take a grid and render it as a simple HTML based table using the grid, store, and column model. You could have a print button which opens a new window with the simple table that the user could print.

Another approach would be to navigate the grids dom and create the same simple HTML table based on the grids elements and contents.

Also, components can only be rendered once, so having multiple render methods will only work when creating multiple grid instances.

powerj
15 Sep 2008, 11:55 AM
Having print-support in the framework sounds like a mutch better solution becouse you can specify while making the components how the component shud look like when render on screen, and how it looks like on print.

And when you add these components on a Panel, the panel might also have diffrent ways how to render their sub-elements depending if there is screen or print render.

Why is that you only can render a element once? I thout that you could only construct a object once, but render it how many times you want. How deep into the framework is this limit?

If you are sighting for real web-applications like mail-clients or word-alikes you really have to start thinking how the user shud be able to print out her email. Maby you can add print-support to your mail-example-app.

Thank you for your time.

/Jimmy

TheBuzzer
16 Sep 2008, 1:59 PM
i would suggest you try out iText.

free open source pdf generator.

Makes lovely print pages if you design it well.

Print normally does not look the same on all browsers and it is even harder to print stuff that is javascript .

So a javascript that generates a normal html page will work but that is just like making a new layout just for printing and I think using the pdf approach will be nicer looking in the end

gslender
16 Sep 2008, 2:11 PM
I think what TheBuzzer said makes the most sense - most users understand the concept that when you click on print, you don't get a screenshot of the application sent to the printer - you get a special rendered version for the printer that contains the data. In the case of Word processing, its obviously the typed page contents correctly formatted, but not the menu bar and tool bars. In the case of email, its not the entire folders, inbox list and current message, but only a specially laid out version of the current msg - same goes for calendars and other systems that print. Printing is rarely the full application render and GXT is both application and data in one system.

The "use iText and produce a PDF" is a good concept as it gives the user the option of saving as document or printing right there and then.

In saying that, I'm sure Google are thinking of ways to change this and make browser printing a concept not much different to printing within the windows/osx client environments.

powerj
17 Sep 2008, 12:45 AM
The printer-support in web-browsers is really useless, its impossible to make borderless-prints, and you can in javascript override the print-page button, or call the print-preview window.

In the current solution we have, we have pages in a i frame, and the iframe can be printed.
When designing the pages we use diffrent style-sheets for screen and print set by the media tag. The quality of the prints with tables is really good, so we dont really need pdf-output for what we are doing.

Its really lot of work render every page as a gwt-component and also as a pdf-file if user also wants to print it, does it not really exists a mutch simpler way?

kym
30 Jul 2013, 5:20 PM
I have not seen anything since the 2008 queries about having print available in GWT. Is it still, in the year 2013, not available?:((

Colin Alworth
8 Aug 2013, 8:56 AM
TheBuzzer and gslender had it right - there are lots and lots of cases where you might *not* want a full application to be able to print itself. Simple examples:
* Popups
* Active Tooltips
* Active Menus
* Running animations

Then there are layout cases - if I have two grids side by side, each with a scrollbar, but the first has 1000 items and the second 100, do I really want them drawn side by side on the paper (and leave dead space for 9x the length of the first)? Or do I want one over the other? Should the short one come first, or the one on the left?

Next the fact that the browser doesn't know what size paper you'll be printing to, and as the page layout routine runs, the JS doesn't get 'resize' events to rebuild itself to fit...

All of these considerations make it practically impossible to design a way to print from within a library meant for application layouts. The library can't be responsible for this, since it doesn't know what data you are trying to work with.

That said, printing is fairly straightforward - look at other online applications for the basic steps:
* User decides to print (typically they select something or hits a specific print button), and signals this to the app
* The app opens a popup to draw *only* the material to be printed out
* Content to be printed is written to that new popup, probably by either copying the DOM structures, or by using an XTemplate against the data to display.
* The print() function is invoked to ask the browser to print.

Here is a quick sample JSNI method that takes a string of HTML content devised to fit your needs and draws a popup with it to be printed. This is just a sample and may need to be tweaked to fit your needs (setting a title, waiting for css/images to load, sizing, etc). Tested briefly in firefox and chrome:


public static native void popupAndPrint(String htmlContent) /*-{
var popup = window.open('about:blank');

popup.document.write(htmlContent);

popup.print();
}-*/;

With that method at our disposal, here is a quick set of changes to make to the Basic Grid example to make it able to generate some text that can be printed. This has essentially no formatting to keep the code sample short - the template can be changed to describe exactly what you need in your output.

First, we need the above method and a template. This is the part that needs to be customized to fit your needs:


public interface PrintGridTemplate extends XTemplates {
@XTemplate("<tpl for='.'><div>{name}: {last}</div></tpl>")
SafeHtml print(List<Stock> items);
}


Next, and finally, we add a button to the grid container that will run this template on the items in the store, and pass it off to the method we wrote to print it. This goes near the end of the asWidget() method, after the grid and toolbar are both added.


con.add(new TextButton("Print Grid", new SelectHandler() {
@Override
public void onSelect(SelectEvent event) {
PrintGridTemplate template = GWT.create(PrintGridTemplate.class);
popupAndPrint(template.print(store.getAll()).asString());
}
}), new VerticalLayoutData(-1, -1));



There is more than one right way to do all of this of course, this is just the first idea that came to mind and the quickest/simplest implementation I could write to share here. The two important takeaways:
* This isn't hard to write or to customize, and
* This cannot be done in the library itself as the printout shouldn't look like a browser window with scrollbars.