001: /*
002: * Copyright (c) 2007, intarsys consulting GmbH
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * - Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * - Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * - Neither the name of intarsys nor the names of its contributors may be used
015: * to endorse or promote products derived from this software without specific
016: * prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
028: * POSSIBILITY OF SUCH DAMAGE.
029: */
030: package de.intarsys.pdf.pd;
031:
032: import java.util.Iterator;
033: import java.util.List;
034: import de.intarsys.pdf.cos.COSBasedObject;
035: import de.intarsys.pdf.cos.COSDictionary;
036: import de.intarsys.pdf.cos.COSName;
037: import de.intarsys.pdf.cos.COSObject;
038: import de.intarsys.pdf.cos.COSStream;
039:
040: /**
041: * The PDAppearance describes the visual content of a PDAnnotation.
042: * <p>
043: * The annotation supports different visual feedback dependent on the kind of
044: * user interaction currently in effect.
045: *
046: * <code>
047: * - Normal
048: * - Down
049: * - Rollover
050: * </code>
051: *
052: * Additionaly, each of these appearances is supported for the different logical
053: * states an annotation can enter (for example "On" and "Off" in a checkbox).
054: * <p>
055: * The PDForm objects responsible for this feedback are described here.
056: *
057: */
058: public class PDAppearance extends PDObject {
059: /**
060: * The meta class implementation
061: */
062: public static class MetaClass extends PDObject.MetaClass {
063: protected MetaClass(Class instanceClass) {
064: super (instanceClass);
065: }
066:
067: protected boolean isIndirect() {
068: return false;
069: }
070:
071: protected COSBasedObject doCreateCOSBasedObject(COSObject object) {
072: return new PDAppearance(object);
073: }
074: }
075:
076: public static final COSName DK_N = COSName.constant("N");
077:
078: public static final COSName DK_R = COSName.constant("R");
079:
080: public static final COSName DK_D = COSName.constant("D");
081:
082: /** The meta class instance */
083: public static final MetaClass META = new MetaClass(MetaClass.class
084: .getDeclaringClass());
085:
086: protected PDAppearance(COSObject object) {
087: super (object);
088: }
089:
090: /**
091: * The {@link PDForm} for state <code>state</code>. <code>key</code>
092: * defines the interaction context and is one of "/D", "/R" or "/N". If no
093: * {@link PDForm} is available, return the {@link PDForm} for the "/N"
094: * context.
095: *
096: * @param key
097: * The interaction context
098: * @param state
099: * The {@link PDAnnotation} state.
100: * @return The {@link PDForm} for state <code>state</code>.
101: */
102: public PDForm getAppearance(COSName key, COSName state) {
103: PDForm form = getForm(key, state);
104: if (form == null) {
105: form = getNormalAppearance(state);
106: }
107: return form;
108: }
109:
110: public void setDownAppearance(COSName state, PDForm form) {
111: setForm(DK_D, state, form);
112: }
113:
114: public PDForm getDownAppearance(COSName state) {
115: return getForm(DK_D, state);
116: }
117:
118: public void setNormalAppearance(COSName state, PDForm form) {
119: setForm(DK_N, state, form);
120: }
121:
122: public PDForm getNormalAppearance(COSName state) {
123: return getForm(DK_N, state);
124: }
125:
126: public void setRolloverAppearance(COSName state, PDForm form) {
127: setForm(DK_R, state, form);
128: }
129:
130: public PDForm getRolloverAppearance(COSName state) {
131: return getForm(DK_R, state);
132: }
133:
134: protected void setForm(COSName key, COSName state, PDForm form) {
135: COSObject cosObject = cosGetField(key);
136: if (state == null) {
137: if (form != null) {
138: cosSetField(key, form.cosGetStream());
139: } else {
140: cosRemoveField(key);
141: }
142: } else {
143: if (!(cosObject instanceof COSDictionary)) {
144: cosObject = COSDictionary.create();
145: cosSetField(key, cosObject);
146: }
147: COSDictionary dict = (COSDictionary) cosObject;
148: if (form != null) {
149: dict.put(state, form.cosGetStream());
150: } else {
151: dict.remove(state);
152: }
153: }
154: }
155:
156: protected PDForm getForm(COSName key, COSName state) {
157: COSObject cosObject = cosGetField(key);
158: if (cosObject.isNull()) {
159: return null;
160: }
161: if (cosObject instanceof COSStream) {
162: return (PDForm) PDForm.META.createFromCos(cosObject);
163: }
164: if (cosObject instanceof COSDictionary && (state != null)) {
165: COSDictionary dict = (COSDictionary) cosObject;
166: COSStream stream = dict.get(state).asStream();
167: return (PDForm) PDForm.META.createFromCos(stream);
168: }
169: return null;
170: }
171:
172: protected void collectAppearances(COSDictionary dict,
173: List appearances) {
174: for (Iterator i = dict.values().iterator(); i.hasNext();) {
175: COSObject entry = (COSObject) i.next();
176: if (entry.isNull()) {
177: continue;
178: }
179: if (entry instanceof COSStream) {
180: COSStream entryStream = (COSStream) entry;
181: PDForm form = (PDForm) PDForm.META
182: .createFromCos(entryStream);
183: appearances.add(form);
184: }
185: if (entry instanceof COSDictionary) {
186: COSDictionary entryDict = (COSDictionary) entry;
187: collectAppearances(entryDict, appearances);
188: }
189: }
190: }
191:
192: /**
193: * <code>true</code> if this appearance dictionary has valid contents.
194: * From time to time there may be an empty /AP stub around, in this case
195: * this method returns false.
196: *
197: * @return <code>true</code> if this appearance dictionary has valid
198: * contents.
199: */
200: public boolean isDefined() {
201: return !cosGetField(DK_N).isNull();
202: }
203: }
|