001: /*
002: * $Id: Frame.java,v 1.10 2002/08/08 23:26:54 skavish Exp $
003: *
004: * ==========================================================================
005: *
006: * The JGenerator Software License, Version 1.0
007: *
008: * Copyright (c) 2000 Dmitry Skavish (skavish@usa.net). All rights reserved.
009: *
010: * Redistribution and use in source and binary forms, with or without
011: * modification, are permitted provided that the following conditions are met:
012: *
013: * 1. Redistributions of source code must retain the above copyright
014: * notice, this list of conditions and the following disclaimer.
015: *
016: * 2. Redistributions in binary form must reproduce the above copyright
017: * notice, this list of conditions and the following disclaimer in
018: * the documentation and/or other materials provided with the
019: * distribution.
020: *
021: * 3. The end-user documentation included with the redistribution, if
022: * any, must include the following acknowlegement:
023: * "This product includes software developed by Dmitry Skavish
024: * (skavish@usa.net, http://www.flashgap.com/)."
025: * Alternately, this acknowlegement may appear in the software itself,
026: * if and wherever such third-party acknowlegements normally appear.
027: *
028: * 4. The name "The JGenerator" must not be used to endorse or promote
029: * products derived from this software without prior written permission.
030: * For written permission, please contact skavish@usa.net.
031: *
032: * 5. Products derived from this software may not be called "The JGenerator"
033: * nor may "The JGenerator" appear in their names without prior written
034: * permission of Dmitry Skavish.
035: *
036: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
037: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
038: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
039: * DISCLAIMED. IN NO EVENT SHALL DMITRY SKAVISH OR THE OTHER
040: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
041: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
042: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
043: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
044: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
045: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
046: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
047: * SUCH DAMAGE.
048: *
049: */
050:
051: package org.openlaszlo.iv.flash.api;
052:
053: import org.openlaszlo.iv.flash.util.*;
054: import org.openlaszlo.iv.flash.commands.*;
055:
056: import org.openlaszlo.iv.flash.api.shape.*;
057: import org.openlaszlo.iv.flash.api.text.*;
058: import org.openlaszlo.iv.flash.api.action.*;
059: import org.openlaszlo.iv.flash.context.Context;
060:
061: import java.awt.geom.AffineTransform;
062: import java.awt.geom.Rectangle2D;
063: import java.io.*;
064: import java.util.*;
065:
066: /**
067: * A movie frame
068: * <P>
069: * A frame contains zero or more FlashObjects.
070: * A frame can have a name (to be referenced in gotoFrame action).
071: *
072: * @author Dmitry Skavish
073: * @see Timeline
074: */
075: public final class Frame extends IVVector {
076:
077: private String name;
078: private boolean is_anchor; // flash mx
079:
080: /**
081: * Creates empty frame
082: */
083: public Frame() {
084: }
085:
086: /**
087: * Creates frame of specified capacity
088: *
089: * @param capacity capacity of created frame
090: */
091: public Frame(int capacity) {
092: super (capacity);
093: }
094:
095: /**
096: * Creates frame from specified vector
097: * <P>
098: * Creates frame with capacity equal to the size of specified vector
099: * and copies all data from the specified vector to this frame
100: *
101: * @param data vector to copy from
102: */
103: public Frame(IVVector data) {
104: super (data);
105: }
106:
107: /**
108: * Returns name of this frame
109: *
110: * @return name of this frame or null
111: */
112: public String getName() {
113: return name;
114: }
115:
116: /**
117: * Assings name to this frame
118: *
119: * @param name new name of this frame
120: */
121: public void setName(String name) {
122: this .name = name;
123: }
124:
125: /**
126: * Sets whether this frame is named anchor or not
127: * <P>
128: * Only for Flash MX
129: *
130: * @param is_anchor this frame is named anchor if its true
131: */
132: public void setAnchor(boolean is_anchor) {
133: this .is_anchor = is_anchor;
134: }
135:
136: /**
137: * Returns whether this frame is named anchor or not
138: * <P>
139: * Only for Flash MX
140: *
141: * @return whether this frame is named anchor or not
142: */
143: public boolean isAnchor() {
144: return is_anchor;
145: }
146:
147: /**
148: * Adds flash object's instance to this frame
149: * <P>
150: * Creates new instance and adds it to this frame using specified
151: * depth, matrix and cxform.
152: *
153: * @param def flash definition instance of which has to be added
154: * @param depth layer depth of the instance to be added
155: * @param matrix transformation matrix for the instance (optional)
156: * @param cxform transformation color for the instance (optional)
157: * @return added instance
158: * @see Instance
159: */
160: public Instance addInstance(FlashDef def, int depth,
161: AffineTransform matrix, CXForm cxform) {
162: return addInstance(def, depth, matrix, cxform, null);
163: }
164:
165: /**
166: * Adds flash object's instance to this frame
167: * <P>
168: * Creates new instance and adds it to this frame using specified
169: * depth, matrix, cxform and name.
170: *
171: * @param def flash definition instance of which has to be added
172: * @param depth layer depth of the instance to be added
173: * @param matrix transformation matrix for the instance (optional)
174: * @param cxform transformation color for the instance (optional)
175: * @param name name of the instance (optional)
176: * @return added instance
177: * @see Instance
178: */
179: public Instance addInstance(FlashDef def, int depth,
180: AffineTransform matrix, CXForm cxform, String name) {
181: Instance inst = new Instance();
182: inst.def = def;
183: inst.depth = depth;
184: inst.matrix = matrix;
185: inst.cxform = cxform;
186: inst.name = name;
187: addFlashObject(inst);
188: return inst;
189: }
190:
191: /**
192: * Adds new instance of flash object which is already on a timeline with new transformation matrix
193: * <P>
194: * Creates new instance of an existing on a timeline flash object
195: * and assigns specified transformation matrix to it.
196: *
197: * @param depth layer depth of the existing instance
198: * @param matrix transformation matrix for the instance (optional)
199: * @return added instance
200: */
201: public Instance addInstance(int depth, AffineTransform matrix) {
202: return addInstance(depth, matrix, null);
203: }
204:
205: /**
206: * Adds new instance of flash object which is already on a timeline with new transformation matrix
207: * <P>
208: * Creates new instance of an existing on a timeline flash object
209: * and assigns specified transformation and color matrixes to it.
210: *
211: * @param depth layer depth of the existing instance
212: * @param matrix transformation matrix for the instance (optional)
213: * @param cxform color matrix for the instance (optional)
214: * @return added instance
215: */
216: public Instance addInstance(int depth, AffineTransform matrix,
217: CXForm cxform) {
218: Instance inst = new Instance();
219: inst.depth = depth;
220: inst.matrix = matrix;
221: inst.cxform = cxform;
222: inst.isMove = true;
223: addFlashObject(inst);
224: return inst;
225: }
226:
227: /**
228: * Adds specified instance into specified layer
229: *
230: * @param inst specified instance
231: * @param depth layer depth
232: * @return added instance
233: */
234: public Instance addInstance(Instance inst, int depth) {
235: inst.depth = depth;
236: addFlashObject(inst);
237: return inst;
238: }
239:
240: /**
241: * "Removes" flash object's instance from specified layer
242: * <p>
243: * Does not actually remove any instance from this frame, but rather adds
244: * flash tag RemoveObject to this frame.
245: *
246: * @param depth layer depth of the existing instance to be removed
247: * @return RemoveObject tag
248: */
249: public RemoveObject removeInstance(int depth) {
250: RemoveObject ro = new RemoveObject();
251: ro.depth = depth;
252: addFlashObject(ro);
253: return ro;
254: }
255:
256: /**
257: * Adds specified flash object to this frame
258: *
259: * @param o flash object to be added
260: */
261: public void addFlashObject(FlashObject o) {
262: addElement(o);
263: }
264:
265: /**
266: * Replaces flash object at specified index with new one
267: *
268: * @param o new flash object to be replaced with
269: * @param index specified index
270: */
271: public void setFlashObjectAt(FlashObject o, int index) {
272: setElementAt(o, index);
273: }
274:
275: /**
276: * Returns flash object at specified index
277: *
278: * @param index specified index
279: * @return flash object at specified index
280: */
281: public FlashObject getFlashObjectAt(int index) {
282: return (FlashObject) elementAt(index);
283: }
284:
285: /**
286: * Removes flash object at specified index
287: *
288: * @param index specified index
289: * @return removed flash object
290: */
291: public FlashObject removeFlashObjectAt(int index) {
292: return (FlashObject) removeElementAt(index);
293: }
294:
295: /**
296: * Removes specified flash object from this frame
297: *
298: * @param o specified flash object to be removed
299: */
300: public void remove(FlashObject o) {
301: removeElement(o);
302: }
303:
304: /**
305: * Writes content of this frame to flash buffer
306: * <P>
307: * Has to be used only when this frame is NOT from main timeline.
308: *
309: * @param fob flash buffer to write to
310: */
311: public void write(FlashOutput fob) {
312: if (name != null)
313: writeFrameLabel(fob);
314: super .write(fob);
315: Tag.SHOWFRAME_TAG.write(fob);
316: }
317:
318: /**
319: * Writes content of this frame to flash buffer
320: * <P>
321: * Has to be used only when this frame is from main timeline.
322: *
323: * @param fob flash buffer to write to
324: * @param dc dependencies collector
325: */
326: public void generate(FlashOutput fob, DepsCollector dc) {
327: if (name != null)
328: writeFrameLabel(fob);
329: for (int i = 0; i < top; i++) {
330: FlashObject fo = (FlashObject) objects[i];
331: fo.generate(fob, dc);
332: }
333: Tag.SHOWFRAME_TAG.write(fob);
334: }
335:
336: /**
337: * Collects dependencies of all the object from this frame
338: *
339: * @param dc dependencies collector
340: */
341: public void collectDeps(DepsCollector dc) {
342: for (int i = 0; i < top; i++) {
343: FlashObject fo = (FlashObject) objects[i];
344: fo.collectDeps(dc);
345: }
346: }
347:
348: /**
349: * Processes all the scripts from this frame in the specified context
350: *
351: * @param file flash file to be used for processing scripts
352: * @param context context to be used for processing scripts
353: * @exception IVException
354: */
355: public void process(FlashFile file, Context context)
356: throws IVException {
357: name = context.apply(name);
358: for (int i = 0; i < top; i++) {
359: FlashObject fo = (FlashObject) objects[i];
360: file.processObject(fo, context);
361: }
362: }
363:
364: /**
365: * Applies specified context to all the object from this frame
366: *
367: * @param context specified context
368: */
369: public void apply(Context context) {
370: name = context.apply(name);
371: for (int i = 0; i < top; i++) {
372: FlashObject fo = (FlashObject) objects[i];
373: fo.apply(context);
374: }
375: }
376:
377: /**
378: * Performs all generator commands from this frame
379: *
380: * @param file flash file to used for processing commands
381: * @param context context to used for processing commands
382: * @param parent parent script
383: * @param frame this frame's number in the parent script's timelime
384: * @exception IVException thrown if there were some errors during command processing
385: */
386: public void doCommand(FlashFile file, Context context,
387: Script parent, int frame) throws IVException {
388: for (int i = 0; i < top; i++) {
389: FlashObject fo = (FlashObject) objects[i];
390: if (!(fo instanceof Instance))
391: continue;
392: Instance instance = (Instance) fo;
393: GenericCommand cmd = instance.command;
394:
395: if (cmd != null) {
396: try {
397: cmd.doCommand(file, context, parent, frame);
398: } catch (Throwable t) {
399: Log.logRB(Resource.ERRDOCMD, new Object[] {
400: file.getFullName(), parent.getName(),
401: String.valueOf(frame + 1),
402: cmd.getCommandName() }, t);
403:
404: if (PropertyManager.showErrorsInline) {
405: // create script with gray rectangle and text in place of the placeholder
406: Script script = new Script(1);
407: Frame fr = script.newFrame();
408: Shape shape = new Shape();
409: shape.setLineStyle(new LineStyle(20,
410: AlphaColor.black));
411: shape.setFillStyle0(FillStyle
412: .newSolid(new AlphaColor(150, 150, 150,
413: 150)));
414: Rectangle2D r = GeomHelper.newRectangle(-1024,
415: -1024, 2048, 2048);
416: shape.drawRectangle(r);
417: shape.setBounds(r);
418: fr.addInstance(shape, 1, null, null);
419:
420: FlashFile defFile = file.getDefaultSymbolFile();
421: if (defFile != null) {
422: Font font = defFile.getFont("Arial");
423: if (font != null) {
424: String msg = cmd.getCommandName()
425: + " : " + t.getMessage();
426: Text text = Text.newText();
427: TextItem item = new TextItem(msg, font,
428: 8 * 20, AlphaColor.black);
429: text.addTextItem(item);
430: text.setBounds((Rectangle2D) r.clone());
431: AffineTransform m = AffineTransform
432: .getTranslateInstance(-1024,
433: -1024);
434: fr.addInstance(text, 2, m, null);
435: }
436: }
437: instance.def = script;
438: instance.command = null;
439: } else {
440: // just put empty shape as a definition for the instance
441: instance.def = Shape.newEmptyShape1();
442: instance.command = null;
443: }
444: }
445: }
446: }
447: }
448:
449: /**
450: * Adds bounds of all the object from this frame to the specified rectangle
451: *
452: * @param rect specified bounds
453: */
454: public void addBounds(Rectangle2D rect) {
455: for (int i = 0; i < top; i++) {
456: FlashObject fo = (FlashObject) objects[i];
457: GeomHelper.add(rect, fo.getBounds());
458: }
459: }
460:
461: /**
462: * Appends all the objects from the specified frame to this one
463: *
464: * @param f frame to be added to this one
465: */
466: public void append(Frame f) {
467: for (int i = 0; i < f.size(); i++) {
468: addFlashObject(f.getFlashObjectAt(i));
469: }
470: }
471:
472: /**
473: * Returns true if this frame is constant
474: * <P>
475: * Returns true if all the objects from this frame are constants.
476: *
477: * @return true - if this frame is constant
478: */
479: public boolean isConstant() {
480: if (Util.hasVar(name))
481: return false;
482: for (int i = 0; i < top; i++) {
483: FlashObject fo = (FlashObject) objects[i];
484: if (!fo.isConstant())
485: return false;
486: }
487: return true;
488: }
489:
490: /**
491: * Creates a copy of this frame
492: * <P>
493: * The copy contains copies of all the objects
494: *
495: * @param copier copier to be used when copying
496: * @return Frame casted to IVVector
497: */
498: public IVVector getCopy(ScriptCopier copier) {
499: Frame c = new Frame(size());
500: for (int i = 0; i < top; i++) {
501: FlashObject fo = (FlashObject) objects[i];
502: c.setElementAt(fo.getCopy(copier), i);
503: }
504: c.setName(name);
505: return c;
506: }
507:
508: /**
509: * Add a stop action to this frame. We do this a lot so it's nice to
510: * have this code in one place.
511: */
512: public void addStopAction() {
513: DoAction action = new DoAction();
514:
515: action.program = new Program();
516: action.program.stop();
517:
518: addFlashObject(action);
519: }
520:
521: private void writeFrameLabel(FlashOutput fob) {
522: fob.writeTag(Tag.FRAMELABEL, name.length()
523: + (is_anchor ? 2 : 1));
524: fob.writeStringZ(name);
525: if (is_anchor)
526: fob.writeByte(1);
527: }
528:
529: }
|