JimHagan / wwwsqldesigner

Automatically exported from code.google.com/p/wwwsqldesigner
BSD 3-Clause "New" or "Revised" License
0 stars 0 forks source link

Printing function #70

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
(new feature request)

Hi,

There is something really missing in wwwsqldesigner : the option to 
download the designed database as PDF (or something else for printing).

I tried the "print" function built in the browser, but in chrome I have 
very bad results and with firefox I have partial schema with random 
behavior.

> My tests drove me to something pretty well working. The idea is to send 
XML + tables coords & dimensions + relations coords & dimensions to a PHP 
script.

To achieve so on my test installation I reused some FPDF work I wrote in 
the past, with a Bezier implementation that mostly matches what you did in 
the JS file.

Have a look : http://maintenance.netsoins.org/dbdesign/ (topright button 
"print" or "Imprimer").

There is some few bugs (bottom borders are too large, relations doesnt 
match perfectly the row...).

I can't give you the PHP code since it is under licence, but the idea is to 
use the DOM, since all work has already been done on the client side.

Best regards,
Geompse

PS : in the JS file, I did this :

SQL.IO.prototype.print = function() {
    var xml = this.owner.toXML();
    var bp = this.owner.getOption("xhrpath");
    var url = bp + "print.php";
    var relations = this.owner.relations;
    var tables = this.owner.tables;

    var data = 'xml='+encodeURIComponent(xml);
    for(var i=0; i<relations.length; i++)
    {
        var r = relations[i];
        if(r.hidden)
            continue;
        data += 
'&rel[]='+r.drawType+'|'+r.p1[0]+'|'+r.p1[1]+'|'+r.p2[0]+'|'+r.p2[1]+'|'+r.
px+'|'+encodeURIComponent(r.color);
    }
    for(var i=0; i<tables.length; i++)
    {
        var t = tables[i];
        data += 
'&tbl[]='+encodeURIComponent(t.getTitle())+'|'+t.x+'|'+t.y+'|'+t.dom.contai
ner.offsetWidth+'|'+t.dom.container.offsetHeight;
    }
    OZ.Request(url, 
function(x){if(x=='OK')document.location=url.replace('.php','.pdf');else 
alert(x);}, {method:"post", data:data});
}

(Note that it requires type,p1,p2,x(actually half or x),color to be stored 
in the SQL.Relation, and that the php file is "print.php" and the pdf file 
is stored server-side under "print.pdf")

Original issue reported on code.google.com by geompse@gmail.com on 12 Mar 2010 at 10:23

GoogleCodeExporter commented 9 years ago
Hi,

this is a very ambitious feature! Your current version seems to work pretty 
well.
However, I am not very happy with the need to serialize table+relation data in 
order
to post them to the printing endpoint. I see two other possible aproaches here:

1) send the normal XML representation to the endpoint. No duplicate code on 
client,
ability to print saved design directly from database. However, server must be 
aware
of the algorithm used to draw and position relations.

2) send OZ.$("area").innerHTML to the endpoint. This is a valid XHTML fragment,
containing all necessary SVG/VML information for relation rendering.

What is your opinion?

Original comment by ondrej.zara on 14 Mar 2010 at 8:59

GoogleCodeExporter commented 9 years ago
I would say that the transport does not matter. As long as you can get the 
infos from 
the server side, it's cool.
- XML is good but I use it when human interaction might be needed 
(ex:config.xml)
- HTML is good but I think it will be too weighty (mostly because of the 
style="background-color: rgb(r, g, b)" on each row)
- JSON is good, lightweight BUT there is no native json_encode function 
client-side
For performance, you shall consider the delays for generation and sending...

I suggest you use XML, since you use it already for the schema data.

What you shall keep in mind :
- don't duplicate the code, else if you enhance your JS you will have to 
enhance the 
PHP the same way -> loss of time
- don't use what is read from the database, but what the user made in his 
browser
- don't send unneeded informations (like the keys, types, relation names...), 
all you 
need are :
    - tables names, dimensions (w,h), coordinates (x,y)
    - row names, style (bold or not, color)
    - relation drawing data (side or normal, x0,y0, x1,y1, half or x, color)

If the future, let's imagine you put some italic on the rows featuring an INDEX 
clause. All you will have to do is to send in the XML the info 'row style 
(italic or 
not)', and add a condition in the PHP script.

An even better example : imagine you made a positioning algorithm (like I did 
but 
it's not awesome enough), you can't afford to dev+test+debug it both in JS and 
PHP...

Not related to your question, but I ran into :
 - removal of the top left margin : all coordinates (x,y) shall translate to (X=x-
mx,Y=y-my)
 - dynamic pdf dymensions : create a PDF page of
       - w = max(tableX+tablew)+padding
       - h = max(tableY+tableh)+padding
     (this was longly think, because I first wanted the PDF to be A4-based, but 
actually it is bound to the final user to manage to print the document)
 - drawing the relations : not as easy as with SVG, in PDF you have lines. What I did 
was to map the Bezier curve with dots and then I drew lines between them. The 
difficulty is to temper between PDF size and PDF speed. May the curve take a w 
x h 
rectangle. I map the curve with max(20,(abs(w)+abs(h))/10) points and I link 
them 
together. It makes a correct file size with a correct redraw delay.
 - fonts in PDF might not have the same size as in your browser (well, mostly because 
I made some css modifications : letter-spacing:-1px, font-size:80%), so the wxh 
of 
the HTML tables might not be the same in PDF, that's why a larger border is 
shown on 
the bottom of my tables. I did not correct this since the relations are well 
connected to their rows... but it might still be an issue.

Original comment by geompse@gmail.com on 14 Mar 2010 at 12:25

GoogleCodeExporter commented 9 years ago
There will always be some kind of duplicity. For instance, most of the styling 
right
now is done via CSS, so the JS app has virtually no information about *how* 
does the
output actually look like. This info cannot be easily transferred to server 
side...

Original comment by ondrej.zara on 14 Mar 2010 at 7:31

GoogleCodeExporter commented 9 years ago
YES !

The biggest issue is with the font (family, style, size...) ; but most of the 
time 
what you want is not 1:1 match. The need is to print the designed model.

So with "x,y w,h table row1 row2 row3", I don't care if there are rounded 
borders or 
some cool shadows. I draw a w x h rectangle starting at (x;y) and manage to set 
font 
so that it fits the table name and its columns in that rectangle.

Maybe you can -in the future- make support for multiple skins towards either 
the PDF 
rendering or the HTML engine... That's another issue to open ? :)

Original comment by geompse@gmail.com on 14 Mar 2010 at 11:07

GoogleCodeExporter commented 9 years ago
Actually, I am thinking about something *completely* different: the ability to 
render
DB model into a <canvas>. This would be done by a JS application.
Canvas can be comfortably (via right-click) saved as a PNG image, so printing 
is not
an issue. Also, canvas (IIRC) supports bezier curves, so doing this should be 
easier
than rendering on server side.

Original comment by ondrej.zara on 15 Mar 2010 at 7:10

GoogleCodeExporter commented 9 years ago
Then you will have to draw tables instead of using Html DOM for them (slower).
Besides I'm not sure of IE's support for canvas (IE8 maybe ?).

In Chrome (Chromium 5.0.333) you don't have the "save as PNG" option (you have 
the 
normal "save page as html"), see screen (french).

Doing this server-side removes at LOT of compatibility issues. Php is of course 
required, then.

For the curves I based my code on this :
 http://trac-sg.casabrasil.gov.br/browser/library/jpgraph/jpgraph_regstat.php
(there are two classes, Spline and Bezier)

Maybe you can implements both methods, let's say the canvas method is for 
removing 
the need for a php server (but for firefox), and the php method is for saving 
to pdf.

Oh yeah, I forget this point : PDF vs PNG. PDF is vector-based, this means that 
not 
only the actual file size is lighter than a compressed image file, but also you 
can 
zoom in/out with no quality loss (no pixelisation). Besides having a heavy PNG 
might 
not suit user's computer, since a large PNG file takes much times to open. I 
also 
believe there is a size (w x h) limitation in PNG.

Best regards.

Original comment by geompse@gmail.com on 15 Mar 2010 at 8:37

GoogleCodeExporter commented 9 years ago
*edit*
this works in chrome :
  canvas.toDataURL("image/png")
  window.open(canvas.toDataURL("image/png"),"mywindow");
demo here : http://mrdoob.com/projects/harmony/

But the file is displayed, not prompted to be save...

Original comment by geompse@gmail.com on 15 Mar 2010 at 8:43

GoogleCodeExporter commented 9 years ago
Following Issue 66, it would be nice to have 1 page per container... you could 
achieve 
this with multiple PNGs, but zipping them would be done server-side.

What's the point here ? I can refactor the code if you want

Original comment by geompse@gmail.com on 15 Mar 2010 at 9:00

GoogleCodeExporter commented 9 years ago
The "canvas" view won't replace what we have now. Instead, there will be a 
"print"
(or some other name) feature that just renders the view into a canvas (perhaps 
in a
new window).

Canvas implementations are very interoperable, there are almost no compatibility
issues. IE is kind of out of game, which I like, because I want to ultimately
completely drop IE support.

Original comment by ondrej.zara on 15 Mar 2010 at 9:17

GoogleCodeExporter commented 9 years ago
We did drop IE (even IE8) in our business model. We dev under chrome and our 
clients 
>must< install firefox (or chrome be they are still reluctant to it)

Original comment by geompse@gmail.com on 15 Mar 2010 at 12:58

GoogleCodeExporter commented 9 years ago
I refactored my code, so here it is :
 - src.zip for the raw versions of new files
 - pdfdiff.txt for all diff (including fr and en locale patch)
 - design.pdf as rendered example

Towards the above discussion, I kept in mind those ideas :
 - both "Save as PDF" and "Save as PNG" might exists, so my function "print" is now 
"downloadpdf"
 - style.css might be modified by the user. In this case the downloadpdf.php must be 
modified too. Altering the FONTSIZE const shall be enough.

Data sent is :
 - Tables : title, offsetWidth, offsetHeight, x, y, className
 - Rows : title, className, backgroundColor
 - SVG : full innerHTML

Tables and rows are sent as XML.
SVG is sent as HTML.
The XML is loaded in a DOMDocument and the HTML is appended to this document as 
a 
fragment.

Original comment by geompse@gmail.com on 18 Mar 2010 at 1:55

Attachments:

GoogleCodeExporter commented 9 years ago
I believe this can be done completely client-side by using something like  
jspdf 
http://jspdf.googlecode.com/svn/trunk/examples/basic.htm

As for handling fonts, I think there are clever ways of deducing font metrics 
from
text rendered in the browser.

As long as data URIs are supported by the browser, it will work. This means it 
will
work everywhere but on IE. That's OK in my book :)

Original comment by ober.14@osu.edu on 28 Mar 2010 at 4:10

GoogleCodeExporter commented 9 years ago
I've just come across this project - a really great visual tool for creating 
databases.

However, I'd like to be able to print it (at the moment, I have to take a 
screenshot and crop it). I've tried the code by geompse, but can't seem to get 
it working in the latest version.

Will this ever appear as an official feature?

Original comment by jgxenite on 15 Feb 2011 at 4:36

GoogleCodeExporter commented 9 years ago
Hi,

I am still not certain about the optimal approach. Additionaly, my time is 
extremely limited these days, so I am unable to implement any larger features. 

On the other hand, it might be sufficient to use a Firefox extensions, which 
leverages the canvas.drawWindow() function in order to produce an image from 
web page. You can try FireShot 
(https://addons.mozilla.org/en-us/firefox/addon/fireshot/) or some other 
extension - there are plenty of those.

Original comment by ondrej.zara on 15 Feb 2011 at 6:51

GoogleCodeExporter commented 9 years ago
This is an optimal tool for printing/downloading the schema: 
http://www.phantomjs.org/

Original comment by ondrej.zara on 31 Mar 2011 at 12:59