0001: /*
0002: * Copyright 2006-2007 Pentaho Corporation. All rights reserved.
0003: * This software was developed by Pentaho Corporation and is provided under the terms
0004: * of the Mozilla Public License, Version 1.1, or any later version. You may not use
0005: * this file except in compliance with the license. If you need a copy of the license,
0006: * please go to http://www.mozilla.org/MPL/MPL-1.1.txt.
0007: *
0008: * Software distributed under the Mozilla Public License is distributed on an "AS IS"
0009: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to
0010: * the license for the specific language governing your rights and limitations.
0011: *
0012: * Additional Contributor(s): Martin Schmid gridvision engineering GmbH
0013: */
0014: package org.pentaho.reportdesigner.crm.report.model;
0015:
0016: import org.gjt.xpp.XmlPullNode;
0017: import org.jetbrains.annotations.NonNls;
0018: import org.jetbrains.annotations.NotNull;
0019: import org.jetbrains.annotations.Nullable;
0020: import org.pentaho.reportdesigner.crm.report.GraphicsContext;
0021: import org.pentaho.reportdesigner.crm.report.PropertyKeys;
0022: import org.pentaho.reportdesigner.crm.report.UndoConstants;
0023: import org.pentaho.reportdesigner.crm.report.datasetplugin.DataSetPlugin;
0024: import org.pentaho.reportdesigner.crm.report.datasetplugin.DataSetPluginRegistry;
0025: import org.pentaho.reportdesigner.crm.report.datasetplugin.properties.PropertiesDataSetReportElement;
0026: import org.pentaho.reportdesigner.crm.report.model.dataset.DataSetsReportElement;
0027: import org.pentaho.reportdesigner.crm.report.model.functions.ExpressionRegistry;
0028: import org.pentaho.reportdesigner.crm.report.model.functions.FunctionGenerator;
0029: import org.pentaho.reportdesigner.crm.report.reportelementinfo.ReportElementInfo;
0030: import org.pentaho.reportdesigner.crm.report.reportelementinfo.ReportElementInfoFactory;
0031: import org.pentaho.reportdesigner.crm.report.reportexporter.ReportCreationException;
0032: import org.pentaho.reportdesigner.crm.report.reportexporter.ReportVisitor;
0033: import org.pentaho.reportdesigner.lib.client.undo.Undo;
0034: import org.pentaho.reportdesigner.lib.client.undo.UndoEntry;
0035: import org.pentaho.reportdesigner.lib.client.util.DoubleDimension;
0036: import org.pentaho.reportdesigner.lib.client.util.MathUtils;
0037: import org.pentaho.reportdesigner.lib.client.util.UncaughtExcpetionsModel;
0038: import org.pentaho.reportdesigner.lib.common.xml.ObjectConverterFactory;
0039: import org.pentaho.reportdesigner.lib.common.xml.XMLConstants;
0040: import org.pentaho.reportdesigner.lib.common.xml.XMLContext;
0041: import org.pentaho.reportdesigner.lib.common.xml.XMLExternalizable;
0042: import org.pentaho.reportdesigner.lib.common.xml.XMLUtils;
0043: import org.pentaho.reportdesigner.lib.common.xml.XMLWriter;
0044:
0045: import java.awt.*;
0046: import java.awt.geom.Arc2D;
0047: import java.awt.geom.GeneralPath;
0048: import java.awt.geom.Point2D;
0049: import java.awt.geom.Rectangle2D;
0050: import java.beans.PropertyChangeListener;
0051: import java.beans.PropertyChangeSupport;
0052: import java.io.IOException;
0053: import java.util.ArrayList;
0054: import java.util.LinkedHashSet;
0055: import java.util.logging.Level;
0056: import java.util.logging.Logger;
0057:
0058: /**
0059: * User: Martin
0060: * Date: 13.10.2005
0061: * Time: 12:19:15
0062: */
0063: public abstract class ReportElement implements XMLExternalizable,
0064: Cloneable {
0065: @NonNls
0066: @NotNull
0067: private static final Logger LOG = Logger
0068: .getLogger(ReportElement.class.getName());
0069:
0070: @NotNull
0071: private PropertyChangeSupport propertyChangeSupport;
0072:
0073: @Nullable
0074: private ReportElement parent;
0075: @NotNull
0076: private ArrayList<ReportElement> children;
0077:
0078: @NotNull
0079: Rectangle2D.Double origRectangle;
0080: @NotNull
0081: Rectangle2D.Double rectangle;
0082:
0083: @NotNull
0084: Point2D.Double position;
0085:
0086: @NotNull
0087: DoubleDimension minimumSize;
0088: @NotNull
0089: private DoubleDimension preferredSize;
0090: @NotNull
0091: private DoubleDimension maximumSize;
0092: @NotNull
0093: private ElementPadding padding;
0094: @NotNull
0095: private ElementBorderDefinition elementBorder;
0096:
0097: @Nullable
0098: private Color background;
0099:
0100: private boolean dynamicContent;
0101:
0102: protected boolean invalid;
0103:
0104: @NotNull
0105: private String name;
0106:
0107: @NotNull
0108: private StyleExpressions styleExpressions;
0109:
0110: @Nullable
0111: private Undo undo;
0112:
0113: private double elementRepaintBorder;
0114:
0115: protected ReportElement() {
0116: propertyChangeSupport = new PropertyChangeSupport(this );
0117:
0118: children = new ArrayList<ReportElement>();
0119:
0120: origRectangle = new Rectangle2D.Double();
0121: rectangle = new Rectangle2D.Double();
0122:
0123: position = new Point2D.Double();
0124: minimumSize = new DoubleDimension();
0125: preferredSize = new DoubleDimension();
0126: maximumSize = new DoubleDimension();
0127:
0128: background = null;
0129:
0130: dynamicContent = false;
0131:
0132: invalid = true;
0133:
0134: //element properties
0135: this .name = "Element@" + System.identityHashCode(this );//NON-NLS
0136:
0137: styleExpressions = new StyleExpressions();
0138:
0139: padding = new ElementPadding();
0140: elementBorder = new ElementBorderDefinition();
0141:
0142: elementRepaintBorder = 0;
0143: }
0144:
0145: @Nullable
0146: public Undo getUndo() {
0147: return undo;
0148: }
0149:
0150: public void setUndo(@Nullable
0151: Undo undo) {
0152: this .undo = undo;
0153:
0154: for (ReportElement reportElement : children) {
0155: reportElement.setUndo(undo);
0156: }
0157: }
0158:
0159: @NotNull
0160: public String getName() {
0161: return name;
0162: }
0163:
0164: public void setName(@NonNls
0165: @NotNull
0166: final String name) {
0167: //noinspection ConstantConditions
0168: if (name == null) {
0169: throw new IllegalArgumentException("name must not be null");
0170: }
0171:
0172: final String oldName = this .name;
0173: this .name = name;
0174:
0175: Undo undo = getUndo();
0176: if (undo != null && !undo.isInProgress()) {
0177: undo.startTransaction(PropertyKeys.NAME);
0178: undo.add(new UndoEntry() {
0179: public void undo() {
0180: setName(oldName);
0181: }
0182:
0183: public void redo() {
0184: setName(name);
0185: }
0186: });
0187: undo.endTransaction();
0188: }
0189:
0190: firePropertyChange(PropertyKeys.NAME, oldName, name);
0191: }
0192:
0193: @Nullable
0194: public ReportElement getParent() {
0195: return parent;
0196: }
0197:
0198: void setParent(@Nullable
0199: final ReportElement parent) {
0200: this .parent = parent;
0201: }
0202:
0203: @Nullable
0204: public Report getReport() {
0205: if (parent == null) {
0206: return null;
0207: } else {
0208: return parent.getReport();
0209: }
0210: }
0211:
0212: @NotNull
0213: public ArrayList<ReportElement> getChildren() {
0214: return children;
0215: }
0216:
0217: public boolean isDescendant(@NotNull
0218: ReportElement parent) {
0219: ReportElement p = this ;
0220: while ((p = p.getParent()) != null) {
0221: //noinspection ObjectEquality
0222: if (p == parent) {
0223: return true;
0224: }
0225: }
0226:
0227: return false;
0228: }
0229:
0230: public void addChild(@NotNull
0231: final ReportElement child) {
0232: //noinspection ConstantConditions
0233: if (child == null) {
0234: throw new IllegalArgumentException("child must not be null");
0235: }
0236:
0237: Undo undo = getUndo();
0238: child.setUndo(undo);
0239:
0240: final ReportElement oldParent = child.getParent();
0241: if (oldParent != null) {
0242: oldParent.removeChild(child);
0243: }
0244: child.setParent(this );
0245: children.add(child);
0246:
0247: if (undo != null && !undo.isInProgress()) {
0248: undo.startTransaction(UndoConstants.ADD_CHILD);
0249: undo.add(new UndoEntry() {
0250: public void undo() {
0251: removeChild(child);
0252: child.setParent(oldParent);
0253: }
0254:
0255: public void redo() {
0256: addChild(child);
0257: }
0258: });
0259: undo.endTransaction();
0260: }
0261:
0262: firePropertyChange(PropertyKeys.CHILD_ADDED, null, child);
0263: }
0264:
0265: public void removeChild(@NotNull
0266: final ReportElement reportElement) {
0267: //noinspection ConstantConditions
0268: if (reportElement == null) {
0269: throw new IllegalArgumentException(
0270: "reportElement must not be null");
0271: }
0272:
0273: final int index = children.indexOf(reportElement);
0274: boolean remomved = children.remove(reportElement);
0275: if (remomved) {
0276: reportElement.setParent(null);
0277:
0278: Undo undo = getUndo();
0279: if (undo != null && !undo.isInProgress()) {
0280: undo.startTransaction(UndoConstants.REMOVE_CHILD);
0281: undo.add(new UndoEntry() {
0282: public void undo() {
0283: insertChild(reportElement, index);
0284: }
0285:
0286: public void redo() {
0287: removeChild(reportElement);
0288: }
0289: });
0290: undo.endTransaction();
0291: }
0292:
0293: firePropertyChange(PropertyKeys.CHILD_REMOVED, null,
0294: reportElement);
0295: }
0296: }
0297:
0298: public void insertChild(@NotNull
0299: final ReportElement child, final int index) {
0300: //noinspection ConstantConditions
0301: if (child == null) {
0302: throw new IllegalArgumentException("child must not be null");
0303: }
0304:
0305: Undo undo = getUndo();
0306: child.setUndo(undo);
0307:
0308: final ReportElement oldParent = child.getParent();
0309: child.setParent(this );
0310: children.add(index, child);
0311:
0312: if (undo != null && !undo.isInProgress()) {
0313: undo.startTransaction(UndoConstants.ADD_CHILD);
0314: undo.add(new UndoEntry() {
0315: public void undo() {
0316: removeChild(child);
0317: child.setParent(oldParent);
0318: }
0319:
0320: public void redo() {
0321: insertChild(child, index);
0322: }
0323: });
0324: undo.endTransaction();
0325: }
0326:
0327: firePropertyChange(PropertyKeys.CHILD_ADDED, null, child);
0328: }
0329:
0330: public void moveChildDown(@NotNull
0331: final ReportElement child) {
0332: int index = children.indexOf(child);
0333: if (index > 0) {
0334: Undo undo = getUndo();
0335: if (undo != null && !undo.isInProgress()) {
0336: undo.startTransaction(UndoConstants.MOVE_CHILD_DOWN);
0337: undo.add(new UndoEntry() {
0338: public void undo() {
0339: moveChildUp(child);
0340: }
0341:
0342: public void redo() {
0343: moveChildDown(child);
0344: }
0345: });
0346: undo.endTransaction();
0347: }
0348:
0349: children.remove(child);
0350: children.add(index - 1, child);
0351: firePropertyChange(PropertyKeys.CHILD_MOVED, null, child);
0352: }
0353: }
0354:
0355: public void moveChildUp(@NotNull
0356: final ReportElement child) {
0357: int index = children.indexOf(child);
0358: if (index != -1 && index < children.size() - 1) {
0359: Undo undo = getUndo();
0360: if (undo != null && !undo.isInProgress()) {
0361: undo.startTransaction(UndoConstants.MOVE_CHILD_UP);
0362: undo.add(new UndoEntry() {
0363: public void undo() {
0364: moveChildDown(child);
0365: }
0366:
0367: public void redo() {
0368: moveChildUp(child);
0369: }
0370: });
0371: undo.endTransaction();
0372: }
0373:
0374: children.remove(child);
0375: children.add(index + 1, child);
0376: firePropertyChange(PropertyKeys.CHILD_MOVED, null, child);
0377: }
0378: }
0379:
0380: @NotNull
0381: public StyleExpressions getStyleExpressions() {
0382: return styleExpressions;
0383: }
0384:
0385: public void setStyleExpressions(@NotNull
0386: final StyleExpressions styleExpressions) {
0387: //noinspection ConstantConditions
0388: if (styleExpressions == null) {
0389: throw new IllegalArgumentException(
0390: "styleExpressions must not be null");
0391: }
0392:
0393: final StyleExpressions oldStyleExpressions = this .styleExpressions;
0394: this .styleExpressions = styleExpressions;
0395:
0396: Undo undo = getUndo();
0397: if (undo != null && !undo.isInProgress()) {
0398: undo.startTransaction(PropertyKeys.STYLE_EXPRESSIONS);
0399: undo.add(new UndoEntry() {
0400: public void undo() {
0401: setStyleExpressions(oldStyleExpressions);
0402: }
0403:
0404: public void redo() {
0405: setStyleExpressions(styleExpressions);
0406: }
0407: });
0408: undo.endTransaction();
0409: }
0410:
0411: firePropertyChange(PropertyKeys.STYLE_EXPRESSIONS,
0412: oldStyleExpressions, styleExpressions);
0413: this .styleExpressions = styleExpressions;
0414: }
0415:
0416: @NotNull
0417: public Rectangle2D.Double getOrigRectangle() {
0418: return origRectangle;
0419: }
0420:
0421: public void setOrigRectangle(@NotNull
0422: final Rectangle2D.Double origRectangle) {
0423: //noinspection ConstantConditions
0424: if (origRectangle == null) {
0425: throw new IllegalArgumentException(
0426: "origRectangle must not be null");
0427: }
0428:
0429: final Rectangle2D.Double oldOrigRectangle = this .origRectangle;
0430: this .origRectangle = origRectangle;
0431:
0432: Undo undo = getUndo();
0433: if (undo != null && !undo.isInProgress()) {
0434: undo.startTransaction(PropertyKeys.ORIG_RECTANGLE);
0435: undo.add(new UndoEntry() {
0436: public void undo() {
0437: setOrigRectangle(oldOrigRectangle);
0438: }
0439:
0440: public void redo() {
0441: setOrigRectangle(origRectangle);
0442: }
0443: });
0444: undo.endTransaction();
0445: }
0446:
0447: firePropertyChange(PropertyKeys.ORIG_RECTANGLE,
0448: oldOrigRectangle, origRectangle);
0449: }
0450:
0451: @NotNull
0452: public Rectangle2D.Double getRectangle() {
0453: return rectangle;
0454: }
0455:
0456: @NotNull
0457: public Rectangle2D.Double getContentRectangle() {
0458: Rectangle2D.Double rect = getRectangle();
0459:
0460: double x;
0461: double y;
0462: double w;
0463: double h;
0464:
0465: if (getElementBorder().isSameBorderForAllSides()) {
0466: x = rect.x + getPadding().getLeft()
0467: + getElementBorder().getTopSide().getPaintWidth();
0468: y = rect.y + getPadding().getTop()
0469: + getElementBorder().getTopSide().getPaintWidth();
0470: w = Math.max(0, rect.width - getPadding().getLeft()
0471: - getPadding().getRight()
0472: - getElementBorder().getTopSide().getPaintWidth()
0473: - getElementBorder().getTopSide().getPaintWidth());
0474: h = Math.max(0, rect.height - getPadding().getTop()
0475: - getPadding().getBottom()
0476: - getElementBorder().getTopSide().getPaintWidth()
0477: - getElementBorder().getTopSide().getPaintWidth());
0478: } else {
0479: x = rect.x + getPadding().getLeft()
0480: + getElementBorder().getLeftSide().getPaintWidth();
0481: y = rect.y + getPadding().getTop()
0482: + getElementBorder().getTopSide().getPaintWidth();
0483: w = Math
0484: .max(0, rect.width
0485: - getPadding().getLeft()
0486: - getPadding().getRight()
0487: - getElementBorder().getLeftSide()
0488: .getPaintWidth()
0489: - getElementBorder().getRightSide()
0490: .getPaintWidth());
0491: h = Math.max(0, rect.height
0492: - getPadding().getTop()
0493: - getPadding().getBottom()
0494: - getElementBorder().getTopSide().getPaintWidth()
0495: - getElementBorder().getBottomSide()
0496: .getPaintWidth());
0497: }
0498:
0499: return new Rectangle2D.Double(x, y, w, h);
0500: }
0501:
0502: @NotNull
0503: public Shape getBorderShape() {
0504: Rectangle2D.Double b = getBorderRectangle();
0505:
0506: double x = b.x;
0507: double y = b.y;
0508: double w = b.width;
0509: double h = b.height;
0510:
0511: double topLeftWidth = getElementBorder().getTopLeftEdge()
0512: .getRadii().getWidth();
0513: double topLeftHeight = getElementBorder().getTopLeftEdge()
0514: .getRadii().getHeight();
0515:
0516: double topRightWidth = getElementBorder()
0517: .isSameBorderForAllSides() ? getElementBorder()
0518: .getTopLeftEdge().getRadii().getWidth()
0519: : getElementBorder().getTopRightEdge().getRadii()
0520: .getWidth();
0521: double topRightHeight = getElementBorder()
0522: .isSameBorderForAllSides() ? getElementBorder()
0523: .getTopLeftEdge().getRadii().getHeight()
0524: : getElementBorder().getTopRightEdge().getRadii()
0525: .getHeight();
0526:
0527: double bottomRightWidth = getElementBorder()
0528: .isSameBorderForAllSides() ? getElementBorder()
0529: .getTopLeftEdge().getRadii().getWidth()
0530: : getElementBorder().getBottomRightEdge().getRadii()
0531: .getWidth();
0532: double bottomRightHeight = getElementBorder()
0533: .isSameBorderForAllSides() ? getElementBorder()
0534: .getTopLeftEdge().getRadii().getHeight()
0535: : getElementBorder().getBottomRightEdge().getRadii()
0536: .getHeight();
0537:
0538: double bottomLeftWidth = getElementBorder()
0539: .isSameBorderForAllSides() ? getElementBorder()
0540: .getTopLeftEdge().getRadii().getWidth()
0541: : getElementBorder().getBottomLeftEdge().getRadii()
0542: .getWidth();
0543: double bottomLeftHeight = getElementBorder()
0544: .isSameBorderForAllSides() ? getElementBorder()
0545: .getTopLeftEdge().getRadii().getHeight()
0546: : getElementBorder().getBottomLeftEdge().getRadii()
0547: .getHeight();
0548:
0549: if (MathUtils.approxZero(topLeftWidth)
0550: && MathUtils.approxZero(topLeftHeight)
0551: && MathUtils.approxZero(topRightWidth)
0552: && MathUtils.approxZero(topRightHeight)
0553: && MathUtils.approxZero(bottomRightWidth)
0554: && MathUtils.approxZero(bottomRightHeight)
0555: && MathUtils.approxZero(bottomLeftWidth)
0556: && MathUtils.approxZero(bottomLeftHeight)) {
0557: return b;
0558: }
0559:
0560: GeneralPath generalPath = new GeneralPath();
0561: generalPath.append(new Arc2D.Double(x, y, 2 * topLeftWidth,
0562: 2 * topLeftHeight, -225, -45, Arc2D.OPEN), true);
0563: generalPath.lineTo((float) (x + w - topRightWidth), (float) y);//2
0564: generalPath.append(new Arc2D.Double(x + w - 2 * topRightWidth,
0565: y, 2 * topRightWidth, 2 * topRightHeight, 90, -45,
0566: Arc2D.OPEN), true);
0567:
0568: generalPath.append(new Arc2D.Double(x + w - 2 * topRightWidth,
0569: y, 2 * topRightWidth, 2 * topRightHeight, 45, -45,
0570: Arc2D.OPEN), true);
0571: generalPath.lineTo((float) (x + w),
0572: (float) (y + h - bottomRightHeight));//4
0573: generalPath.append(new Arc2D.Double(x + w - 2
0574: * bottomRightWidth, y + h - 2 * bottomRightHeight,
0575: 2 * bottomRightWidth, 2 * bottomRightHeight, 0, -45,
0576: Arc2D.OPEN), true);
0577:
0578: generalPath.append(new Arc2D.Double(x + w - 2
0579: * bottomRightWidth, y + h - 2 * bottomRightHeight,
0580: 2 * bottomRightWidth, 2 * bottomRightHeight, -45, -45,
0581: Arc2D.OPEN), true);
0582: generalPath.lineTo((float) (x + bottomLeftWidth),
0583: (float) (y + h));//6
0584: generalPath.append(new Arc2D.Double(x, y + h - 2
0585: * bottomLeftHeight, 2 * bottomLeftWidth,
0586: 2 * bottomLeftHeight, -90, -45, Arc2D.OPEN), true);
0587:
0588: generalPath.append(new Arc2D.Double(x, y + h - 2
0589: * bottomLeftHeight, 2 * bottomLeftWidth,
0590: 2 * bottomLeftHeight, -135, -45, Arc2D.OPEN), true);
0591: generalPath.lineTo((float) x, (float) (y + topLeftHeight));//8
0592: generalPath.append(new Arc2D.Double(x, y, 2 * topLeftWidth,
0593: 2 * topLeftHeight, -180, -45, Arc2D.OPEN), true);
0594:
0595: generalPath.closePath();
0596:
0597: return generalPath;
0598: }
0599:
0600: @NotNull
0601: public Shape getBorderTopShape() {
0602: Rectangle2D.Double b = getBorderRectangle();
0603:
0604: double x = b.x;
0605: double y = b.y;
0606: double w = b.width;
0607: //double h = b.height;
0608:
0609: double topLeftWidth = getElementBorder().getTopLeftEdge()
0610: .getRadii().getWidth();
0611: double topLeftHeight = getElementBorder().getTopLeftEdge()
0612: .getRadii().getHeight();
0613:
0614: double topRightWidth = getElementBorder()
0615: .isSameBorderForAllSides() ? getElementBorder()
0616: .getTopLeftEdge().getRadii().getWidth()
0617: : getElementBorder().getTopRightEdge().getRadii()
0618: .getWidth();
0619: double topRightHeight = getElementBorder()
0620: .isSameBorderForAllSides() ? getElementBorder()
0621: .getTopLeftEdge().getRadii().getHeight()
0622: : getElementBorder().getTopRightEdge().getRadii()
0623: .getHeight();
0624:
0625: GeneralPath generalPath = new GeneralPath();
0626: generalPath.append(new Arc2D.Double(x, y, 2 * topLeftWidth,
0627: 2 * topLeftHeight, -225, -45, Arc2D.OPEN), true);
0628: generalPath.lineTo((float) (x + w - topRightWidth), (float) y);//2
0629: generalPath.append(new Arc2D.Double(x + w - 2 * topRightWidth,
0630: y, 2 * topRightWidth, 2 * topRightHeight, 90, -45,
0631: Arc2D.OPEN), true);
0632:
0633: return generalPath;
0634: }
0635:
0636: @NotNull
0637: public Shape getBorderBottomShape() {
0638: Rectangle2D.Double b = getBorderRectangle();
0639:
0640: double x = b.x;
0641: double y = b.y;
0642: double w = b.width;
0643: double h = b.height;
0644:
0645: double bottomRightWidth = getElementBorder()
0646: .isSameBorderForAllSides() ? getElementBorder()
0647: .getTopLeftEdge().getRadii().getWidth()
0648: : getElementBorder().getBottomRightEdge().getRadii()
0649: .getWidth();
0650: double bottomRightHeight = getElementBorder()
0651: .isSameBorderForAllSides() ? getElementBorder()
0652: .getTopLeftEdge().getRadii().getHeight()
0653: : getElementBorder().getBottomRightEdge().getRadii()
0654: .getHeight();
0655:
0656: double bottomLeftWidth = getElementBorder()
0657: .isSameBorderForAllSides() ? getElementBorder()
0658: .getTopLeftEdge().getRadii().getWidth()
0659: : getElementBorder().getBottomLeftEdge().getRadii()
0660: .getWidth();
0661: double bottomLeftHeight = getElementBorder()
0662: .isSameBorderForAllSides() ? getElementBorder()
0663: .getTopLeftEdge().getRadii().getHeight()
0664: : getElementBorder().getBottomLeftEdge().getRadii()
0665: .getHeight();
0666:
0667: GeneralPath generalPath = new GeneralPath();
0668: generalPath.append(new Arc2D.Double(x + w - 2
0669: * bottomRightWidth, y + h - 2 * bottomRightHeight,
0670: 2 * bottomRightWidth, 2 * bottomRightHeight, -45, -45,
0671: Arc2D.OPEN), true);
0672: generalPath.lineTo((float) (x + bottomLeftWidth),
0673: (float) (y + h));//6
0674: generalPath.append(new Arc2D.Double(x, y + h - 2
0675: * bottomLeftHeight, 2 * bottomLeftWidth,
0676: 2 * bottomLeftHeight, -90, -45, Arc2D.OPEN), true);
0677:
0678: return generalPath;
0679: }
0680:
0681: @NotNull
0682: public Shape getBorderLeftShape() {
0683: Rectangle2D.Double b = getBorderRectangle();
0684:
0685: double x = b.x;
0686: double y = b.y;
0687: //double w = b.width;
0688: double h = b.height;
0689:
0690: double topLeftWidth = getElementBorder().getTopLeftEdge()
0691: .getRadii().getWidth();
0692: double topLeftHeight = getElementBorder().getTopLeftEdge()
0693: .getRadii().getHeight();
0694:
0695: double bottomLeftWidth = getElementBorder()
0696: .isSameBorderForAllSides() ? getElementBorder()
0697: .getTopLeftEdge().getRadii().getWidth()
0698: : getElementBorder().getBottomLeftEdge().getRadii()
0699: .getWidth();
0700: double bottomLeftHeight = getElementBorder()
0701: .isSameBorderForAllSides() ? getElementBorder()
0702: .getTopLeftEdge().getRadii().getHeight()
0703: : getElementBorder().getBottomLeftEdge().getRadii()
0704: .getHeight();
0705:
0706: GeneralPath generalPath = new GeneralPath();
0707: generalPath.append(new Arc2D.Double(x, y + h - 2
0708: * bottomLeftHeight, 2 * bottomLeftWidth,
0709: 2 * bottomLeftHeight, -135, -45, Arc2D.OPEN), true);
0710: generalPath.lineTo((float) x, (float) (y + topLeftHeight));//8
0711: generalPath.append(new Arc2D.Double(x, y, 2 * topLeftWidth,
0712: 2 * topLeftHeight, -180, -45, Arc2D.OPEN), true);
0713:
0714: return generalPath;
0715: }
0716:
0717: @NotNull
0718: public Shape getBorderRightShape() {
0719: Rectangle2D.Double b = getBorderRectangle();
0720:
0721: double x = b.x;
0722: double y = b.y;
0723: double w = b.width;
0724: double h = b.height;
0725:
0726: double topRightWidth = getElementBorder()
0727: .isSameBorderForAllSides() ? getElementBorder()
0728: .getTopLeftEdge().getRadii().getWidth()
0729: : getElementBorder().getTopRightEdge().getRadii()
0730: .getWidth();
0731: double topRightHeight = getElementBorder()
0732: .isSameBorderForAllSides() ? getElementBorder()
0733: .getTopLeftEdge().getRadii().getHeight()
0734: : getElementBorder().getTopRightEdge().getRadii()
0735: .getHeight();
0736:
0737: double bottomRightWidth = getElementBorder()
0738: .isSameBorderForAllSides() ? getElementBorder()
0739: .getTopLeftEdge().getRadii().getWidth()
0740: : getElementBorder().getBottomRightEdge().getRadii()
0741: .getWidth();
0742: double bottomRightHeight = getElementBorder()
0743: .isSameBorderForAllSides() ? getElementBorder()
0744: .getTopLeftEdge().getRadii().getHeight()
0745: : getElementBorder().getBottomRightEdge().getRadii()
0746: .getHeight();
0747:
0748: GeneralPath generalPath = new GeneralPath();
0749: generalPath.append(new Arc2D.Double(x + w - 2 * topRightWidth,
0750: y, 2 * topRightWidth, 2 * topRightHeight, 45, -45,
0751: Arc2D.OPEN), true);
0752: generalPath.lineTo((float) (x + w),
0753: (float) (y + h - bottomRightHeight));//4
0754: generalPath.append(new Arc2D.Double(x + w - 2
0755: * bottomRightWidth, y + h - 2 * bottomRightHeight,
0756: 2 * bottomRightWidth, 2 * bottomRightHeight, 0, -45,
0757: Arc2D.OPEN), true);
0758:
0759: return generalPath;
0760: }
0761:
0762: @NotNull
0763: private Rectangle2D.Double getBorderRectangle() {
0764: Rectangle2D.Double rect = getRectangle();
0765:
0766: double x;
0767: double y;
0768: double w;
0769: double h;
0770:
0771: if (getElementBorder().isSameBorderForAllSides()) {
0772: x = rect.x
0773: + getElementBorder().getTopSide().getPaintWidth()
0774: / 2;
0775: y = rect.y
0776: + getElementBorder().getTopSide().getPaintWidth()
0777: / 2;
0778: w = Math.max(0, rect.width
0779: - getElementBorder().getTopSide().getPaintWidth()
0780: / 2
0781: - getElementBorder().getTopSide().getPaintWidth()
0782: / 2);
0783: h = Math.max(0, rect.height
0784: - getElementBorder().getTopSide().getPaintWidth()
0785: / 2
0786: - getElementBorder().getTopSide().getPaintWidth()
0787: / 2);
0788: } else {
0789: x = rect.x
0790: + +getElementBorder().getLeftSide().getPaintWidth()
0791: / 2;
0792: y = rect.y
0793: + getElementBorder().getTopSide().getPaintWidth()
0794: / 2;
0795: w = Math.max(0, rect.width
0796: - getElementBorder().getLeftSide().getPaintWidth()
0797: / 2
0798: - getElementBorder().getRightSide().getPaintWidth()
0799: / 2);
0800: h = Math.max(0, rect.height
0801: - getElementBorder().getTopSide().getPaintWidth()
0802: / 2
0803: - getElementBorder().getBottomSide()
0804: .getPaintWidth() / 2);
0805: }
0806: return new Rectangle2D.Double(x, y, w, h);
0807: }
0808:
0809: public void setRectangle(@NotNull
0810: final Rectangle2D.Double rectangle) {
0811: //noinspection ConstantConditions
0812: if (rectangle == null) {
0813: throw new IllegalArgumentException(
0814: "rectangle must not be null");
0815: }
0816:
0817: final Rectangle2D.Double oldRectangle = this .rectangle;
0818: this .rectangle = rectangle;
0819:
0820: Undo undo = getUndo();
0821: if (undo != null && !undo.isInProgress()) {
0822: undo.startTransaction(PropertyKeys.RECTANGLE);
0823: undo.add(new UndoEntry() {
0824: public void undo() {
0825: setRectangle(oldRectangle);
0826: }
0827:
0828: public void redo() {
0829: setRectangle(rectangle);
0830: }
0831: });
0832: undo.endTransaction();
0833: }
0834:
0835: firePropertyChange(PropertyKeys.RECTANGLE, oldRectangle,
0836: rectangle);
0837: }
0838:
0839: @NotNull
0840: public Point2D.Double getPosition() {
0841: return position;
0842: }
0843:
0844: public void setPosition(@NotNull
0845: final Point2D.Double position) {
0846: //noinspection ConstantConditions
0847: if (position == null) {
0848: throw new IllegalArgumentException(
0849: "position must not be null");
0850: }
0851:
0852: final Point2D.Double oldPosition = this .position;
0853: this .position = position;
0854:
0855: if (position.equals(oldPosition)) {
0856: return;
0857: }
0858:
0859: Undo undo = getUndo();
0860: if (undo != null && !undo.isInProgress()) {
0861: undo.startTransaction(PropertyKeys.POSITION);
0862: undo.add(new UndoEntry() {
0863: public void undo() {
0864: setPosition(oldPosition);
0865: }
0866:
0867: public void redo() {
0868: setPosition(position);
0869: }
0870: });
0871: undo.endTransaction();
0872: }
0873:
0874: firePropertyChange(PropertyKeys.POSITION, oldPosition, position);
0875: }
0876:
0877: @NotNull
0878: public DoubleDimension getMinimumSize() {
0879: return minimumSize;
0880: }
0881:
0882: public void setMinimumSize(@NotNull
0883: final DoubleDimension minimumSize) {
0884: final DoubleDimension oldMinimumSize = this .minimumSize;
0885: if (minimumSize.getWidth() < 0) {
0886: minimumSize.setSize(0, minimumSize.getHeight());
0887: }
0888: if (minimumSize.getHeight() < 0) {
0889: minimumSize.setSize(minimumSize.getWidth(), 0);
0890: }
0891:
0892: this .minimumSize = minimumSize;
0893:
0894: if (minimumSize.equals(oldMinimumSize)) {
0895: return;
0896: }
0897:
0898: Undo undo = getUndo();
0899: if (undo != null && !undo.isInProgress()) {
0900: undo.startTransaction(PropertyKeys.MINIMUM_SIZE);
0901: undo.add(new UndoEntry() {
0902: public void undo() {
0903: setMinimumSize(oldMinimumSize);
0904: }
0905:
0906: public void redo() {
0907: setMinimumSize(minimumSize);
0908: }
0909: });
0910: undo.endTransaction();
0911: }
0912:
0913: firePropertyChange(PropertyKeys.MINIMUM_SIZE, oldMinimumSize,
0914: minimumSize);
0915: }
0916:
0917: @NotNull
0918: public DoubleDimension getPreferredSize() {
0919: return preferredSize;
0920: }
0921:
0922: public void setPreferredSize(@NotNull
0923: final DoubleDimension preferredSize) {
0924: final DoubleDimension oldPreferredSize = this .preferredSize;
0925: this .preferredSize = preferredSize;
0926:
0927: Undo undo = getUndo();
0928: if (undo != null && !undo.isInProgress()) {
0929: undo.startTransaction(PropertyKeys.PREFERRED_SIZE);
0930: undo.add(new UndoEntry() {
0931: public void undo() {
0932: setPreferredSize(oldPreferredSize);
0933: }
0934:
0935: public void redo() {
0936: setPreferredSize(preferredSize);
0937: }
0938: });
0939: undo.endTransaction();
0940: }
0941:
0942: firePropertyChange(PropertyKeys.PREFERRED_SIZE,
0943: oldPreferredSize, preferredSize);
0944: }
0945:
0946: @NotNull
0947: public DoubleDimension getMaximumSize() {
0948: return maximumSize;
0949: }
0950:
0951: public void setMaximumSize(@NotNull
0952: final DoubleDimension maximumSize) {
0953: final DoubleDimension oldMaximumSize = this .maximumSize;
0954: this .maximumSize = maximumSize;
0955:
0956: Undo undo = getUndo();
0957: if (undo != null && !undo.isInProgress()) {
0958: undo.startTransaction(PropertyKeys.MAXIMUM_SIZE);
0959: undo.add(new UndoEntry() {
0960: public void undo() {
0961: setMaximumSize(oldMaximumSize);
0962: }
0963:
0964: public void redo() {
0965: setMaximumSize(maximumSize);
0966: }
0967: });
0968: undo.endTransaction();
0969: }
0970:
0971: firePropertyChange(PropertyKeys.MAXIMUM_SIZE, oldMaximumSize,
0972: maximumSize);
0973: }
0974:
0975: @Nullable
0976: public Color getBackground() {
0977: return background;
0978: }
0979:
0980: public void setBackground(@Nullable
0981: final Color background) {
0982: final Color oldBackground = this .background;
0983: this .background = background;
0984:
0985: Undo undo = getUndo();
0986: if (undo != null && !undo.isInProgress()) {
0987: undo.startTransaction(PropertyKeys.BACKGROUND);
0988: undo.add(new UndoEntry() {
0989: public void undo() {
0990: setBackground(oldBackground);
0991: }
0992:
0993: public void redo() {
0994: setBackground(background);
0995: }
0996: });
0997: undo.endTransaction();
0998: }
0999:
1000: firePropertyChange(PropertyKeys.BACKGROUND, oldBackground,
1001: background);
1002: }
1003:
1004: @NotNull
1005: public ElementPadding getPadding() {
1006: return padding;
1007: }
1008:
1009: public void setPadding(@NotNull
1010: final ElementPadding padding) {
1011: final ElementPadding oldPadding = this .padding;
1012: this .padding = padding;
1013:
1014: Undo undo = getUndo();
1015: if (undo != null && !undo.isInProgress()) {
1016: undo.startTransaction(PropertyKeys.PADDING);
1017: undo.add(new UndoEntry() {
1018: public void undo() {
1019: setPadding(oldPadding);
1020: }
1021:
1022: public void redo() {
1023: setPadding(padding);
1024: }
1025: });
1026: undo.endTransaction();
1027: }
1028:
1029: firePropertyChange(PropertyKeys.PADDING, oldPadding, padding);
1030: }
1031:
1032: @NotNull
1033: public ElementBorderDefinition getElementBorder() {
1034: return elementBorder;
1035: }
1036:
1037: public void setElementBorder(@NotNull
1038: final ElementBorderDefinition elementBorder) {
1039: final ElementBorderDefinition oldElementBorder = this .elementBorder;
1040: this .elementBorder = elementBorder;
1041:
1042: Undo undo = getUndo();
1043: if (undo != null && !undo.isInProgress()) {
1044: undo.startTransaction(PropertyKeys.ELEMENT_BORDER);
1045: undo.add(new UndoEntry() {
1046: public void undo() {
1047: setElementBorder(oldElementBorder);
1048: }
1049:
1050: public void redo() {
1051: setElementBorder(elementBorder);
1052: }
1053: });
1054: undo.endTransaction();
1055: }
1056:
1057: firePropertyChange(PropertyKeys.ELEMENT_BORDER,
1058: oldElementBorder, elementBorder);
1059: }
1060:
1061: public boolean isDynamicContent() {
1062: return dynamicContent;
1063: }
1064:
1065: public void setDynamicContent(final boolean dynamicContent) {
1066: final boolean oldDynamicContent = this .dynamicContent;
1067: this .dynamicContent = dynamicContent;
1068:
1069: Undo undo = getUndo();
1070: if (undo != null && !undo.isInProgress()) {
1071: undo.startTransaction(PropertyKeys.DYNAMIC_CONTENT);
1072: undo.add(new UndoEntry() {
1073: public void undo() {
1074: setDynamicContent(oldDynamicContent);
1075: }
1076:
1077: public void redo() {
1078: setDynamicContent(dynamicContent);
1079: }
1080: });
1081: undo.endTransaction();
1082: }
1083:
1084: firePropertyChange(PropertyKeys.DYNAMIC_CONTENT,
1085: oldDynamicContent, dynamicContent);
1086: }
1087:
1088: public double getElementRepaintBorder() {
1089: return elementRepaintBorder;
1090: }
1091:
1092: public void setElementRepaintBorder(double elementRepaintBorder) {
1093: this .elementRepaintBorder = elementRepaintBorder;
1094: }
1095:
1096: public void invalidate() {
1097: invalid = true;
1098: if (parent != null) {
1099: parent.invalidate();
1100: }
1101: }
1102:
1103: public void validate() {
1104: if (!invalid) {
1105: return;
1106: }
1107:
1108: for (ReportElement reportElement : children) {
1109: reportElement.validate();
1110: }
1111:
1112: //convert position to absolute coordinate
1113: origRectangle.setRect(position.getX(), position.getY(),
1114: minimumSize.getWidth(), minimumSize.getHeight());
1115: rectangle.setRect(position.getX(), position.getY(), minimumSize
1116: .getWidth(), minimumSize.getHeight());
1117:
1118: for (ReportElement reportElement : children) {
1119: origRectangle = (Rectangle2D.Double) origRectangle
1120: .createUnion(reportElement.getOrigRectangle());
1121: rectangle = (Rectangle2D.Double) rectangle
1122: .createUnion(reportElement.getOrigRectangle());
1123: }
1124:
1125: //adjust minimum size to contain all children
1126: //scream if there are elements >100%
1127:
1128: //convert relative positions to absolute ones
1129: //invalid = false;
1130: }
1131:
1132: @NotNull
1133: public String toString() {
1134: return getName();
1135: }
1136:
1137: public void addPropertyChangeListener(@NotNull
1138: PropertyChangeListener listener) {
1139: propertyChangeSupport.addPropertyChangeListener(listener);
1140: }
1141:
1142: public void removePropertyChangeListener(@NotNull
1143: PropertyChangeListener listener) {
1144: propertyChangeSupport.removePropertyChangeListener(listener);
1145: }
1146:
1147: @NotNull
1148: public PropertyChangeListener[] getPropertyChangeListeners() {
1149: return propertyChangeSupport.getPropertyChangeListeners();
1150: }
1151:
1152: public void addPropertyChangeListener(@NotNull
1153: String propertyName, @NotNull
1154: PropertyChangeListener listener) {
1155: propertyChangeSupport.addPropertyChangeListener(propertyName,
1156: listener);
1157: }
1158:
1159: public void removePropertyChangeListener(@NotNull
1160: String propertyName, @NotNull
1161: PropertyChangeListener listener) {
1162: propertyChangeSupport.removePropertyChangeListener(
1163: propertyName, listener);
1164: }
1165:
1166: public void firePropertyChange(@NotNull
1167: @NonNls
1168: String propertyName, @Nullable
1169: Object oldValue, @Nullable
1170: Object newValue) {
1171: propertyChangeSupport.firePropertyChange(propertyName,
1172: oldValue, newValue);
1173: }
1174:
1175: public void firePropertyChange(@NotNull
1176: @NonNls
1177: String propertyName, int oldValue, int newValue) {
1178: propertyChangeSupport.firePropertyChange(propertyName, Integer
1179: .valueOf(oldValue), Integer.valueOf(newValue));
1180: }
1181:
1182: public void firePropertyChange(@NotNull
1183: @NonNls
1184: String propertyName, boolean oldValue, boolean newValue) {
1185: propertyChangeSupport.firePropertyChange(propertyName, Boolean
1186: .valueOf(oldValue), Boolean.valueOf(newValue));
1187: }
1188:
1189: public void firePropertyChange(@NotNull
1190: @NonNls
1191: String propertyName, double oldValue, double newValue) {
1192: propertyChangeSupport.firePropertyChange(propertyName, Double
1193: .valueOf(oldValue), Double.valueOf(newValue));
1194: }
1195:
1196: public void fireIndexedPropertyChange(@NotNull
1197: String propertyName, int index, @Nullable
1198: Object oldValue, @Nullable
1199: Object newValue) {
1200: propertyChangeSupport.fireIndexedPropertyChange(propertyName,
1201: index, oldValue, newValue);
1202: }
1203:
1204: public void paint(@NotNull
1205: GraphicsContext graphicsContext, @NotNull
1206: Graphics2D g2d) {
1207: for (ReportElement reportElement : children) {
1208: reportElement.paint(graphicsContext, g2d);
1209: }
1210: }
1211:
1212: public void paintBackroundAndBorder(@NotNull
1213: Graphics2D g2d) {
1214: Color oldColor = g2d.getColor();
1215: Stroke oldStroke = g2d.getStroke();
1216:
1217: Color bgColor = getBackground();
1218: if (bgColor != null) {
1219: g2d.setColor(bgColor);
1220: g2d.fill(getBorderShape());
1221: }
1222:
1223: if (getElementBorder().isSameBorderForAllSides()) {
1224: if (getElementBorder().getTopSide().getType() != ElementBorderDefinition.BorderType.NONE) {
1225: g2d
1226: .setColor(getElementBorder().getTopSide()
1227: .getColor());
1228: g2d.setStroke(getElementBorder().getTopSide()
1229: .getStroke());
1230: g2d.draw(getBorderShape());
1231: }
1232: } else {
1233: if (getElementBorder().getTopSide().getType() != ElementBorderDefinition.BorderType.NONE) {
1234: g2d
1235: .setColor(getElementBorder().getTopSide()
1236: .getColor());
1237: g2d.setStroke(getElementBorder().getTopSide()
1238: .getStroke());
1239: g2d.draw(getBorderTopShape());
1240: }
1241:
1242: if (getElementBorder().getRightSide().getType() != ElementBorderDefinition.BorderType.NONE) {
1243: g2d.setColor(getElementBorder().getRightSide()
1244: .getColor());
1245: g2d.setStroke(getElementBorder().getRightSide()
1246: .getStroke());
1247: g2d.draw(getBorderRightShape());
1248: }
1249:
1250: if (getElementBorder().getBottomSide().getType() != ElementBorderDefinition.BorderType.NONE) {
1251: g2d.setColor(getElementBorder().getBottomSide()
1252: .getColor());
1253: g2d.setStroke(getElementBorder().getBottomSide()
1254: .getStroke());
1255: g2d.draw(getBorderBottomShape());
1256: }
1257:
1258: if (getElementBorder().getLeftSide().getType() != ElementBorderDefinition.BorderType.NONE) {
1259: g2d.setColor(getElementBorder().getLeftSide()
1260: .getColor());
1261: g2d.setStroke(getElementBorder().getLeftSide()
1262: .getStroke());
1263: g2d.draw(getBorderLeftShape());
1264: }
1265: }
1266:
1267: g2d.setColor(oldColor);
1268: g2d.setStroke(oldStroke);
1269: }
1270:
1271: @NotNull
1272: public ReportElement[] getPath() {
1273: ArrayList<ReportElement> path = new ArrayList<ReportElement>();
1274: path.add(this );
1275:
1276: ReportElement parent = this ;
1277: while ((parent = parent.getParent()) != null) {
1278: path.add(0, parent);
1279: }
1280:
1281: return path.toArray(new ReportElement[path.size()]);
1282: }
1283:
1284: public void disposeCachedData() {
1285: }
1286:
1287: public abstract void accept(@Nullable
1288: Object parent, @NotNull
1289: ReportVisitor reportVisitor) throws ReportCreationException;
1290:
1291: @NotNull
1292: public ReportElement clone() throws CloneNotSupportedException {
1293: ReportElement re = (ReportElement) super .clone();
1294: re.propertyChangeSupport = new PropertyChangeSupport(re);
1295: re.parent = null;
1296: re.children = new ArrayList<ReportElement>();
1297: for (int i = 0; i < children.size(); i++) {
1298: ReportElement reportElement = children.get(i);
1299: ReportElement child = reportElement.clone();
1300: re.children.add(child);
1301: child.setParent(re);
1302: }
1303: re.origRectangle = (Rectangle2D.Double) origRectangle.clone();
1304: re.rectangle = (Rectangle2D.Double) rectangle.clone();
1305: re.position = (Point2D.Double) position.clone();
1306: re.minimumSize = (DoubleDimension) minimumSize.clone();
1307: re.preferredSize = (DoubleDimension) preferredSize.clone();
1308: re.maximumSize = (DoubleDimension) maximumSize.clone();
1309: re.name = name;
1310: re.undo = undo;
1311:
1312: return re;
1313: }
1314:
1315: public final void externalizeObject(@NotNull
1316: XMLWriter xmlWriter, @NotNull
1317: XMLContext xmlContext) throws IOException {
1318: externalizeAttributes(xmlWriter, xmlContext);
1319: externalizeElements(xmlWriter, xmlContext);
1320: }
1321:
1322: protected void externalizeElements(@NotNull
1323: XMLWriter xmlWriter, @NotNull
1324: XMLContext xmlContext) throws IOException {
1325: xmlWriter.writeProperty(XMLConstants.NAME, name);
1326: if (!isDefault(position)) {
1327: xmlWriter.writeProperty(PropertyKeys.POSITION,
1328: ObjectConverterFactory.getInstance()
1329: .getPoint2DConverter().getString(position));
1330: }
1331:
1332: if (!isDefault(minimumSize)) {
1333: xmlWriter.writeProperty(PropertyKeys.MINIMUM_SIZE,
1334: ObjectConverterFactory.getInstance()
1335: .getDoubleDimensionConverter().getString(
1336: minimumSize));
1337: }
1338: if (!isDefault(preferredSize)) {
1339: xmlWriter.writeProperty(PropertyKeys.PREFERRED_SIZE,
1340: ObjectConverterFactory.getInstance()
1341: .getDoubleDimensionConverter().getString(
1342: preferredSize));
1343: }
1344: if (!isDefault(maximumSize)) {
1345: xmlWriter.writeProperty(PropertyKeys.MAXIMUM_SIZE,
1346: ObjectConverterFactory.getInstance()
1347: .getDoubleDimensionConverter().getString(
1348: maximumSize));
1349: }
1350: Color bg = background;
1351: if (bg != null) {
1352: xmlWriter.writeProperty(PropertyKeys.BACKGROUND,
1353: ObjectConverterFactory.getInstance()
1354: .getColorConverter().getString(bg));
1355: }
1356: if (dynamicContent) {
1357: xmlWriter.writeProperty(PropertyKeys.DYNAMIC_CONTENT,
1358: String.valueOf(dynamicContent));
1359: }
1360:
1361: if (!styleExpressions.getStyleExpressions().isEmpty()) {
1362: xmlWriter.startElement(PropertyKeys.STYLE_EXPRESSIONS);
1363: styleExpressions.externalizeObject(xmlWriter, xmlContext);
1364: xmlWriter.closeElement(PropertyKeys.STYLE_EXPRESSIONS);
1365: }
1366:
1367: if (!padding.isDefault()) {
1368: xmlWriter.startElement(PropertyKeys.PADDING);
1369: padding.externalizeObject(xmlWriter, xmlContext);
1370: xmlWriter.closeElement(PropertyKeys.PADDING);
1371: }
1372:
1373: if (!elementBorder.isDefault()) {
1374: xmlWriter.startElement(PropertyKeys.ELEMENT_BORDER);
1375: elementBorder.externalizeObject(xmlWriter, xmlContext);
1376: xmlWriter.closeElement(PropertyKeys.ELEMENT_BORDER);
1377: }
1378:
1379: for (ReportElement reportElement : children) {
1380: xmlWriter.startElement(PropertyKeys.CHILD);
1381: String name = reportElement.getClass().getName();
1382: if (name.startsWith(FunctionGenerator.PACKAGE_PREFIX)) {
1383: name = name.substring(FunctionGenerator.PACKAGE_PREFIX
1384: .length());
1385: }
1386: xmlWriter.writeAttribute(PropertyKeys.TYPE, name);
1387: if (reportElement instanceof BandToplevelReportElement) {
1388: BandToplevelReportElement bandToplevelReportElement = (BandToplevelReportElement) reportElement;
1389: xmlWriter.writeAttribute(
1390: PropertyKeys.BAND_TOPLEVEL_TYPE,
1391: bandToplevelReportElement.getBandToplevelType()
1392: .toString());
1393: }
1394: reportElement.externalizeObject(xmlWriter, xmlContext);
1395: xmlWriter.closeElement(PropertyKeys.CHILD);
1396: }
1397: }
1398:
1399: @SuppressWarnings({"EmptyMethod","UnusedDeclaration"})
1400: protected final void externalizeAttributes(@NotNull
1401: XMLWriter xmlWriter, @NotNull
1402: XMLContext xmlContext) {
1403: }
1404:
1405: private boolean isDefault(@NotNull
1406: Point2D.Double position) {
1407: return MathUtils.approxEquals(position.x, 0)
1408: && MathUtils.approxEquals(position.y, 0);
1409: }
1410:
1411: private boolean isDefault(@NotNull
1412: DoubleDimension doubleDimension) {
1413: return MathUtils.approxEquals(doubleDimension.getWidth(), 0)
1414: && MathUtils.approxEquals(doubleDimension.getHeight(),
1415: 0);
1416: }
1417:
1418: public void readObject(@NotNull
1419: XmlPullNode node, @NotNull
1420: XMLContext xmlContext) throws Exception {
1421: readAttributes(node);
1422: readElements(node, xmlContext);
1423: }
1424:
1425: private void readElements(@NotNull
1426: XmlPullNode node, @NotNull
1427: XMLContext xmlContext) throws Exception {
1428: ExpressionRegistry expressionRegistry = ExpressionRegistry
1429: .getInstance();
1430:
1431: while (!node.isFinished()) {
1432: Object childNodeList = node.readNextChild();
1433: if (childNodeList instanceof XmlPullNode) {
1434: XmlPullNode child = (XmlPullNode) childNodeList;
1435: readElement(expressionRegistry, child, xmlContext);
1436: }
1437: }
1438: }
1439:
1440: @SuppressWarnings({"EmptyMethod","UnusedDeclaration"})
1441: protected final void readAttributes(@NotNull
1442: XmlPullNode node) {
1443: }
1444:
1445: protected void readElement(@NotNull
1446: ExpressionRegistry expressions, @NotNull
1447: XmlPullNode node, @NotNull
1448: XMLContext xmlContext) throws Exception {
1449: if (PropertyKeys.CHILD.equals(node.getRawName())) {
1450: ReportElementInfo reportElementInfo = getReportElementInfo(
1451: expressions, node);
1452: if (reportElementInfo != null) {
1453: ReportElement reportElement = reportElementInfo
1454: .createReportElement();
1455: reportElement.readObject(node, xmlContext);
1456: addChild(reportElement);
1457: } else {
1458: String className = node
1459: .getAttributeValueFromRawName(PropertyKeys.TYPE);
1460: LinkedHashSet<DataSetPlugin> dataSetPlugins = DataSetPluginRegistry
1461: .getInstance().getDataSetPlugins();
1462: boolean read = false;
1463: for (DataSetPlugin dataSetPlugin : dataSetPlugins) {
1464: if (dataSetPlugin.canRead(className)) {
1465: ReportElement reportElement = dataSetPlugin
1466: .createEmptyInstance(className);
1467: reportElement.readObject(node, xmlContext);
1468: addChild(reportElement);
1469: read = true;
1470: break;//ensures not to read from the sampleDB plugin and a second time by the JDBCDataSetPlugin
1471: }
1472: }
1473: if (!read) {
1474: //noinspection ThrowableInstanceNeverThrown
1475: UncaughtExcpetionsModel.getInstance().addException(
1476: new Throwable(
1477: "Could not read complete file, Plugin missing? Element = "
1478: + className));//NON-NLS
1479: }
1480: }
1481: } else if (XMLConstants.PROPERTY.equals(node.getRawName())
1482: && PropertyKeys.NAME
1483: .equals(node
1484: .getAttributeValueFromRawName(XMLConstants.NAME))) {
1485: name = XMLUtils.readProperty(PropertyKeys.NAME, node);
1486: } else if (XMLConstants.PROPERTY.equals(node.getRawName())
1487: && PropertyKeys.POSITION
1488: .equals(node
1489: .getAttributeValueFromRawName(XMLConstants.NAME))) {
1490: position = ObjectConverterFactory.getInstance()
1491: .getPoint2DConverter().getObject(
1492: XMLUtils.readProperty(
1493: PropertyKeys.POSITION, node));
1494: //layout managers generate garbage if these properties are not correct
1495: rectangle = new Rectangle2D.Double(position.x, position.y,
1496: minimumSize.getWidth(), minimumSize.getHeight());
1497: origRectangle = new Rectangle2D.Double(position.x,
1498: position.y, minimumSize.getWidth(), minimumSize
1499: .getHeight());
1500: } else if (XMLConstants.PROPERTY.equals(node.getRawName())
1501: && PropertyKeys.MINIMUM_SIZE
1502: .equals(node
1503: .getAttributeValueFromRawName(XMLConstants.NAME))) {
1504: minimumSize = ObjectConverterFactory.getInstance()
1505: .getDoubleDimensionConverter().getObject(
1506: XMLUtils.readProperty(
1507: PropertyKeys.MINIMUM_SIZE, node));
1508: //layout managers generate garbage if these properties are not correct
1509: rectangle = new Rectangle2D.Double(position.x, position.y,
1510: minimumSize.getWidth(), minimumSize.getHeight());
1511: origRectangle = new Rectangle2D.Double(position.x,
1512: position.y, minimumSize.getWidth(), minimumSize
1513: .getHeight());
1514: } else if (XMLConstants.PROPERTY.equals(node.getRawName())
1515: && PropertyKeys.PREFERRED_SIZE
1516: .equals(node
1517: .getAttributeValueFromRawName(XMLConstants.NAME))) {
1518: preferredSize = ObjectConverterFactory.getInstance()
1519: .getDoubleDimensionConverter().getObject(
1520: XMLUtils.readProperty(
1521: PropertyKeys.PREFERRED_SIZE, node));
1522: } else if (XMLConstants.PROPERTY.equals(node.getRawName())
1523: && PropertyKeys.MAXIMUM_SIZE
1524: .equals(node
1525: .getAttributeValueFromRawName(XMLConstants.NAME))) {
1526: maximumSize = ObjectConverterFactory.getInstance()
1527: .getDoubleDimensionConverter().getObject(
1528: XMLUtils.readProperty(
1529: PropertyKeys.MAXIMUM_SIZE, node));
1530: } else if (XMLConstants.PROPERTY.equals(node.getRawName())
1531: && PropertyKeys.BACKGROUND
1532: .equals(node
1533: .getAttributeValueFromRawName(XMLConstants.NAME))) {
1534: background = ObjectConverterFactory.getInstance()
1535: .getColorConverter().getObject(
1536: XMLUtils.readProperty(
1537: PropertyKeys.BACKGROUND, node));
1538: } else if (XMLConstants.PROPERTY.equals(node.getRawName())
1539: && PropertyKeys.DYNAMIC_CONTENT
1540: .equals(node
1541: .getAttributeValueFromRawName(XMLConstants.NAME))) {
1542: dynamicContent = Boolean.parseBoolean(XMLUtils
1543: .readProperty(PropertyKeys.DYNAMIC_CONTENT, node));
1544: } else if (PropertyKeys.STYLE_EXPRESSIONS.equals(node
1545: .getRawName())) {
1546: styleExpressions = new StyleExpressions();
1547: styleExpressions.readObject(node, xmlContext);
1548: } else if (PropertyKeys.PADDING.equals(node.getRawName())) {
1549: padding = new ElementPadding();
1550: padding.readObject(node, xmlContext);
1551: } else if (PropertyKeys.ELEMENT_BORDER
1552: .equals(node.getRawName())) {
1553: elementBorder = new ElementBorderDefinition();
1554: elementBorder.readObject(node, xmlContext);
1555: }
1556: }
1557:
1558: @Nullable
1559: protected ReportElementInfo getReportElementInfo(@NotNull
1560: ExpressionRegistry expressions, @NotNull
1561: XmlPullNode node) {
1562: String className = node
1563: .getAttributeValueFromRawName(PropertyKeys.TYPE);
1564:
1565: try {
1566: Class<?> clazz;
1567: //noinspection UnusedCatchParameter
1568: try {
1569: clazz = Class.forName(className);
1570: } catch (ClassNotFoundException e) {
1571: clazz = Class.forName(FunctionGenerator.PACKAGE_PREFIX
1572: + className);
1573: }
1574:
1575: if (className.equals(BandToplevelReportElement.class
1576: .getName())
1577: || className
1578: .equals(BandToplevelGroupReportElement.class
1579: .getName())
1580: || className
1581: .equals(BandToplevelPageReportElement.class
1582: .getName())
1583: || className
1584: .equals(BandToplevelItemReportElement.class
1585: .getName())) {
1586: String bandTopLevelType = node
1587: .getAttributeValueFromRawName(PropertyKeys.BAND_TOPLEVEL_TYPE);
1588: BandToplevelType bandToplevelType = BandToplevelType
1589: .valueOf(bandTopLevelType);
1590: return ReportElementInfoFactory.getInstance()
1591: .getBandToplevelReportElementInfo(
1592: bandToplevelType);
1593: } else if (className.equals(LabelReportElement.class
1594: .getName())) {
1595: return ReportElementInfoFactory.getInstance()
1596: .getLabelReportElementInfo();
1597: } else if (className.equals(DateFieldReportElement.class
1598: .getName())) {
1599: return ReportElementInfoFactory.getInstance()
1600: .getDateFieldReportElementInfo();
1601: } else if (className.equals(TextFieldReportElement.class
1602: .getName())) {
1603: return ReportElementInfoFactory.getInstance()
1604: .getTextFieldReportElementInfo();
1605: } else if (className.equals(MessageFieldReportElement.class
1606: .getName())) {
1607: return ReportElementInfoFactory.getInstance()
1608: .getMessageFieldReportElementInfo();
1609: } else if (className.equals(NumberFieldReportElement.class
1610: .getName())) {
1611: return ReportElementInfoFactory.getInstance()
1612: .getNumberFieldReportElementInfo();
1613: } else if (className
1614: .equals(ResourceFieldReportElement.class.getName())) {
1615: return ReportElementInfoFactory.getInstance()
1616: .getResourceFieldReportElementInfo();
1617: } else if (className
1618: .equals(ResourceLabelReportElement.class.getName())) {
1619: return ReportElementInfoFactory.getInstance()
1620: .getResourceLabelReportElementInfo();
1621: } else if (className
1622: .equals(ResourceMessageReportElement.class
1623: .getName())) {
1624: return ReportElementInfoFactory.getInstance()
1625: .getResourceMessageReportElementInfo();
1626: } else if (className.equals(BandReportElement.class
1627: .getName())) {
1628: return ReportElementInfoFactory.getInstance()
1629: .getBandReportElementInfo();
1630: } else if (className.equals(ReportGroups.class.getName())) {
1631: return ReportElementInfoFactory.getInstance()
1632: .getReportGroupsElementInfo();
1633: } else if (className.equals(ReportGroup.class.getName())) {
1634: return ReportElementInfoFactory.getInstance()
1635: .getReportGroupElementInfo();
1636: } else if (className.equals(ReportFunctionsElement.class
1637: .getName())) {
1638: return ReportElementInfoFactory.getInstance()
1639: .getReportFunctionsElementInfo();
1640: } else if (className.equals(LineReportElement.class
1641: .getName())) {
1642: return ReportElementInfoFactory.getInstance()
1643: .getLineReportElementInfo();
1644: } else if (className.equals(StaticImageReportElement.class
1645: .getName())) {
1646: return ReportElementInfoFactory.getInstance()
1647: .getStaticImageReportElementInfo();
1648: } else if (className.equals(ImageFieldReportElement.class
1649: .getName())) {
1650: return ReportElementInfoFactory.getInstance()
1651: .getImageFieldReportElementInfo();
1652: } else if (className
1653: .equals(ImageURLFieldReportElement.class.getName())) {
1654: return ReportElementInfoFactory.getInstance()
1655: .getImageURLFieldReportElementInfo();
1656: } else if (className.equals(AnchorFieldReportElement.class
1657: .getName())) {
1658: return ReportElementInfoFactory.getInstance()
1659: .getAnchorFieldReportElementInfo();
1660: } else if (className.equals(RectangleReportElement.class
1661: .getName())) {
1662: return ReportElementInfoFactory.getInstance()
1663: .getRectangleReportElementInfo();
1664: } else if (className.equals(EllipseReportElement.class
1665: .getName())) {
1666: return ReportElementInfoFactory.getInstance()
1667: .getEllipseReportElementInfo();
1668: } else if (className.equals(DataSetsReportElement.class
1669: .getName())) {
1670: return ReportElementInfoFactory.getInstance()
1671: .getDataSetsReportElementInfo();
1672: } else if (className
1673: .equals(PropertiesDataSetReportElement.class
1674: .getName())) {
1675: return ReportElementInfoFactory.getInstance()
1676: .getPropertiesDataSetReportElementInfo();
1677: } else if (className
1678: .equals(DrawableFieldReportElement.class.getName())) {
1679: return ReportElementInfoFactory.getInstance()
1680: .getDrawableFieldReportElementInfo();
1681: } else if (className.equals(ChartReportElement.class
1682: .getName())) {
1683: return ReportElementInfoFactory.getInstance()
1684: .getChartReportElementInfo();
1685: } else if (className.equals(SubReportElement.class
1686: .getName())) {
1687: return ReportElementInfoFactory.getInstance()
1688: .getSubReportElementInfo();
1689: } else if (className.equals(SubReportDataElement.class
1690: .getName())) {
1691: return ReportElementInfoFactory.getInstance()
1692: .getSubReportDataElementInfo();
1693: } else if (expressions
1694: .getJFreeReportExpressionToWrapperClassesMap()
1695: .containsValue(clazz)) {
1696: return ReportElementInfoFactory.getInstance()
1697: .getReportFunctionElementInfo(clazz.getName());
1698: }
1699: } catch (ClassNotFoundException e) {
1700: //perhaps an old function -> try to map to new one
1701: int index = className.lastIndexOf('.');
1702: if (index != -1) {
1703: String simpleClassName = className.substring(index + 1);
1704: Class<?> wrapperClass = expressions
1705: .getWrapperClassForOldFunction(simpleClassName);
1706: if (wrapperClass != null) {
1707: return ReportElementInfoFactory.getInstance()
1708: .getReportFunctionElementInfo(
1709: wrapperClass.getName());
1710: } else {
1711: if (LOG.isLoggable(Level.FINE))
1712: LOG
1713: .log(
1714: Level.FINE,
1715: "ReportElement.getReportElementInfo searched for an old function with name = "
1716: + simpleClassName
1717: + " but did not find anything useful");
1718: }
1719: }
1720: }
1721:
1722: if (LOG.isLoggable(Level.FINE))
1723: LOG.log(Level.FINE,
1724: "ReportElement.getReportElementInfo did not find type = "
1725: + className);
1726: return null;
1727: }
1728:
1729: }
|