001: /*
002: * $Id: TableCommand.java,v 1.3 2002/02/24 02:10:19 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: /*
052: * 03/23/2001 fixed some problems with help from Patrick Talbot
053: * 12/11/2001 fixed alignment of symbols in table cells (now bounds are taken into account)
054: */
055:
056: package org.openlaszlo.iv.flash.commands;
057:
058: import org.openlaszlo.iv.flash.parser.*;
059: import org.openlaszlo.iv.flash.api.*;
060: import org.openlaszlo.iv.flash.api.shape.*;
061: import org.openlaszlo.iv.flash.api.text.*;
062: import org.openlaszlo.iv.flash.util.*;
063:
064: import org.openlaszlo.iv.flash.context.Context;
065: import java.io.*;
066: import java.text.*;
067: import java.util.*;
068: import java.awt.geom.*;
069:
070: /**
071: * Insert Table command
072: *
073: */
074: public class TableCommand extends GenericCommand {
075:
076: protected String datasource; // datasource
077: protected String halign; // left, center, right
078: protected String valign; // top, center, bottom
079: protected int rows, cols; // number of rows and columns
080: protected double contentscale; // auto, fixed, half, double
081: protected String defsym; // default symbol name
082: protected String labelformat; // Arial, Times, Courier, name of the font
083: protected double labelscale; // auto, fixed, half, double
084: protected int labelsize; // size of label text
085: protected boolean borders; // true, false
086: protected AlphaColor bordercolor; // border color
087: protected int borderthickness; // thickness of border in twips
088: protected String mediafile; // external symbol file
089: protected String instancename; // instancename
090: protected String[] rlabels; // labels for rows
091: protected String[] clabels; // labels for columns
092:
093: protected int tableSize; // in twips
094: protected int cellWidth, cellHeight;
095: protected int winWidth;
096: protected int winHeight;
097:
098: public TableCommand() {
099: }
100:
101: protected String[] parseLabels(String s) {
102: if (s == null || s.length() == 0)
103: return null;
104: StringTokenizer st = new StringTokenizer(s, ",\t\n \r");
105: IVVector v = new IVVector();
106: while (st.hasMoreTokens()) {
107: v.addElement(st.nextToken());
108: }
109: String[] rs = new String[v.size()];
110: v.copyInto(rs);
111: return rs;
112: }
113:
114: protected double parseLabelSizing(String s) {
115: try {
116: labelsize = Integer.parseInt(s) * 20;
117: return 1.0;
118: } catch (NumberFormatException e) {
119: labelsize = 18 * 20;
120: return parseSizing(s);
121: }
122: }
123:
124: protected double parseSizing(String s) {
125: if (s.equalsIgnoreCase("fixed"))
126: return 1.0;
127: if (s.equalsIgnoreCase("auto"))
128: return -1.0;
129: if (s.equalsIgnoreCase("half"))
130: return 0.5;
131: if (s.equalsIgnoreCase("double"))
132: return 2.0;
133: return Util.toDouble(s, -1.0);
134: }
135:
136: protected void initParms(Context context) throws IVException {
137: datasource = getParameter(context, "datasource", "");
138: halign = getParameter(context, "halign");
139: valign = getParameter(context, "valign");
140: rows = getIntParameter(context, "rows", 0);
141: cols = getIntParameter(context, "cols", 0);
142: contentscale = parseSizing(getParameter(context, "sizing"));
143: defsym = getParameter(context, "defsym");
144: labelformat = getParameter(context, "labelformat");
145: labelscale = parseLabelSizing(getParameter(context,
146: "labelsizing"));
147: rlabels = parseLabels(getParameter(context, "rlabels"));
148: clabels = parseLabels(getParameter(context, "clabels"));
149: mediafile = getParameter(context, "mediafile");
150: borders = getBoolParameter(context, "borders", true);
151: bordercolor = getColorParameter(context, "bordercolor",
152: AlphaColor.black);
153: borderthickness = borders ? getIntParameter(context,
154: "borderthickness", 20) : 0;
155: instancename = getParameter(context, "instancename");
156: }
157:
158: protected Instance putSymbolInCell(Frame frame, FlashDef sym,
159: Rectangle2D rect, int layer, double scale, boolean prop) {
160: double scaleX, scaleY, translateX = rect.getMinX(), translateY = rect
161: .getMinY();
162:
163: Rectangle2D bounds = sym.getBounds();
164: double x = bounds.getX();
165: double y = bounds.getY();
166: if (scale < 0.0) {
167: double xk = cellWidth / bounds.getWidth();
168: double yk = cellHeight / bounds.getHeight();
169: if (prop) {
170: double k = Math.min(xk, yk);
171: scaleX = scaleY = k;
172: } else {
173: scaleX = xk;
174: scaleY = yk;
175: }
176: } else {
177: scaleX = scaleY = scale;
178: }
179:
180: //AffineTransform m = AffineTransform.getTranslateInstance(translateX,translateY);
181: //m.scale(scaleX, scaleY);
182: //m.translate(-x,-y);
183: AffineTransform m = new AffineTransform(scaleX, 0, 0, scaleY,
184: translateX - scaleX * x, translateY - scaleY * y);
185:
186: return frame.addInstance(sym, layer, m, null);
187: }
188:
189: protected Rectangle2D getCellRect(int col, int row) {
190: int xmin = borderthickness + (cellWidth + borderthickness)
191: * col;
192: int ymin = borderthickness + (cellHeight + borderthickness)
193: * row;
194:
195: return GeomHelper.newRectangle(xmin, ymin, cellWidth,
196: cellHeight);
197: }
198:
199: protected Script makeTable(FlashFile file, Context context,
200: Script parent, int frameNum) throws IVException {
201:
202: String[][] data;
203: try {
204: UrlDataSource ds = new UrlDataSource(datasource, file);
205: data = ds.getData();
206: } catch (IOException e) {
207: throw new IVException(Resource.ERRDATAREAD, new Object[] {
208: datasource, getCommandName() }, e);
209: }
210:
211: if (data.length < 1) {
212: throw new IVException(Resource.INVALDATASOURCE,
213: new Object[] { datasource, getCommandName() });
214: }
215:
216: Instance mainInst = getInstance();
217: Rectangle2D winBounds = GeomHelper.getTransformedSize(
218: mainInst.matrix, GeomHelper.newRectangle(-1024, -1024,
219: 2048, 2048)); // mask of the list
220: winWidth = (int) winBounds.getWidth();
221: winHeight = (int) winBounds.getHeight();
222:
223: int clipIdx = findColumn("clip", data);
224:
225: if (rows <= 0 || cols <= 0) {
226: throw new IVException(Resource.ROWSORCOLS,
227: new Object[] { getCommandName() });
228: }
229:
230: boolean isLabels = rlabels != null || clabels != null;
231: if (defsym != null || isLabels) {
232: // loading symbol file
233: if (mediafile != null) {
234: try {
235: file.addExternalFile(mediafile, true);
236: } catch (IVException e) {
237: Log.log(e);
238: }
239: }
240: // load default symbol file
241: file.getDefaultSymbolFile();
242: }
243:
244: Script tableScript = new Script(1);
245: Frame frame = tableScript.newFrame();
246:
247: int totalRows = rows;
248: int totalCols = cols;
249: if (rlabels != null)
250: totalCols++;
251: if (clabels != null)
252: totalRows++;
253:
254: // calculate cell width and height
255: cellWidth = (winWidth - borderthickness * (totalCols + 1))
256: / totalCols;
257: cellHeight = (winHeight - borderthickness * (totalRows + 1))
258: / totalRows;
259:
260: if (cellWidth <= 0 || cellHeight <= 0) {
261: Log.logRB(Resource.BORDERTOOTHICK);
262: }
263:
264: // buidl grid cells
265: Rectangle2D[][] cellRects = new Rectangle2D[totalCols][totalRows];
266: for (int c = 0; c < totalCols; c++) {
267: for (int r = 0; r < totalRows; r++) {
268: cellRects[c][r] = getCellRect(c, r);
269: }
270: }
271: // draw grid (borders)
272: if (borders) {
273: Shape shape = new Shape();
274: int fullColor = shape.addLineStyle(new LineStyle(25,
275: bordercolor));
276: int reducedColor = shape.addLineStyle(new LineStyle(25,
277: bordercolor.getReducedColor()));
278: // draw cells with full color
279: shape.setLineStyle(fullColor);
280: for (int c = 0; c < totalCols; c++) {
281: for (int r = 0; r < totalRows; r++) {
282: Rectangle2D rect = cellRects[c][r];
283: shape.movePenTo((int) rect.getMinX(), (int) rect
284: .getMaxY());
285: shape.drawLineTo((int) rect.getMinX(), (int) rect
286: .getMinY());
287: shape.drawLineTo((int) rect.getMaxX(), (int) rect
288: .getMinY());
289: }
290: }
291: // draw main table with full color
292: shape.movePenTo(winWidth, 0);
293: shape.drawLineTo(winWidth, winHeight);
294: shape.drawLineTo(0, winHeight);
295:
296: // draw cells with reduced color
297: shape.setLineStyle(reducedColor);
298: for (int c = 0; c < totalCols; c++) {
299: for (int r = 0; r < totalRows; r++) {
300: Rectangle2D rect = cellRects[c][r];
301: shape.movePenTo((int) rect.getMaxX(), (int) rect
302: .getMinY());
303: shape.drawLineTo((int) rect.getMaxX(), (int) rect
304: .getMaxY());
305: shape.drawLineTo((int) rect.getMinX(), (int) rect
306: .getMaxY());
307: }
308: }
309: // draw main table with reduced color
310: shape.movePenTo(0, winHeight);
311: shape.drawLineTo(0, 0);
312: shape.drawLineTo(winWidth, 0);
313:
314: // add shape to frame
315: frame.addInstance(shape, 2, null, null);
316: shape.setBounds(0, 0, winWidth, winHeight);
317: }
318:
319: Script defSymbol = null;
320: if (defsym != null) {
321: defSymbol = file.getScript(defsym);
322: }
323:
324: Font labelFont = null;
325: if (isLabels) {
326: if (labelformat == null)
327: labelformat = "Arial";
328: // map generator font names to font names from DefaultSymbolFile
329: if (labelformat.equals("Times"))
330: labelformat = "Times New Roman";
331: else if (labelformat.equals("Courier"))
332: labelformat = "Courier New";
333:
334: labelFont = getFont(file, labelformat);
335: }
336:
337: if (clipIdx == -1 && defSymbol == null) {
338: throw new IVException(Resource.CLIPORDEFSYM);
339: }
340:
341: int col = 0, row = 0;
342: int layer = 3;
343: int rbase = clabels != null ? 1 : 0;
344: int cbase = rlabels != null ? 1 : 0;
345:
346: // draw labels
347: if (labelFont != null) {
348: if (rlabels != null) {
349: int nLabels = Math.min(totalRows, rlabels.length);
350: for (int i = 0; i < nLabels; i++) {
351: String label = rlabels[i];
352: Rectangle2D r = cellRects[0][i + rbase];
353: Text text = newText(file, label, labelFont,
354: labelsize, AlphaColor.black, (int) r
355: .getWidth(), (int) r.getHeight());
356: ((TextItem) text.getTextItems().elementAt(0)).align = 2; // center
357: putSymbolInCell(frame, text, r, layer++,
358: labelscale, true);
359: }
360: col++;
361: }
362: if (clabels != null) {
363: int nLabels = Math.min(totalCols, clabels.length);
364: for (int i = 0; i < nLabels; i++) {
365: String label = clabels[i];
366: Rectangle2D r = cellRects[i + cbase][0];
367: Text text = newText(file, label, labelFont,
368: labelsize, AlphaColor.black, (int) r
369: .getWidth(), (int) r.getHeight());
370: ((TextItem) text.getTextItems().elementAt(0)).align = 2; // center
371: putSymbolInCell(frame, text, r, layer++,
372: labelscale, true);
373: }
374: row++;
375: }
376: }
377:
378: // process datasource
379: for (int r = 1; r < data.length; r++) {
380: Context myContext = makeContext(context, data, r);
381: Script template;
382: if (defSymbol != null) {
383: template = defSymbol;
384: } else {
385: String clipName = data[r][clipIdx];
386: template = file.getScript(clipName);
387: if (template == null) {
388: throw new IVException(Resource.CMDSCRIPTNOTFOUND,
389: new Object[] { clipName, getCommandName() });
390: }
391: }
392: Script myScript = template.copyScript();
393: file.processScript(myScript, myContext);
394:
395: Instance myInst = putSymbolInCell(frame, myScript,
396: cellRects[col][row], layer++, contentscale, true);
397:
398: if (!halign.equalsIgnoreCase("left")
399: && !valign.equalsIgnoreCase("top")) {
400: double translateX = 0.0, translateY = 0.0;
401: Rectangle2D bounds = myInst.getBounds();
402: double width = bounds.getWidth();
403: double height = bounds.getHeight();
404:
405: if (halign.equalsIgnoreCase("right")) {
406: translateX = cellWidth - width;
407: } else if (halign.equalsIgnoreCase("center")) {
408: translateX = (cellWidth - width) / 2;
409: }
410:
411: if (valign.equalsIgnoreCase("bottom")) {
412: translateY = cellHeight - height;
413: } else if (valign.equalsIgnoreCase("center")) {
414: translateY = (cellHeight - height) / 2;
415: }
416:
417: myInst.matrix.preConcatenate(AffineTransform
418: .getTranslateInstance(translateX, translateY));
419: }
420:
421: col++;
422: if (col >= totalCols) {
423: row++;
424: col = cbase;
425: if (row >= totalRows)
426: break;
427: }
428:
429: }
430:
431: return tableScript;
432: }
433:
434: public void doCommand(FlashFile file, Context context,
435: Script parent, int frameNum) throws IVException {
436: initParms(context);
437:
438: Script tableScript = makeTable(file, context, parent, frameNum);
439:
440: GeomHelper.deScaleMatrix(getInstance().matrix);
441: getInstance().matrix.translate(-winWidth / 2, -winHeight / 2);
442:
443: if (instancename != null) {
444: getInstance().name = instancename;
445: }
446:
447: getInstance().setScript(tableScript);
448: addMask(parent, frameNum, getInstance(), winWidth, winHeight);
449: }
450:
451: }
|