001: /*
002: * $Id: PDFTest.java,v 1.4 2001/11/16 15:26:04 ezb Exp $
003: *
004: * $Date: 2001/11/16 15:26:04 $
005: *
006: * Copyright (C) 2001 Eric Z. Beard, ericzbeard@hotmail.com
007: *
008: *
009: * This library is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU Lesser General Public
011: * License as published by the Free Software Foundation; either
012: * version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * Lesser General Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
022: *
023: */
024: package gnu.jpdf;
025:
026: import java.awt.*;
027: import java.awt.event.*;
028: import javax.swing.*;
029: import java.io.*;
030: import java.util.*;
031:
032: /**
033: * <p>The purpose of this class is to test all functionality of the
034: * gnu.jpdf package and serve as a demonstration of how to use the
035: * library.</p>
036: *
037: * <p>This library produces pdf format files and can display and print
038: * them in a java Graphics context by extending java.awt.Graphics and
039: * java.awt.PrintJob. The pdf file itself is not viewed, but an
040: * identical copy made with the same methods that constructed the
041: * pdf file. See the code or the tutorial for an example</p>
042: *
043: * @author Eric Z. Beard
044: * <a href = "mailto:ericzbeard@hotmail.com">ericzbeard@hotmail.com</a>
045: * @author $Author: ezb $
046: * @version $Revision: 1.4 $
047: */
048: public class PDFTest extends JFrame implements ActionListener {
049: /** Entered on the command line after '-pdf' */
050: private static String outputPdfFile;
051:
052: /** Entered on the command line after '-img' */
053: private static String sampleImageFile;
054:
055: /** Not yet supported - test without a window */
056: private static boolean noWindow;
057:
058: /** Main content pane */
059: private JPanel pane = new JPanel();
060:
061: /** All sizes will be derived from the desired pdf document size */
062: private Dimension documentDimension;
063:
064: private int currentPage;
065:
066: private PDFJob job;
067:
068: private boolean pdfDocumentAlreadyDone;
069:
070: /**
071: * A JPanel used for drawing the document on the screen
072: *
073: * The source is included in this file at the bottom
074: */
075: private TestPanel drawingArea;
076:
077: /** The menu bar */
078: private TestMenuBar menuBar;
079:
080: // TODO: Add the toolbar, use Action objects for action handling
081:
082: public PDFTest(String outputPdfFile, String sampleImageFile,
083: boolean noWindow) {
084:
085: // First see if the file path is valid
086: File file = null;
087: FileOutputStream fileOutputStream = null;
088: try {
089: file = new File(outputPdfFile);
090: fileOutputStream = new FileOutputStream(file);
091: } catch (Exception e) {
092: System.err.println("Error!! - Invalid output file path: "
093: + outputPdfFile);
094: usage();
095: System.exit(1);
096: }
097:
098: // Handle window closing
099: addWindowListener(new WindowAdapter() {
100: public void windowClosing(WindowEvent e) {
101: System.exit(0);
102: }
103: });
104:
105: Container contentPane = getContentPane();
106:
107: pane.setLayout(new BorderLayout());
108:
109: // Add the menubar
110: menuBar = new TestMenuBar(this );
111: setJMenuBar(menuBar);
112:
113: // Get the Graphics object for pdf writing
114: Graphics pdfGraphics = null;
115: job = new PDFJob(fileOutputStream);
116: pdfGraphics = job.getGraphics();
117: Dimension d = job.getPageDimension();
118: documentDimension = d;
119:
120: // Finish setting up the window and bring to front
121: int w = (int) d.getWidth();
122: int h = (int) d.getHeight();
123:
124: drawingArea = new TestPanel();
125:
126: // Put the drawing area in a scroll pane
127: JScrollPane scrollPane = new JScrollPane(drawingArea,
128: ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
129: ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
130:
131: // Set the preferred size bigger than the scroll pane so the bars show up
132: drawingArea.setPreferredSize(new Dimension(1000, 1000));
133:
134: pane.add(scrollPane, "Center");
135:
136: contentPane.add(pane);
137:
138: setTitle("PDF Test Application");
139:
140: // Set the location and size of the window and show it
141: Toolkit toolkit = Toolkit.getDefaultToolkit();
142: Dimension screenSize = toolkit.getScreenSize();
143: setLocation(50, 50);
144: setSize(w, h / 2);
145: setVisible(true);
146: toFront();
147:
148: doFirstPage(pdfGraphics);
149: currentPage = 1;
150:
151: if (fileOutputStream != null) {
152: try {
153: fileOutputStream.close();
154: } catch (IOException e) {
155: e.printStackTrace();
156: }
157: fileOutputStream = null;
158: }
159: drawingArea.repaint();
160: pane.revalidate();
161:
162: } // end constructor
163:
164: private void doFirstPage(Graphics pdfGraphics) {
165: Dimension d = documentDimension;
166: // Get the graphics object for screen drawing
167: Image img = drawingArea.createImage((int) d.getWidth(), (int) d
168: .getHeight());
169: if (img == null) {
170: System.out.println("Error!! - drawing image is null");
171: System.exit(1);
172: }
173:
174: drawingArea.setImage(img);
175: Graphics javaGraphics = img.getGraphics();
176:
177: // Now we have two Graphics objects - one for java Graphics to
178: // draw to the screen , another to write
179: // to the pdf file. We'll use the same methods to act on both
180: // objects, and (theoretically) the results should be identical.
181: // If 'Print' is selected from the menu, the same methods wi
182: // act on a Graphics object from the java.awt.PrintJob
183:
184: doTest(javaGraphics, d);
185: javaGraphics.dispose();
186:
187: // The whole pdf doc will be written when the program starts
188: if ((!pdfDocumentAlreadyDone) && (pdfGraphics != null)) {
189: doTest(pdfGraphics, d);
190: pdfGraphics.dispose();
191:
192: pdfGraphics = job.getGraphics();
193: doSecondPageTest(pdfGraphics);
194: pdfGraphics.dispose();
195: job.end();
196: }
197:
198: // The same methods (such as 'job.end()') are called on the pdf job
199: // as on a print job, so this could be abstracted further to use the
200: // same code on both jobs
201: currentPage = 1;
202:
203: drawingArea.repaint();
204: drawingArea.revalidate();
205: }
206:
207: /**
208: * <p>Very basic action handler - a more robust app would use
209: * Action objects</p>
210: *
211: * @param e an <code>ActionEvent</code> value
212: */
213: public void actionPerformed(ActionEvent e) {
214: Object source = e.getSource();
215: if (source == menuBar.close) {
216: System.exit(0);
217: }
218: if (source == menuBar.printer) {
219: printPdf();
220: return;
221: }
222: if (source == menuBar.helpTopics) {
223: System.out.println("Help..");
224: showHelp();
225: return;
226: }
227: if (source == menuBar.aboutApp) {
228: System.out.println("About...");
229: showAboutBox();
230: return;
231: }
232: if (source == menuBar.viewFirstPage) {
233: if (currentPage != 1) {
234: doFirstPage(null);
235: return;
236: }
237: }
238: if (source == menuBar.viewSecondPage) {
239: if (currentPage != 2) {
240: doSecondPage();
241: return;
242: }
243: }
244: }
245:
246: /**
247: * <p>Show the about dialog box</p>
248: *
249: */
250: private void showAboutBox() {
251: JOptionPane.showMessageDialog(this ,
252: "gnujpdf test application, " + "by Eric Z. Beard. "
253: + "http://gnujpdf.sourceforge.net");
254: }
255:
256: /**
257: * <p>Show a help dialog - it would be good to use text from
258: * a tutorial that sits in the docs directory</p>
259: *
260: */
261: private void showHelp() {
262: HelpFrame helpFrame = new HelpFrame();
263: }
264:
265: /**
266: * <p>Gets a print job and uses the same drawing methods that
267: * were used on the other Graphics objects to print the document</p>
268: *
269: */
270: private void printPdf() {
271: System.out.println("Printing..");
272: JobAttributes jobAttributes = new JobAttributes();
273: //jobAttributes.setDialog(JobAttributes.DialogType.NONE);
274: // CRAP!! - This doesn't work with jdk1.2.2 - fix it
275: Toolkit toolkit = Toolkit.getDefaultToolkit();
276: PrintJob pjob = toolkit.getPrintJob(this , "PDF Test Print",
277: jobAttributes, null);
278: if (pjob != null) {
279: Graphics printGraphics = pjob.getGraphics();
280: if (currentPage == 1) {
281: doTest(printGraphics, documentDimension);
282: printGraphics.dispose();
283: pjob.end();
284: } else {
285: doSecondPageTest(printGraphics);
286: printGraphics.dispose();
287: pjob.end();
288: }
289: } else {
290: System.err.println("Can't print: printjob null");
291: }
292: }
293:
294: /**
295: * <p>This method accepts any Graphics object and draws to it. It
296: * can be a java Graphics object for drawing to the screen, a pdf
297: * graphics object for constructing a pdf object, or a print job
298: * graphics object. The goal is to make all three look exactly the
299: * same, along with how the document looks when opened in Acrobat
300: * Reader and printed from Acrobat Reader - so it's actually 5 things
301: * that should ultimately look exactly the same, all constructed with
302: * the same set of methods</p>
303: *
304: * <p>This method should provide programmers with a good basis
305: * for using the BoundingBox class, if they choose to do so. It is by
306: * no means necessary, as it only makes layout on a fixed dimension
307: * canvas easier. The point of the pdf graphics library is to use
308: * the same drawing methods used in applets and applications</p>
309: *
310: * @param g a <code>Graphics</code> object to draw to
311: * @param d a <code>Dimension</code> object, the size of the document
312: */
313: private void doTest(Graphics g, Dimension d) {
314: g.setColor(Color.white);
315: g.fillRect(0, 0, d.width, d.height);
316: g.setColor(Color.black);
317: Point boxUpperLeft = new Point(60, 60);
318: Dimension boxSize = new Dimension(200, 200);
319: Font f = new Font("TimesRoman", Font.PLAIN, 16);
320: g.setFont(f);
321: FontMetrics fm = g.getFontMetrics(f);
322: BoundingBox box = new BoundingBox(boxUpperLeft, boxSize);
323: String string = "Hello World! this is a really long string";
324: int padding = 10;
325: BoundingBox child = null;
326: try {
327: child = box.getStringBounds(string,
328: BoundingBox.HORIZ_ALIGN_CENTER,
329: BoundingBox.VERT_ALIGN_BOTTOM, fm, padding);
330: } catch (StringTooLongException stle) {
331: // A more robust app might just cut off the end of the string or
332: // prevent the string from ever being too long or break it into
333: // pieces and create a new PDFPage (by getting a new graphics object)
334: // and continue the document
335: stle.printStackTrace();
336: return;
337: }
338:
339: g.drawRect(60, 60, 200, 200);
340: g.drawRect((int) child.getLocation().getX() + 60, (int) child
341: .getLocation().getY() + 60, (int) child.getSize()
342: .getWidth(), (int) child.getSize().getHeight());
343: Point p = child.getDrawingPoint();
344: int x = (int) p.getX();
345: int y = (int) p.getY();
346: // Draw the baseline
347: g.drawLine(x, y, x
348: + ((int) child.getSize().getWidth() - padding * 2), y);
349:
350: try {
351: child.drawWrappedString(g, fm, padding,
352: BoundingBox.HORIZ_ALIGN_CENTER);
353: } catch (StringTooLongException stle) {
354: stle.printStackTrace();
355: return;
356: }
357:
358: //drawHeader(g, d);
359: //drawBody(g, d);
360:
361: // Draw Hello world in a nested box
362: BoundingBox b1 = new BoundingBox(new Point(300, 60),
363: new Dimension(200, 200));
364: g.drawRect((int) b1.getAbsoluteLocation().getX(), (int) b1
365: .getAbsoluteLocation().getY(), (int) b1.getSize()
366: .getWidth(), (int) b1.getSize().getHeight());
367: BoundingBox b2 = new BoundingBox(new Point(10, 10),
368: new Dimension(100, 100));
369: b1.add(b2);
370: g.drawRect((int) b2.getAbsoluteLocation().getX(), (int) b2
371: .getAbsoluteLocation().getY(), (int) b2.getSize()
372: .getWidth(), (int) b2.getSize().getHeight());
373:
374: try {
375: BoundingBox b3 = b2.getStringBounds(string,
376: BoundingBox.HORIZ_ALIGN_CENTER,
377: BoundingBox.VERT_ALIGN_BOTTOM, fm, padding);
378: g.drawRect((int) b3.getAbsoluteLocation().getX(), (int) b3
379: .getAbsoluteLocation().getY(), (int) b3.getSize()
380: .getWidth(), (int) b3.getSize().getHeight());
381:
382: Point pt = b3.getDrawingPoint();
383: int px = (int) pt.getX();
384: int py = (int) pt.getY();
385: b3.drawWrappedString(g, fm, padding,
386: BoundingBox.HORIZ_ALIGN_CENTER);
387: } catch (StringTooLongException stle) {
388: stle.printStackTrace();
389: }
390:
391: drawStringsInBox(g);
392:
393: drawSampleImage(g, d);
394:
395: } // end doTest
396:
397: /**
398: * Describe <code>drawStringsInBox</code> method here.
399: *
400: * @param g a <code>Graphics</code> value
401: */
402: private void drawStringsInBox(Graphics g) {
403: g.setColor(Color.black);
404: BoundingBox box = new BoundingBox(new Point(20, 300),
405: new Dimension(250, 250));
406: g.drawRect((int) box.getAbsoluteLocation().getX(), (int) box
407: .getAbsoluteLocation().getY(), (int) box.getSize()
408: .getWidth(), (int) box.getSize().getHeight());
409: Font f = new Font("Helvetica", Font.PLAIN, 12);
410: g.setFont(f);
411: FontMetrics fm = g.getFontMetrics();
412: String line1 = "Line 1";
413: String line2 = "Line 2";
414: String line3 = "Line 3 realllllly loooooong .h gkjhg kjh gkjh gkjhg kjhg kjhg kjh gk jbhg";
415: int padding = 5;
416:
417: BoundingBox child = null;
418: try {
419: child = box.getStringBounds(line1,
420: BoundingBox.HORIZ_ALIGN_LEFT,
421: BoundingBox.VERT_ALIGN_TOP, fm, padding);
422: child.drawWrappedString(g, fm, padding,
423: BoundingBox.HORIZ_ALIGN_LEFT);
424: } catch (StringTooLongException stle) {
425: stle.printStackTrace();
426: return;
427: }
428: box.subtract(child, BoundingBox.SUBTRACT_FROM_BOTTOM);
429:
430: try {
431: child = box.getStringBounds(line2,
432: BoundingBox.HORIZ_ALIGN_LEFT,
433: BoundingBox.VERT_ALIGN_TOP, fm, padding);
434: child.drawWrappedString(g, fm, padding,
435: BoundingBox.HORIZ_ALIGN_LEFT);
436: } catch (StringTooLongException stle) {
437: stle.printStackTrace();
438: return;
439: }
440:
441: box.subtract(child, BoundingBox.SUBTRACT_FROM_BOTTOM);
442:
443: try {
444: child = box.getStringBounds(line3,
445: BoundingBox.HORIZ_ALIGN_LEFT,
446: BoundingBox.VERT_ALIGN_TOP, fm, padding);
447: child.drawWrappedString(g, fm, padding,
448: BoundingBox.HORIZ_ALIGN_LEFT);
449: } catch (StringTooLongException stle) {
450: stle.printStackTrace();
451: return;
452: }
453: box.subtract(child, BoundingBox.SUBTRACT_FROM_BOTTOM);
454:
455: try {
456: child = box.getStringBounds(line1,
457: BoundingBox.HORIZ_ALIGN_RIGHT,
458: BoundingBox.VERT_ALIGN_BOTTOM, fm, padding);
459: child.drawWrappedString(g, fm, padding,
460: BoundingBox.HORIZ_ALIGN_RIGHT);
461: box.subtract(child, BoundingBox.SUBTRACT_FROM_TOP);
462:
463: child = box.getStringBounds(line2,
464: BoundingBox.HORIZ_ALIGN_RIGHT,
465: BoundingBox.VERT_ALIGN_BOTTOM, fm, padding);
466: child.drawWrappedString(g, fm, padding,
467: BoundingBox.HORIZ_ALIGN_RIGHT);
468: box.subtract(child, BoundingBox.SUBTRACT_FROM_TOP);
469:
470: child = box.getStringBounds(line3,
471: BoundingBox.HORIZ_ALIGN_RIGHT,
472: BoundingBox.VERT_ALIGN_BOTTOM, fm, padding);
473: child.drawWrappedString(g, fm, padding,
474: BoundingBox.HORIZ_ALIGN_RIGHT);
475: box.subtract(child, BoundingBox.SUBTRACT_FROM_TOP);
476: } catch (StringTooLongException stle) {
477: stle.printStackTrace();
478: return;
479: }
480:
481: } // end drawStringsInBox
482:
483: /**
484: * Describe <code>drawSampleImage</code> method here.
485: *
486: * @param g a <code>Graphics</code> value
487: * @param d a <code>Dimension</code> value
488: */
489: private void drawSampleImage(Graphics g, Dimension d) {
490: try {
491: Toolkit toolkit = Toolkit.getDefaultToolkit();
492: Image img = toolkit.createImage(sampleImageFile);
493: MediaTracker tracker = new MediaTracker(drawingArea);
494: tracker.addImage(img, 0);
495: try {
496: tracker.waitForID(0);
497: } catch (Exception e) {
498: e.printStackTrace();
499: }
500: g.drawImage(img, 300, 300, img.getWidth(drawingArea), img
501: .getHeight(drawingArea), Color.green, drawingArea);
502: } catch (Exception e) {
503: e.printStackTrace();
504: }
505: }
506:
507: private void doSecondPage() {
508:
509: Dimension d = documentDimension;
510: // Get the graphics object for screen drawing
511: Image img = drawingArea.createImage((int) d.getWidth(), (int) d
512: .getHeight());
513: if (img == null) {
514: System.out.println("Error!! - drawing image is null");
515: System.exit(1);
516: }
517:
518: drawingArea.setImage(img);
519: Graphics javaGraphics = img.getGraphics();
520:
521: doSecondPageTest(javaGraphics);
522: javaGraphics.dispose();
523:
524: currentPage = 2;
525: drawingArea.repaint();
526: drawingArea.revalidate();
527: }
528:
529: private void doSecondPageTest(Graphics g) {
530: g.setColor(Color.white);
531: g.fillRect(0, 0, documentDimension.width,
532: documentDimension.height);
533: g.setColor(Color.black);
534: // test drawLine()
535: g.drawLine(10, 10, 50, 50);
536:
537: // test drawRect()
538: g.drawRect(30, 10, 10, 10);
539:
540: // test fillRect()
541: g.fillRect(30, 90, 10, 10);
542:
543: // test drawPolygon()
544: int xp[] = new int[] { 10, 10, 20, 15, 20 };
545: int yp[] = new int[] { 50, 60, 60, 55, 50 };
546: int np = xp.length;
547: g.drawPolygon(xp, yp, np);
548:
549: // test drawPolygon()
550: xp = new int[] { 60, 60, 70, 65, 70 };
551: yp = new int[] { 80, 90, 90, 85, 80 };
552: np = xp.length;
553: g.drawPolyline(xp, yp, np);
554:
555: // test fillPolygon()
556: xp = new int[] { 60, 60, 70, 65, 70 };
557: yp = new int[] { 50, 60, 60, 55, 50 };
558: np = xp.length;
559: g.fillPolygon(xp, yp, np);
560:
561: // Now some text
562: g.setFont(new Font("SansSerif", Font.PLAIN, 12));
563: g.drawString("This is a simple string", 10, 120);
564:
565: g.drawString("This is a (complex) string", 10, 130);
566:
567: g.drawString("(complex) string (with ( (multiple brackets ))",
568: 10, 140);
569:
570: // Now some arcs - first test is with a square
571: g.drawRect(200, 60, 50, 50); // rectangle
572: g.drawLine(200, 60, 250, 110); // join both corners
573: g.drawLine(200, 110, 250, 60);
574: g.drawLine(200, 85, 225, 60); // this should be a chord
575: g.drawArc(200, 60, 50, 50, 45, 180); // the arc
576:
577: // June 20, 2001 ezb - Looks like ovals work as expected
578: g.drawArc(100, 400, 100, 200, 0, 360);
579:
580: g.drawOval(200, 400, 100, 200);
581:
582: g.fillOval(300, 400, 100, 200);
583:
584: // These two tests act on a rectangular region (ie width != height)
585: // Now the interesting thing is that they don't fit the arc within
586: // the rectangle, but act on the width. This - by accident - matches the
587: // way the Linux JDK operates...
588:
589: // Now the same test, but with a rectangle
590: g.drawRect(300, 50, 80, 40);
591: g.drawLine(300, 50, 380, 90);
592: g.drawLine(300, 90, 380, 50);
593: g.drawArc(300, 50, 80, 40, 135, 180);
594:
595: // Again the same test, but we will fill the arc
596: g.drawRect(400, 50, 40, 80);
597: g.drawLine(400, 50, 440, 130);
598: g.drawLine(400, 130, 440, 50);
599: g.setColor(Color.blue);
600: g.fillArc(400, 50, 40, 80, 135, 180);
601: g.setColor(Color.black);
602:
603: // Repeat again, but this time with different angles to the arc.
604: // We do this to compare how Java and PDF render the arcs
605: g.drawRect(400, 150, 40, 80);
606: g.drawLine(400, 150, 440, 230);
607: g.drawLine(400, 230, 440, 150);
608: g.setColor(Color.blue);
609: g.fillArc(400, 150, 40, 80, 135, 225);
610: g.setColor(Color.black);
611:
612: // Finally draw a small table of all the fonts and styles
613: String fonts[] = new String[] { "SansSerif", "Monospaced",
614: "TimesRoman", "Helvetica", "Courier", "Dialog",
615: "DialogInput" };
616: String modes[] = new String[] { "Plain", "Bold", "Italic",
617: "Bold+Italic" };
618: int imodes[] = new int[] { Font.PLAIN, Font.BOLD, Font.ITALIC,
619: Font.BOLD + Font.ITALIC };
620:
621: int ty = 170;
622:
623: for (int i = 0; i < modes.length; i++)
624: g.drawString(modes[i], 100 + (50 * i), ty - 14);
625:
626: FontMetrics fm = g.getFontMetrics();
627: for (int i = 0; i < fonts.length; i++)
628: g.drawString(fonts[i], 98 - fm.stringWidth(fonts[i]), ty
629: + (12 * i));
630:
631: Font cf = g.getFont();
632:
633: for (int i = 0; i < fonts.length; i++) {
634: for (int j = 0; j < modes.length; j++) {
635: g.setFont(new Font(fonts[i], imodes[j], 10));
636: g.drawString(modes[j], 100 + (50 * j), ty);
637: }
638:
639: ty += 12;
640: }
641: } // end doSecondPage
642:
643: /**
644: * <p>The test is initiated through the main method. From the
645: * command line, two parameters are needed, -pdf [path-to-pdf], which
646: * is the path and filename of the pdf you would like to create using
647: * this test. It should end in ".pdf". The other param is
648: * -img [path-to-image]. It should be a pre-existing image, preferably
649: * a very small jpg. The command line arg -nw, for no window test, is
650: * not yet supported.</p>
651: *
652: * @param args a <code>String[]</code> value
653: */
654: public static void main(String[] args) {
655: if ((args != null) && (args.length > 0)) {
656: int len = args.length;
657:
658: for (int i = 0; i < len; i++) {
659: if (args[i].equals("-nw")) {
660: noWindow = true;
661: }
662: if (args[i].equals("-pdf")) {
663: if (len > (i + 1)) {
664: outputPdfFile = args[i + 1];
665: }
666: }
667: if (args[i].equals("-img")) {
668: if (len > (i + 1)) {
669: sampleImageFile = args[i + 1];
670: }
671: }
672: }
673: } else {
674: usage();
675: System.exit(1);
676: }
677: if (outputPdfFile == null) {
678: System.err.println("No output file specified");
679: usage();
680: System.exit(1);
681: }
682: if (sampleImageFile == null) {
683: System.err.println("No sample image file specified");
684: usage();
685: System.exit(1);
686: }
687:
688: // Params are ok, proceed with test
689: PDFTest window = new PDFTest(outputPdfFile, sampleImageFile,
690: noWindow);
691:
692: } // end main
693:
694: private static void usage() {
695: System.out.println("PDFTest Usage:");
696: System.out.println();
697: System.out
698: .print("java -classpath <$CLASSPATH> gnu.jpdf.PDFTest -pdf ");
699: System.out.print("<output-file-path> -img <path-to-image>");
700: System.out.println();
701: System.out.println();
702: System.out
703: .println("This will produce the pdf file generated at ");
704: System.out
705: .println("<output-file-path> (which should end in '.pdf') and ");
706: System.out
707: .println("use the image at <path-to-image>. Use a small jpg ");
708: System.out
709: .println("preferably since the compression is not so good ");
710: System.out
711: .println("and a pdf file will typically be 10 times as big as ");
712: System.out.println("the image used as a sample.");
713: System.out.println();
714: }
715: } // end class PDFTest
716:
717: // Non public classes used by PDFTest
718:
719: class TestPanel extends JPanel implements Scrollable {
720: // Scrollable methods
721: private Image image;
722:
723: public Dimension getPreferredScrollableViewportSize() {
724: return getPreferredSize(); // Not sure if this is what I want
725: }
726:
727: public int getScrollableBlockIncrement(Rectangle visibleRect,
728: int orientation, int direction) {
729: return 20; // This is fine, no customization needed
730: }
731:
732: public boolean getScrollableTracksViewportHeight() {
733: return false; // true disables scrolling
734: }
735:
736: public boolean getScrollableTracksViewportWidth() {
737: return false; // true disables scrolling
738: }
739:
740: public int getScrollableUnitIncrement(Rectangle visibleRect,
741: int orientation, int direction) {
742: return 5; // This is fine, no customization needed
743: }
744:
745: public void setImage(Image img) {
746: image = img;
747: }
748:
749: protected void paintComponent(Graphics g) {
750: super .paintComponent(g);
751: g.setColor(Color.gray);
752: g.fillRect(0, 0, getSize().width, getSize().height);
753: if (image != null) {
754: g.drawImage(image, 0, 0, this );
755: }
756: } // end paintComponent
757:
758: } // end class TestPanel
759:
760: /**
761: * Really basic toolbar - not an example of the finest GUI design
762: *
763: */
764: class TestMenuBar extends JMenuBar {
765: JMenu file, personnel, help, about, view;
766: JMenuItem printer;
767: JMenuItem close;
768: JMenuItem helpTopics;
769: JMenuItem aboutApp;
770: JMenuItem viewFirstPage;
771: JMenuItem viewSecondPage;
772:
773: public TestMenuBar(ActionListener parent) {
774: file = new JMenu("File");
775: file.setMnemonic(KeyEvent.VK_F);
776:
777: printer = new JMenuItem("Print");
778: printer.setMnemonic(KeyEvent.VK_R);
779: printer.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R,
780: ActionEvent.CTRL_MASK));
781: printer.addActionListener(parent);
782: //printer.setEnabled(false);
783: file.add(printer);
784:
785: close = new JMenuItem("Close");
786: close.setMnemonic(KeyEvent.VK_Q);
787: close.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
788: ActionEvent.CTRL_MASK));
789: close.addActionListener(parent);
790: file.add(close);
791:
792: view = new JMenu("View");
793: view.setMnemonic(KeyEvent.VK_V);
794:
795: // This isn't very extensible
796: viewFirstPage = new JMenuItem("First Page");
797: viewFirstPage.addActionListener(parent);
798: view.add(viewFirstPage);
799: viewSecondPage = new JMenuItem("Second Page");
800: viewSecondPage.addActionListener(parent);
801: view.add(viewSecondPage);
802:
803: help = new JMenu("Help");
804: help.setMnemonic(KeyEvent.VK_H);
805: helpTopics = new JMenuItem("Help Topics");
806: helpTopics.addActionListener(parent);
807: help.add(helpTopics);
808:
809: about = new JMenu("About");
810: about.setMnemonic(KeyEvent.VK_A);
811: aboutApp = new JMenuItem("About");
812: aboutApp.addActionListener(parent);
813: about.add(aboutApp);
814:
815: add(file);
816: add(view);
817: add(help);
818: add(about);
819: } // end constructor
820:
821: } // end class TestMenuBar
822:
823: /**
824: * A simple help frame. Nothing fancy.
825: *
826: */
827: class HelpFrame extends JFrame {
828: public HelpFrame() {
829: setTitle("gnupdf Help");
830:
831: Container helpContent = getContentPane();
832:
833: helpContent.setLayout(new BorderLayout());
834: JTextArea textArea = new JTextArea(20, 40);
835: textArea.setLineWrap(true);
836: textArea.append(getHelpText());
837: JScrollPane helpScroller = new JScrollPane(textArea);
838: helpContent.add(helpScroller);
839: setSize(helpScroller.getSize());
840: setLocation(new Point(200, 200));
841: pack();
842: toFront();
843: show();
844: //helpScroller.getViewport().setViewPosition(new Point(0, 0));
845: //textArea.scrollRectToVisible(new Rectangle(0, 0, 2, 2));
846: textArea.setCaretPosition(0);
847: textArea.setEditable(false);
848: }
849:
850: private String getHelpText() {
851: StringBuffer out = new StringBuffer();
852: out.append("gnujpdf Help File and Tutorial\n");
853: out.append("\n");
854: out
855: .append("This file contains some general help and a simple tutorial on the\n");
856: out
857: .append("gnujpdf java package (gnu.jpdf.*). More information can be\n");
858: out
859: .append("obtained from the website, http://gnujpdf.sourceforge.net.\n");
860: out.append("\n");
861: out
862: .append("gnujpdf is a set of Java classes that allows a programmer to use\n");
863: out
864: .append("extended versions of java.awt.Graphics and java.awt.PrintJob to\n");
865: out
866: .append("generate and print pdf files. The idea is to use methods and\n");
867: out
868: .append("classes that act on a Graphics object to produce the same output\n");
869: out
870: .append("in a pdf file, on the screen, and on the printer.\n");
871: out.append("\n");
872: out
873: .append("The best source of information for a programmer wishing to use\n");
874: out
875: .append("this simple API is the source code in PDFTest.java. It\n");
876: out
877: .append("demonstrates a simple application that displays various\n");
878: out
879: .append("formatting and simultaneously writes a pdf file that will be an\n");
880: out.append("identical copy of what is seen on the screen.\n");
881: out.append("\n");
882: out
883: .append("The starting point for creating any PDF document with this\n");
884: out.append("library is the PDFJob class.\n");
885: out.append("\n");
886: out.append("PDFJob job = new PDFJob(fileOutputStream);\n");
887: out.append("\n");
888: out
889: .append("The fileOutputStream is normally a stream initialized with the\n");
890: out
891: .append("name of the pdf you wish to generate, such as \"test.pdf\". A\n");
892: out
893: .append("PDFGraphics object can be obtained from the job by calling:\n");
894: out.append("\n");
895: out.append("Graphics pdfGraphics = job.getGraphics();\n");
896: out.append("\n");
897: out
898: .append("This Graphics object can be passed into the same methods used to\n");
899: out
900: .append("draw to the screen. Most of the common methods in\n");
901: out
902: .append("java.awt.Graphics have been implemented (with a few important\n");
903: out
904: .append("exceptions - this is a beta product, so there is still plenty of\n");
905: out
906: .append("work to be done - see the source code for more specifics). When\n");
907: out
908: .append("calling methods such as drawString(..) or drawImage(..), what is\n");
909: out
910: .append("actually happening is that the PDFGraphics object is writing the\n");
911: out.append("necessary markup to the output stream.\n");
912: out.append("\n");
913: out
914: .append("A new pdf page is initialized by disposing of the exisiting\n");
915: out
916: .append("Graphics object and getting a new one from the job.\n");
917: out.append("\n");
918: out.append("pdfGraphics.dispose(); \n");
919: out.append("pdfGraphics = job.getGraphics();\n");
920: out.append("\n");
921: out
922: .append("Any Graphics operations will now be made on a new page in the pdf\n");
923: out
924: .append("document. When the document is finished, the job must be closed\n");
925: out.append("out:\n");
926: out.append("\n");
927: out.append("pdfGraphics.dispose();\n");
928: out.append("job.end();\n");
929: out.append("\n");
930: out
931: .append("And the fileOutputStream will need to be closed properly as well,\n");
932: out
933: .append("as this is not guaranteed to be taken care of by the PDF classes.\n");
934: out.append("\n");
935: out.append("----------------\n");
936: out.append("End of Help File\n");
937: out.append("\n");
938: out
939: .append("For more information, see http://gnujpdf.sourceforge.net\n");
940: out.append("\n");
941:
942: return out.toString();
943: }
944: } // end class HelpFrame
|