001: /*
002: * $Id: PdfAction.java 2526 2007-01-14 09:43:13Z blowagie $
003: * $Name$
004: *
005: * Copyright 2001, 2002 by Bruno Lowagie.
006: *
007: * The contents of this file are subject to the Mozilla Public License Version 1.1
008: * (the "License"); you may not use this file except in compliance with the License.
009: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
010: *
011: * Software distributed under the License is distributed on an "AS IS" basis,
012: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
013: * for the specific language governing rights and limitations under the License.
014: *
015: * The Original Code is 'iText, a free JAVA-PDF library'.
016: *
017: * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
018: * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
019: * All Rights Reserved.
020: * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
021: * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
022: *
023: * Contributor(s): all the names of the contributors are added in the source code
024: * where applicable.
025: *
026: * Alternatively, the contents of this file may be used under the terms of the
027: * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
028: * provisions of LGPL are applicable instead of those above. If you wish to
029: * allow use of your version of this file only under the terms of the LGPL
030: * License and not to allow others to use your version of this file under
031: * the MPL, indicate your decision by deleting the provisions above and
032: * replace them with the notice and other provisions required by the LGPL.
033: * If you do not delete the provisions above, a recipient may use your version
034: * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
035: *
036: * This library is free software; you can redistribute it and/or modify it
037: * under the terms of the MPL as stated above or under the terms of the GNU
038: * Library General Public License as published by the Free Software Foundation;
039: * either version 2 of the License, or any later version.
040: *
041: * This library is distributed in the hope that it will be useful, but WITHOUT
042: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
043: * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
044: * details.
045: *
046: * If you didn't download this code from the following link, you should check if
047: * you aren't using an obsolete version:
048: * http://www.lowagie.com/iText/
049: */
050:
051: package com.lowagie.text.pdf;
052:
053: import java.io.IOException;
054: import java.net.URL;
055: import java.util.ArrayList;
056:
057: import com.lowagie.text.ExceptionConverter;
058: import com.lowagie.text.pdf.collection.PdfTargetDictionary;
059:
060: /**
061: * A <CODE>PdfAction</CODE> defines an action that can be triggered from a PDF file.
062: *
063: * @see PdfDictionary
064: */
065:
066: public class PdfAction extends PdfDictionary {
067:
068: /** A named action to go to the first page.
069: */
070: public static final int FIRSTPAGE = 1;
071: /** A named action to go to the previous page.
072: */
073: public static final int PREVPAGE = 2;
074: /** A named action to go to the next page.
075: */
076: public static final int NEXTPAGE = 3;
077: /** A named action to go to the last page.
078: */
079: public static final int LASTPAGE = 4;
080:
081: /** A named action to open a print dialog.
082: */
083: public static final int PRINTDIALOG = 5;
084:
085: /** a possible submitvalue */
086: public static final int SUBMIT_EXCLUDE = 1;
087: /** a possible submitvalue */
088: public static final int SUBMIT_INCLUDE_NO_VALUE_FIELDS = 2;
089: /** a possible submitvalue */
090: public static final int SUBMIT_HTML_FORMAT = 4;
091: /** a possible submitvalue */
092: public static final int SUBMIT_HTML_GET = 8;
093: /** a possible submitvalue */
094: public static final int SUBMIT_COORDINATES = 16;
095: /** a possible submitvalue */
096: public static final int SUBMIT_XFDF = 32;
097: /** a possible submitvalue */
098: public static final int SUBMIT_INCLUDE_APPEND_SAVES = 64;
099: /** a possible submitvalue */
100: public static final int SUBMIT_INCLUDE_ANNOTATIONS = 128;
101: /** a possible submitvalue */
102: public static final int SUBMIT_PDF = 256;
103: /** a possible submitvalue */
104: public static final int SUBMIT_CANONICAL_FORMAT = 512;
105: /** a possible submitvalue */
106: public static final int SUBMIT_EXCL_NON_USER_ANNOTS = 1024;
107: /** a possible submitvalue */
108: public static final int SUBMIT_EXCL_F_KEY = 2048;
109: /** a possible submitvalue */
110: public static final int SUBMIT_EMBED_FORM = 8196;
111: /** a possible submitvalue */
112: public static final int RESET_EXCLUDE = 1;
113:
114: // constructors
115:
116: /** Create an empty action.
117: */
118: public PdfAction() {
119: }
120:
121: /**
122: * Constructs a new <CODE>PdfAction</CODE> of Subtype URI.
123: *
124: * @param url the Url to go to
125: */
126:
127: public PdfAction(URL url) {
128: this (url.toExternalForm());
129: }
130:
131: /**
132: * Construct a new <CODE>PdfAction</CODE> of Subtype URI that accepts the x and y coordinate of the position that was clicked.
133: * @param url
134: * @param isMap
135: */
136: public PdfAction(URL url, boolean isMap) {
137: this (url.toExternalForm(), isMap);
138: }
139:
140: /**
141: * Constructs a new <CODE>PdfAction</CODE> of Subtype URI.
142: *
143: * @param url the url to go to
144: */
145:
146: public PdfAction(String url) {
147: this (url, false);
148: }
149:
150: /**
151: * Construct a new <CODE>PdfAction</CODE> of Subtype URI that accepts the x and y coordinate of the position that was clicked.
152: * @param url
153: * @param isMap
154: */
155:
156: public PdfAction(String url, boolean isMap) {
157: put(PdfName.S, PdfName.URI);
158: put(PdfName.URI, new PdfString(url));
159: if (isMap)
160: put(PdfName.ISMAP, PdfBoolean.PDFTRUE);
161: }
162:
163: /**
164: * Constructs a new <CODE>PdfAction</CODE> of Subtype GoTo.
165: * @param destination the destination to go to
166: */
167:
168: PdfAction(PdfIndirectReference destination) {
169: put(PdfName.S, PdfName.GOTO);
170: put(PdfName.D, destination);
171: }
172:
173: /**
174: * Constructs a new <CODE>PdfAction</CODE> of Subtype GoToR.
175: * @param filename the file name to go to
176: * @param name the named destination to go to
177: */
178:
179: public PdfAction(String filename, String name) {
180: put(PdfName.S, PdfName.GOTOR);
181: put(PdfName.F, new PdfString(filename));
182: put(PdfName.D, new PdfString(name));
183: }
184:
185: /**
186: * Constructs a new <CODE>PdfAction</CODE> of Subtype GoToR.
187: * @param filename the file name to go to
188: * @param page the page destination to go to
189: */
190:
191: public PdfAction(String filename, int page) {
192: put(PdfName.S, PdfName.GOTOR);
193: put(PdfName.F, new PdfString(filename));
194: put(PdfName.D, new PdfLiteral("[" + (page - 1)
195: + " /FitH 10000]"));
196: }
197:
198: /** Implements name actions. The action can be FIRSTPAGE, LASTPAGE,
199: * NEXTPAGE, PREVPAGE and PRINTDIALOG.
200: * @param named the named action
201: */
202: public PdfAction(int named) {
203: put(PdfName.S, PdfName.NAMED);
204: switch (named) {
205: case FIRSTPAGE:
206: put(PdfName.N, PdfName.FIRSTPAGE);
207: break;
208: case LASTPAGE:
209: put(PdfName.N, PdfName.LASTPAGE);
210: break;
211: case NEXTPAGE:
212: put(PdfName.N, PdfName.NEXTPAGE);
213: break;
214: case PREVPAGE:
215: put(PdfName.N, PdfName.PREVPAGE);
216: break;
217: case PRINTDIALOG:
218: put(PdfName.S, PdfName.JAVASCRIPT);
219: put(PdfName.JS, new PdfString("this.print(true);\r"));
220: break;
221: default:
222: throw new RuntimeException("Invalid named action.");
223: }
224: }
225:
226: /** Launchs an application or a document.
227: * @param application the application to be launched or the document to be opened or printed.
228: * @param parameters (Windows-specific) A parameter string to be passed to the application.
229: * It can be <CODE>null</CODE>.
230: * @param operation (Windows-specific) the operation to perform: "open" - Open a document,
231: * "print" - Print a document.
232: * It can be <CODE>null</CODE>.
233: * @param defaultDir (Windows-specific) the default directory in standard DOS syntax.
234: * It can be <CODE>null</CODE>.
235: */
236: public PdfAction(String application, String parameters,
237: String operation, String defaultDir) {
238: put(PdfName.S, PdfName.LAUNCH);
239: if (parameters == null && operation == null
240: && defaultDir == null)
241: put(PdfName.F, new PdfString(application));
242: else {
243: PdfDictionary dic = new PdfDictionary();
244: dic.put(PdfName.F, new PdfString(application));
245: if (parameters != null)
246: dic.put(PdfName.P, new PdfString(parameters));
247: if (operation != null)
248: dic.put(PdfName.O, new PdfString(operation));
249: if (defaultDir != null)
250: dic.put(PdfName.D, new PdfString(defaultDir));
251: put(PdfName.WIN, dic);
252: }
253: }
254:
255: /** Launchs an application or a document.
256: * @param application the application to be launched or the document to be opened or printed.
257: * @param parameters (Windows-specific) A parameter string to be passed to the application.
258: * It can be <CODE>null</CODE>.
259: * @param operation (Windows-specific) the operation to perform: "open" - Open a document,
260: * "print" - Print a document.
261: * It can be <CODE>null</CODE>.
262: * @param defaultDir (Windows-specific) the default directory in standard DOS syntax.
263: * It can be <CODE>null</CODE>.
264: * @return a Launch action
265: */
266: public static PdfAction createLaunch(String application,
267: String parameters, String operation, String defaultDir) {
268: return new PdfAction(application, parameters, operation,
269: defaultDir);
270: }
271:
272: /**Creates a Rendition action
273: * @param file
274: * @param fs
275: * @param mimeType
276: * @param ref
277: * @return a Media Clip action
278: * @throws IOException
279: */
280: public static PdfAction rendition(String file,
281: PdfFileSpecification fs, String mimeType,
282: PdfIndirectReference ref) throws IOException {
283: PdfAction js = new PdfAction();
284: js.put(PdfName.S, PdfName.RENDITION);
285: js.put(PdfName.R, new PdfRendition(file, fs, mimeType));
286: js.put(new PdfName("OP"), new PdfNumber(0));
287: js.put(new PdfName("AN"), ref);
288: return js;
289: }
290:
291: /** Creates a JavaScript action. If the JavaScript is smaller than
292: * 50 characters it will be placed as a string, otherwise it will
293: * be placed as a compressed stream.
294: * @param code the JavaScript code
295: * @param writer the writer for this action
296: * @param unicode select JavaScript unicode. Note that the internal
297: * Acrobat JavaScript engine does not support unicode,
298: * so this may or may not work for you
299: * @return the JavaScript action
300: */
301: public static PdfAction javaScript(String code, PdfWriter writer,
302: boolean unicode) {
303: PdfAction js = new PdfAction();
304: js.put(PdfName.S, PdfName.JAVASCRIPT);
305: if (unicode && code.length() < 50) {
306: js.put(PdfName.JS, new PdfString(code,
307: PdfObject.TEXT_UNICODE));
308: } else if (!unicode && code.length() < 100) {
309: js.put(PdfName.JS, new PdfString(code));
310: } else {
311: try {
312: byte b[] = PdfEncodings.convertToBytes(code,
313: unicode ? PdfObject.TEXT_UNICODE
314: : PdfObject.TEXT_PDFDOCENCODING);
315: PdfStream stream = new PdfStream(b);
316: stream.flateCompress();
317: js.put(PdfName.JS, writer.addToBody(stream)
318: .getIndirectReference());
319: } catch (Exception e) {
320: throw new ExceptionConverter(e);
321: }
322: }
323: return js;
324: }
325:
326: /** Creates a JavaScript action. If the JavaScript is smaller than
327: * 50 characters it will be place as a string, otherwise it will
328: * be placed as a compressed stream.
329: * @param code the JavaScript code
330: * @param writer the writer for this action
331: * @return the JavaScript action
332: */
333: public static PdfAction javaScript(String code, PdfWriter writer) {
334: return javaScript(code, writer, false);
335: }
336:
337: /**
338: * A Hide action hides or shows an object.
339: * @param obj object to hide or show
340: * @param hide true is hide, false is show
341: * @return a Hide Action
342: */
343: static PdfAction createHide(PdfObject obj, boolean hide) {
344: PdfAction action = new PdfAction();
345: action.put(PdfName.S, PdfName.HIDE);
346: action.put(PdfName.T, obj);
347: if (!hide)
348: action.put(PdfName.H, PdfBoolean.PDFFALSE);
349: return action;
350: }
351:
352: /**
353: * A Hide action hides or shows an annotation.
354: * @param annot
355: * @param hide
356: * @return A Hide Action
357: */
358: public static PdfAction createHide(PdfAnnotation annot, boolean hide) {
359: return createHide(annot.getIndirectReference(), hide);
360: }
361:
362: /**
363: * A Hide action hides or shows an annotation.
364: * @param name
365: * @param hide
366: * @return A Hide Action
367: */
368: public static PdfAction createHide(String name, boolean hide) {
369: return createHide(new PdfString(name), hide);
370: }
371:
372: static PdfArray buildArray(Object names[]) {
373: PdfArray array = new PdfArray();
374: for (int k = 0; k < names.length; ++k) {
375: Object obj = names[k];
376: if (obj instanceof String)
377: array.add(new PdfString((String) obj));
378: else if (obj instanceof PdfAnnotation)
379: array.add(((PdfAnnotation) obj).getIndirectReference());
380: else
381: throw new RuntimeException(
382: "The array must contain String or PdfAnnotation.");
383: }
384: return array;
385: }
386:
387: /**
388: * A Hide action hides or shows objects.
389: * @param names
390: * @param hide
391: * @return A Hide Action
392: */
393: public static PdfAction createHide(Object names[], boolean hide) {
394: return createHide(buildArray(names), hide);
395: }
396:
397: /**
398: * Creates a submit form.
399: * @param file the URI to submit the form to
400: * @param names the objects to submit
401: * @param flags submit properties
402: * @return A PdfAction
403: */
404: public static PdfAction createSubmitForm(String file,
405: Object names[], int flags) {
406: PdfAction action = new PdfAction();
407: action.put(PdfName.S, PdfName.SUBMITFORM);
408: PdfDictionary dic = new PdfDictionary();
409: dic.put(PdfName.F, new PdfString(file));
410: dic.put(PdfName.FS, PdfName.URL);
411: action.put(PdfName.F, dic);
412: if (names != null)
413: action.put(PdfName.FIELDS, buildArray(names));
414: action.put(PdfName.FLAGS, new PdfNumber(flags));
415: return action;
416: }
417:
418: /**
419: * Creates a resetform.
420: * @param names the objects to reset
421: * @param flags submit properties
422: * @return A PdfAction
423: */
424: public static PdfAction createResetForm(Object names[], int flags) {
425: PdfAction action = new PdfAction();
426: action.put(PdfName.S, PdfName.RESETFORM);
427: if (names != null)
428: action.put(PdfName.FIELDS, buildArray(names));
429: action.put(PdfName.FLAGS, new PdfNumber(flags));
430: return action;
431: }
432:
433: /**
434: * Creates an Import field.
435: * @param file
436: * @return A PdfAction
437: */
438: public static PdfAction createImportData(String file) {
439: PdfAction action = new PdfAction();
440: action.put(PdfName.S, PdfName.IMPORTDATA);
441: action.put(PdfName.F, new PdfString(file));
442: return action;
443: }
444:
445: /** Add a chained action.
446: * @param na the next action
447: */
448: public void next(PdfAction na) {
449: PdfObject nextAction = get(PdfName.NEXT);
450: if (nextAction == null)
451: put(PdfName.NEXT, na);
452: else if (nextAction.isDictionary()) {
453: PdfArray array = new PdfArray(nextAction);
454: array.add(na);
455: put(PdfName.NEXT, array);
456: } else {
457: ((PdfArray) nextAction).add(na);
458: }
459: }
460:
461: /** Creates a GoTo action to an internal page.
462: * @param page the page to go. First page is 1
463: * @param dest the destination for the page
464: * @param writer the writer for this action
465: * @return a GoTo action
466: */
467: public static PdfAction gotoLocalPage(int page,
468: PdfDestination dest, PdfWriter writer) {
469: PdfIndirectReference ref = writer.getPageReference(page);
470: dest.addPage(ref);
471: PdfAction action = new PdfAction();
472: action.put(PdfName.S, PdfName.GOTO);
473: action.put(PdfName.D, dest);
474: return action;
475: }
476:
477: /**
478: * Creates a GoTo action to a named destination.
479: * @param dest the named destination
480: * @param isName if true sets the destination as a name, if false sets it as a String
481: * @return a GoTo action
482: */
483: public static PdfAction gotoLocalPage(String dest, boolean isName) {
484: PdfAction action = new PdfAction();
485: action.put(PdfName.S, PdfName.GOTO);
486: if (isName)
487: action.put(PdfName.D, new PdfName(dest));
488: else
489: action.put(PdfName.D, new PdfString(dest, null));
490: return action;
491: }
492:
493: /**
494: * Creates a GoToR action to a named destination.
495: * @param filename the file name to go to
496: * @param dest the destination name
497: * @param isName if true sets the destination as a name, if false sets it as a String
498: * @param newWindow open the document in a new window if <CODE>true</CODE>, if false the current document is replaced by the new document.
499: * @return a GoToR action
500: */
501: public static PdfAction gotoRemotePage(String filename,
502: String dest, boolean isName, boolean newWindow) {
503: PdfAction action = new PdfAction();
504: action.put(PdfName.F, new PdfString(filename));
505: action.put(PdfName.S, PdfName.GOTOR);
506: if (isName)
507: action.put(PdfName.D, new PdfName(dest));
508: else
509: action.put(PdfName.D, new PdfString(dest, null));
510: if (newWindow)
511: action.put(PdfName.NEWWINDOW, PdfBoolean.PDFTRUE);
512: return action;
513: }
514:
515: /**
516: * Creates a GoToE action to an embedded file.
517: * @param filename the root document of the target (null if the target is in the same document)
518: * @param dest the named destination
519: * @param isName if true sets the destination as a name, if false sets it as a String
520: * @return a GoToE action
521: */
522: public static PdfAction gotoEmbedded(String filename,
523: PdfTargetDictionary target, String dest, boolean isName,
524: boolean newWindow) {
525: if (isName)
526: return gotoEmbedded(filename, target, new PdfName(dest),
527: newWindow);
528: else
529: return gotoEmbedded(filename, target, new PdfString(dest,
530: null), newWindow);
531: }
532:
533: /**
534: * Creates a GoToE action to an embedded file.
535: * @param filename the root document of the target (null if the target is in the same document)
536: * @param target a path to the target document of this action
537: * @param dest the destination inside the target document, can be of type PdfDestination, PdfName, or PdfString
538: * @param newWindow if true, the destination document should be opened in a new window
539: * @return a GoToE action
540: */
541: public static PdfAction gotoEmbedded(String filename,
542: PdfTargetDictionary target, PdfObject dest,
543: boolean newWindow) {
544: PdfAction action = new PdfAction();
545: action.put(PdfName.S, PdfName.GOTOE);
546: action.put(PdfName.T, target);
547: action.put(PdfName.D, dest);
548: action.put(PdfName.NEWWINDOW, new PdfBoolean(newWindow));
549: if (filename != null) {
550: action.put(PdfName.F, new PdfString(filename));
551: }
552: return action;
553: }
554:
555: /**
556: * A set-OCG-state action (PDF 1.5) sets the state of one or more optional content
557: * groups.
558: * @param state an array consisting of any number of sequences beginning with a <CODE>PdfName</CODE>
559: * or <CODE>String</CODE> (ON, OFF, or Toggle) followed by one or more optional content group dictionaries
560: * <CODE>PdfLayer</CODE> or a <CODE>PdfIndirectReference</CODE> to a <CODE>PdfLayer</CODE>.<br>
561: * The array elements are processed from left to right; each name is applied
562: * to the subsequent groups until the next name is encountered:
563: * <ul>
564: * <li>ON sets the state of subsequent groups to ON</li>
565: * <li>OFF sets the state of subsequent groups to OFF</li>
566: * <li>Toggle reverses the state of subsequent groups</li>
567: * </ul>
568: * @param preserveRB if <CODE>true</CODE>, indicates that radio-button state relationships between optional
569: * content groups (as specified by the RBGroups entry in the current configuration
570: * dictionary) should be preserved when the states in the
571: * <CODE>state</CODE> array are applied. That is, if a group is set to ON (either by ON or Toggle) during
572: * processing of the <CODE>state</CODE> array, any other groups belong to the same radio-button
573: * group are turned OFF. If a group is set to OFF, there is no effect on other groups.<br>
574: * If <CODE>false</CODE>, radio-button state relationships, if any, are ignored
575: * @return the action
576: */
577: public static PdfAction setOCGstate(ArrayList state,
578: boolean preserveRB) {
579: PdfAction action = new PdfAction();
580: action.put(PdfName.S, PdfName.SETOCGSTATE);
581: PdfArray a = new PdfArray();
582: for (int k = 0; k < state.size(); ++k) {
583: Object o = state.get(k);
584: if (o == null)
585: continue;
586: if (o instanceof PdfIndirectReference)
587: a.add((PdfIndirectReference) o);
588: else if (o instanceof PdfLayer)
589: a.add(((PdfLayer) o).getRef());
590: else if (o instanceof PdfName)
591: a.add((PdfName) o);
592: else if (o instanceof String) {
593: PdfName name = null;
594: String s = (String) o;
595: if (s.equalsIgnoreCase("on"))
596: name = PdfName.ON;
597: else if (s.equalsIgnoreCase("off"))
598: name = PdfName.OFF;
599: else if (s.equalsIgnoreCase("toggle"))
600: name = PdfName.TOGGLE;
601: else
602: throw new IllegalArgumentException(
603: "A string '"
604: + s
605: + " was passed in state. Only 'ON', 'OFF' and 'Toggle' are allowed.");
606: a.add(name);
607: } else
608: throw new IllegalArgumentException(
609: "Invalid type was passed in state: "
610: + o.getClass().getName());
611: }
612: action.put(PdfName.STATE, a);
613: if (!preserveRB)
614: action.put(PdfName.PRESERVERB, PdfBoolean.PDFFALSE);
615: return action;
616: }
617: }
|