Index: lams_common/src/java/org/lamsfoundation/lams/learningdesign/service/ExportToolContentService.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/learningdesign/service/ExportToolContentService.java,v diff -u -r1.101.2.1.4.1 -r1.101.2.1.4.2 --- lams_common/src/java/org/lamsfoundation/lams/learningdesign/service/ExportToolContentService.java 3 Sep 2010 20:10:25 -0000 1.101.2.1.4.1 +++ lams_common/src/java/org/lamsfoundation/lams/learningdesign/service/ExportToolContentService.java 14 Sep 2010 12:35:04 -0000 1.101.2.1.4.2 @@ -60,6 +60,7 @@ import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; +import org.apache.batik.transcoder.TranscoderException; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; @@ -184,6 +185,8 @@ public static final String TOOL_FAILED_FILE_NAME = "export_failed.xml"; public static final String SVG_IMAGE_FILE_NAME = "learning_design.svg"; + + public static final String PNG_IMAGE_FILE_NAME = "learning_design.png"; private static final String ERROR_TOOL_NOT_FOUND = "error.import.matching.tool.not.found"; @@ -661,17 +664,16 @@ //generate SVG image if (format != ExportToolContentService.PACKAGE_FORMAT_IMS) { - String svgFileName = FileUtil.getFullPath(contentDir, ExportToolContentService.SVG_IMAGE_FILE_NAME); - Writer svgFile = new OutputStreamWriter(new FileOutputStream(svgFileName), "UTF-8"); SVGGenerator svgGenerator = new SVGGenerator(); - svgGenerator.generateSvg(ldDto); - OutputFormat outputFormat = new OutputFormat(svgGenerator.getSVGDocument()); - outputFormat.setLineWidth(65); - outputFormat.setIndenting(true); - outputFormat.setIndent(2); - XMLSerializer serializer = new XMLSerializer(svgFile, outputFormat); - serializer.serialize(svgGenerator.getSVGDocument()); - svgFile.close(); + svgGenerator.generateSvgDom(ldDto); + + String svgFileName = FileUtil.getFullPath(contentDir, ExportToolContentService.SVG_IMAGE_FILE_NAME); + FileOutputStream svgOutputStream = new FileOutputStream(svgFileName); + svgGenerator.streamOutDocument(svgOutputStream, SVGGenerator.OUTPUT_FORMAT_SVG); + + String pngFileName = FileUtil.getFullPath(contentDir, ExportToolContentService.PNG_IMAGE_FILE_NAME); + FileOutputStream pngOutputStream = new FileOutputStream(pngFileName); + svgGenerator.streamOutDocument(pngOutputStream, SVGGenerator.OUTPUT_FORMAT_PNG); } log.debug("Learning design xml export success"); @@ -720,7 +722,10 @@ } catch (JDOMException e) { log.error("JDOMException:", e); throw new ExportToolContentException(e); - } + } catch (TranscoderException e) { + log.error("TranscoderException:", e); + throw new ExportToolContentException(e); + } } /** Fisheye: Tag 1.2.2.1 refers to a dead (removed) revision in file `lams_common/src/java/org/lamsfoundation/lams/util/svg/ActivityTreeNodeComparator.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_common/src/java/org/lamsfoundation/lams/util/svg/SVGConstants.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/util/svg/SVGConstants.java,v diff -u -r1.4.2.2 -r1.4.2.3 --- lams_common/src/java/org/lamsfoundation/lams/util/svg/SVGConstants.java 3 Sep 2010 20:10:25 -0000 1.4.2.2 +++ lams_common/src/java/org/lamsfoundation/lams/util/svg/SVGConstants.java 14 Sep 2010 12:35:04 -0000 1.4.2.3 @@ -32,8 +32,8 @@ public static final String ROOT_ELEMENT_ID = "rootElement"; // canvas dimensions - public static final String CANVAS_DEFAULT_WIDTH = "100%"; - public static final String CANVAS_DEFAULT_HEIGHT = "100%"; + public static final int CANVAS_DEFAULT_WIDTH = 1024; + public static final int CANVAS_DEFAULT_HEIGHT = 768; // gate dimensions public static final int GATE_WIDTH = 30; Index: lams_common/src/java/org/lamsfoundation/lams/util/svg/SVGGenerator.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/util/svg/SVGGenerator.java,v diff -u -r1.4.2.2 -r1.4.2.3 --- lams_common/src/java/org/lamsfoundation/lams/util/svg/SVGGenerator.java 3 Sep 2010 20:10:25 -0000 1.4.2.2 +++ lams_common/src/java/org/lamsfoundation/lams/util/svg/SVGGenerator.java 14 Sep 2010 12:35:04 -0000 1.4.2.3 @@ -26,12 +26,23 @@ import java.awt.Dimension; import java.awt.geom.Point2D; import java.io.IOException; +import java.io.OutputStream; +import java.io.StringWriter; +import java.io.Writer; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.Iterator; +import java.util.TreeSet; import org.apache.batik.dom.svg.SVGDOMImplementation; +import org.apache.batik.transcoder.TranscoderException; +import org.apache.batik.transcoder.TranscoderInput; +import org.apache.batik.transcoder.TranscoderOutput; +import org.apache.batik.transcoder.image.PNGTranscoder; import org.apache.commons.lang.StringUtils; +import org.apache.xml.serialize.OutputFormat; +import org.apache.xml.serialize.XMLSerializer; import org.jdom.JDOMException; import org.lamsfoundation.lams.learningdesign.Activity; import org.lamsfoundation.lams.learningdesign.dto.AuthoringActivityDTO; @@ -46,40 +57,28 @@ /** * Generates SVG document based on exported learning design's xml file. * - * To be able to see resulted SVG image in swing component use the following lines. - JSVGCanvas canvas = new JSVGCanvas(); - JFrame f = new JFrame(); - f.getContentPane().add(canvas); - canvas.setSVGDocument(svgGenerator.getSVGDocument()); - f.pack(); - f.setSize(CANVAS_DEFAULT_WIDTH, CANVAS_DEFAULT_HEIGHT); - f.setVisible(true); - * * @author Andrey Balan */ public class SVGGenerator extends SVGConstants{ + public final static int OUTPUT_FORMAT_SVG = 1; + public final static int OUTPUT_FORMAT_PNG = 2; + public final static int OUTPUT_FORMAT_SYSTEM_OUT = 3; + private SVGDocument doc; - private String width = null; - private String height = null; - private Double scale = null; + private Integer adjustedDocumentWidth = null; /** * Sets up Svg root and defs. */ private void initializeSvgDocument() { - String canvasWidth = (width == null) ? CANVAS_DEFAULT_WIDTH : width; - String canvasHeigth = (height == null) ? CANVAS_DEFAULT_HEIGHT : height; - Double scale = (this.scale == null) ? 1 : this.scale; // Create an SVG document. DOMImplementation impl = SVGDOMImplementation.getDOMImplementation(); doc = (SVGDocument) impl.createDocument(SVG_NAMESPACE, "svg", null); // Get the root element (the 'svg' element). Element svgRoot = doc.getDocumentElement(); // Set the width and height attributes on the root 'svg' element. - svgRoot.setAttributeNS(null, "width", canvasWidth); - svgRoot.setAttributeNS(null, "height", canvasHeigth); svgRoot.setAttributeNS(null, "xmlns", SVG_NAMESPACE); svgRoot.setAttributeNS(null, "xmlns:xlink", SVG_NAMESPACE_XLINK); @@ -103,19 +102,23 @@ // Create root g element Element g = doc.createElementNS(SVG_NAMESPACE, "g"); g.setAttributeNS(null, "id", ROOT_ELEMENT_ID); - g.setAttributeNS(null, "transform", "scale(" + scale + " ," + scale + ")"); svgRoot.appendChild(g); - } - public void setSVGDocumentParameters(String width, String height, Double scale) { - this.width = width; - this.height = height; - this.scale = scale; + public void adjustDocumentWidth(Integer width) { + this.adjustedDocumentWidth = width; } - public SVGDocument getSVGDocument() { - return doc; + public Dimension getDocumentWidthHeight() { + + Element svg = doc.getDocumentElement(); + String widthStr = svg.getAttributeNS(null, "width"); + String heightStr = svg.getAttributeNS(null, "height"); + + int width = Integer.parseInt(widthStr); + int height = Integer.parseInt(heightStr); + + return new Dimension(width, height); } /** @@ -125,7 +128,7 @@ * @throws JDOMException * @throws IOException */ - public void generateSvg(LearningDesignDTO learningDesign) throws JDOMException, IOException { + public void generateSvgDom(LearningDesignDTO learningDesign) throws JDOMException, IOException { initializeSvgDocument(); //initialize all tree nodes @@ -159,8 +162,9 @@ Point2D fromIntersection = SVGTrigonometryUtils.getRectangleAndLineSegmentIntersection(fromActivity, toActivity); Point2D toIntersection = SVGTrigonometryUtils.getRectangleAndLineSegmentIntersection(toActivity, fromActivity); - //skip optional sequence's childs - if (fromActivity.isOptionalSequenceActivityChild()) { + //skip optional sequence's childs and lines between overlapped activities + if (fromActivity.isOptionalSequenceActivityChild() + || (fromIntersection == null) || (toIntersection == null)) { continue; } @@ -176,8 +180,8 @@ double a = (toIntersection.getX() - fromIntersection.getX()); double b = (toIntersection.getY() - fromIntersection.getY()); - double yArrowShift = 5* b/Math.sqrt(a*a + b*b); - double xArrowShift = 5* a/Math.sqrt(a*a + b*b); + double yArrowShift = (a*a + b*b == 0) ? 0 : 5* b/Math.sqrt(a*a + b*b); + double xArrowShift = (a*a + b*b == 0) ? 0 : 5* a/Math.sqrt(a*a + b*b); // Create the arrowhead Element arrowhead = doc.createElementNS(SVG_NAMESPACE, "line"); arrowhead.setAttributeNS(null, "id", "arrowhead_" + transition.getFromActivityID() + "_to_" + transition.getToActivityID()); @@ -197,6 +201,8 @@ //**************** Draw activities ******************************************************** //tree traverse treeTraverse(root); + + setUpDocumentWidthHeight(allNodes.values()); } /** @@ -368,7 +374,9 @@ startingPoint.setAttributeNS(null, "style", "fill:#000000"); g.appendChild(startingPoint); - Iterator sequenceNodeIterator = node.getChildren().iterator(); + TreeSet sequenceNodes = new TreeSet(new ActivityTreeNodeComparator()); + sequenceNodes.addAll(node.getChildren()); + Iterator sequenceNodeIterator = sequenceNodes.iterator(); for (int sequenceIndex = -1; sequenceNodeIterator.hasNext() && (sequenceIndex < 4); sequenceIndex++) { ActivityTreeNode sequenceNode = sequenceNodeIterator.next(); double previousActivityPointX = startingPointX + BRANCHING_ACTIVITY_POINT/2; @@ -509,6 +517,128 @@ } + /** + * Returns estimated width and height of the whole SVG document. + * + * @param nodes + * @param x + * @param y + * @param g + * @return + */ + private void setUpDocumentWidthHeight(Collection nodes) { + int maxX = 0; + int maxY = 0; + for (ActivityTreeNode node : nodes) { + Dimension dimension = node.getActivityDimension(); + + int rightestActivityPoint = node.getActivityCoordinates().x + dimension.width; + if (rightestActivityPoint > maxX) { + maxX = rightestActivityPoint; + } + int bottomActivityPoint = node.getActivityCoordinates().y + dimension.height; + if (bottomActivityPoint > maxY) { + maxY = bottomActivityPoint; + } + } + + int minX = Integer.MAX_VALUE; + int minY = Integer.MAX_VALUE; + for (ActivityTreeNode node : nodes) { + AuthoringActivityDTO activity = node.getActivity(); + if (activity.getParentActivityID() == null) { + int leftActivityPoint = node.getActivityCoordinates().x; + if (leftActivityPoint < minX) { + minX = leftActivityPoint; + } + int topActivityPoint = node.getActivityCoordinates().y; + if (topActivityPoint < minY) { + minY = topActivityPoint; + } + } + } + + Element svg = doc.getDocumentElement(); + + //Removes padding of the SVG image. + minX--; + minY--; + int width = maxX - minX +5; + int height = maxY - minY +5; + svg.setAttributeNS(null, "viewBox", minX + " " + minY + " " + Integer.toString(width) + " " + Integer.toString(height)); + + // adjust width and height to adjustedDocumentWidth + if ((adjustedDocumentWidth != null) && adjustedDocumentWidth < width) { + double scale = (double) adjustedDocumentWidth / (double) width; + width = adjustedDocumentWidth; + height *= scale; + } + + //Sets the width and height + svg.setAttributeNS(null, "width", Integer.toString(width)); + svg.setAttributeNS(null, "height", Integer.toString(height)); + } + + /** + * Stream out SVG document into specified outputStream. + * + * @param outputStream stream where we put resulted data. It can be null in case of RESULT_TYPE_DISPLAY + * @param resultType one of SVGGenerator's constants: either RESULT_TYPE_SVG or RESULT_TYPE_PNG or RESULT_TYPE_DISPLAY + * + * @throws TranscoderException + * @throws IOException + */ + public void streamOutDocument(OutputStream outputStream, int resultType) throws TranscoderException, IOException { + + switch (resultType) { + case OUTPUT_FORMAT_SVG: + OutputFormat format = new OutputFormat(doc); + format.setLineWidth(65); + format.setIndenting(true); + format.setIndent(2); + + XMLSerializer serializer = new XMLSerializer(outputStream, format); + serializer.serialize(doc); + outputStream.flush(); + outputStream.close(); + break; + + case OUTPUT_FORMAT_PNG: + PNGTranscoder transcoder = new PNGTranscoder(); + // Set the transcoder input and output. + TranscoderInput input = new TranscoderInput(doc); + TranscoderOutput output = new TranscoderOutput(outputStream); + + // Perform the transcoding. + transcoder.transcode(input, output); + outputStream.flush(); + outputStream.close(); + break; + +// // to see resulted SVG image in swing component +// case OUTPUT_FORMAT_DISPLAY: +// JSVGCanvas canvas = new JSVGCanvas(); +// JFrame f = new JFrame(); +// f.getContentPane().add(canvas); +// canvas.setSVGDocument(doc); +// f.pack(); +// f.setSize(CANVAS_DEFAULT_WIDTH, CANVAS_DEFAULT_HEIGHT); +// f.setVisible(true); +// break; + + default: + OutputFormat format2 = new OutputFormat(doc); + format2.setLineWidth(65); + format2.setIndenting(true); + format2.setIndent(2); + Writer out = new StringWriter(); + XMLSerializer serializer2 = new XMLSerializer(out, format2); + serializer2.serialize(doc); + System.out.println(out.toString()); + } + + } + //**************** Auxiliary methods for creating svg components ******************************************************** private void createRectangle(ActivityTreeNode node, double x, double y, Element g) { @@ -634,14 +764,14 @@ || activity.getActivityTypeID().equals(Activity.SCHEDULE_GATE_ACTIVITY_TYPE) || activity.getActivityTypeID().equals(Activity.PERMISSION_GATE_ACTIVITY_TYPE) || activity.getActivityTypeID().equals(Activity.CONDITION_GATE_ACTIVITY_TYPE)) { - imageFileName = "stop.png"; + imageFileName = "icon_gate.png"; } else if (activity.getActivityTypeID().equals(Activity.CHOSEN_BRANCHING_ACTIVITY_TYPE) || activity.getActivityTypeID().equals(Activity.GROUP_BRANCHING_ACTIVITY_TYPE) || activity.getActivityTypeID().equals(Activity.TOOL_BRANCHING_ACTIVITY_TYPE)) { imageFileName = "icon_branching.png"; } else if (activity.getActivityTypeID().equals(Activity.OPTIONS_WITH_SEQUENCES_TYPE) || activity.getActivityTypeID().equals(Activity.OPTIONS_ACTIVITY_TYPE)) { - imageFileName = "icon_optional.png"; + imageFileName = "icon_urlcontentmessageboard.png"; } else { imageFileName = "icon_grouping.png"; }