0001: /*
0002: @license.gpl.text@
0003: */
0004: package biz.hammurapi.web.diagrameditor;
0005:
0006: import java.awt.BorderLayout;
0007: import java.awt.Color;
0008: import java.awt.Component;
0009: import java.awt.Container;
0010: import java.awt.Font;
0011: import java.awt.GridLayout;
0012: import java.awt.KeyboardFocusManager;
0013: import java.awt.event.ActionEvent;
0014: import java.awt.geom.Point2D;
0015: import java.awt.geom.Rectangle2D;
0016: import java.awt.image.BufferedImage;
0017: import java.beans.DefaultPersistenceDelegate;
0018: import java.beans.Encoder;
0019: import java.beans.Expression;
0020: import java.beans.PersistenceDelegate;
0021: import java.beans.PropertyChangeEvent;
0022: import java.beans.PropertyChangeListener;
0023: import java.io.ByteArrayInputStream;
0024: import java.io.ByteArrayOutputStream;
0025: import java.io.DataInputStream;
0026: import java.io.DataOutputStream;
0027: import java.io.IOException;
0028: import java.io.ObjectInputStream;
0029: import java.io.ObjectOutputStream;
0030: import java.net.Authenticator;
0031: import java.net.MalformedURLException;
0032: import java.net.URL;
0033: import java.util.Date;
0034: import java.util.HashMap;
0035: import java.util.Map;
0036: import java.util.zip.GZIPInputStream;
0037: import java.util.zip.GZIPOutputStream;
0038:
0039: import javax.imageio.ImageIO;
0040: import javax.swing.BorderFactory;
0041: import javax.swing.ImageIcon;
0042: import javax.swing.JApplet;
0043: import javax.swing.JComponent;
0044: import javax.swing.JFrame;
0045: import javax.swing.JOptionPane;
0046: import javax.swing.JPanel;
0047: import javax.swing.JToolBar;
0048: import javax.swing.ToolTipManager;
0049: import javax.swing.border.Border;
0050: import javax.swing.tree.DefaultMutableTreeNode;
0051: import javax.swing.tree.MutableTreeNode;
0052: import javax.xml.parsers.ParserConfigurationException;
0053:
0054: import org.apache.commons.httpclient.HttpClient;
0055: import org.apache.commons.httpclient.HttpMethod;
0056: import org.apache.commons.httpclient.HttpStatus;
0057: import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
0058: import org.apache.commons.httpclient.methods.GetMethod;
0059: import org.apache.commons.httpclient.methods.PostMethod;
0060: import org.jgraph.JGraph;
0061: import org.jgraph.event.GraphSelectionEvent;
0062: import org.jgraph.event.GraphSelectionListener;
0063: import org.jgraph.graph.AttributeMap;
0064: import org.jgraph.graph.CellView;
0065: import org.jgraph.graph.ConnectionSet;
0066: import org.jgraph.graph.DefaultEdge;
0067: import org.jgraph.graph.DefaultGraphCell;
0068: import org.jgraph.graph.DefaultPort;
0069: import org.jgraph.graph.Edge;
0070: import org.jgraph.graph.GraphCell;
0071: import org.jgraph.graph.GraphConstants;
0072: import org.jgraph.graph.GraphLayoutCache;
0073: import org.w3c.dom.Element;
0074: import org.w3c.dom.Node;
0075: import org.xml.sax.SAXException;
0076:
0077: import biz.hammurapi.web.file.sql.DbFileImpl;
0078:
0079: import com.jgraph.JGraphEditor;
0080: import com.jgraph.editor.JGraphEditorAction;
0081: import com.jgraph.editor.JGraphEditorFactory;
0082: import com.jgraph.editor.JGraphEditorKit;
0083: import com.jgraph.editor.JGraphEditorModel;
0084: import com.jgraph.editor.JGraphEditorPlugin;
0085: import com.jgraph.editor.JGraphEditorResources;
0086: import com.jgraph.editor.JGraphEditorSettings;
0087: import com.jgraph.editor.JGraphEditorTool;
0088: import com.jgraph.editor.factory.JGraphEditorComboBox;
0089: import com.jgraph.editor.factory.JGraphEditorNavigator;
0090: import com.jgraph.editor.factory.JGraphEditorToolbox;
0091: import com.jgraph.pad.JGraphpadDiagram;
0092: import com.jgraph.pad.JGraphpadFile;
0093: import com.jgraph.pad.JGraphpadLibrary;
0094: import com.jgraph.pad.action.JGraphpadCellAction;
0095: import com.jgraph.pad.action.JGraphpadEditAction;
0096: import com.jgraph.pad.action.JGraphpadFileAction;
0097: import com.jgraph.pad.action.JGraphpadFormatAction;
0098: import com.jgraph.pad.action.JGraphpadViewAction;
0099: import com.jgraph.pad.dialog.JGraphpadAuthenticator;
0100: import com.jgraph.pad.factory.JGraphpadComboBox;
0101: import com.jgraph.pad.factory.JGraphpadConsole;
0102: import com.jgraph.pad.factory.JGraphpadLibraryPane;
0103: import com.jgraph.pad.factory.JGraphpadOpenRecentMenu;
0104: import com.jgraph.pad.factory.JGraphpadStatusBar;
0105: import com.jgraph.pad.factory.JGraphpadWindowMenu;
0106: import com.jgraph.pad.graph.JGraphpadBusinessObject;
0107: import com.jgraph.pad.graph.JGraphpadEdgeView;
0108: import com.jgraph.pad.graph.JGraphpadGraph;
0109: import com.jgraph.pad.graph.JGraphpadGraphConstants;
0110: import com.jgraph.pad.graph.JGraphpadGraphLayoutCache;
0111: import com.jgraph.pad.graph.JGraphpadGraphModel;
0112: import com.jgraph.pad.graph.JGraphpadHeavyweightRenderer;
0113: import com.jgraph.pad.graph.JGraphpadMarqueeHandler;
0114: import com.jgraph.pad.graph.JGraphpadPortView;
0115: import com.jgraph.pad.graph.JGraphpadRichTextValue;
0116: import com.jgraph.pad.graph.JGraphpadTransferHandler;
0117: import com.jgraph.pad.graph.JGraphpadVertexRenderer;
0118: import com.jgraph.pad.graph.JGraphpadVertexView;
0119: import com.jgraph.pad.tool.JGraphpadEdgeTool;
0120: import com.jgraph.pad.tool.JGraphpadVertexTool;
0121: import com.jgraph.pad.util.JGraphpadFocusManager;
0122: import com.jgraph.pad.util.JGraphpadImageIcon;
0123: import com.jgraph.pad.util.JGraphpadParallelEdgeRouter;
0124: import com.jgraph.pad.util.JGraphpadParallelSplineRouter;
0125: import com.jgraph.pad.util.JGraphpadShadowBorder;
0126:
0127: /**
0128: * Diagram editor applet.
0129: */
0130: public class DiagramEditorApplet extends JApplet {
0131:
0132: public static final String IS_NEW = "isNew";
0133:
0134: public static final String CREATE_ID = "create-id";
0135:
0136: /**
0137: * Global static product identifier.
0138: */
0139: public static final String VERSION_NUMBER = "0.1";
0140:
0141: /**
0142: * Holds the application title for dialogs.
0143: */
0144: public static final String APPTITLE = "Argun diagram editor";
0145:
0146: /**
0147: * Global static product identifier.
0148: */
0149: public static final String VERSION = APPTITLE + " (v"
0150: + VERSION_NUMBER + ")";
0151:
0152: /**
0153: * Defines the look and feel argument name.
0154: */
0155: public static final String ARG_SYSTEMLOOKANDFEEL = "S";
0156:
0157: /**
0158: * Defines the look and feel argument name.
0159: */
0160: public static final String ARG_JGOODIESLOOKANDFEEL = "J";
0161:
0162: /**
0163: * Defines the look and feel argument name.
0164: */
0165: public static final String ARG_VERSION = "V";
0166:
0167: /**
0168: * Defines the path to the UI config file.
0169: */
0170: public static final String PATH_UICONFIG = "/biz/hammurapi/web/diagrameditor/ui.xml";
0171:
0172: /**
0173: * Defines the path to the UI config file.
0174: */
0175: // public static String PATH_DEFAULTLIBRARY = "/com/jgraph/pad/resources/default.xml";
0176: /**
0177: * Defines the path the the user settings file. This should also work with
0178: * URLs (untested).
0179: */
0180: public static final String PATH_DEFAULTSETTINGS = "/com/jgraph/pad/resources/default.ini";
0181:
0182: /**
0183: * Defines the name for the ui XML document in the editor settings.
0184: */
0185: public static final String NAME_UICONFIG = "ui";
0186:
0187: /**
0188: * Defines the name for the user properties in the editor settings.
0189: */
0190: // public static String NAME_USERSETTINGS = "user";
0191: /**
0192: * Defines the key used to identify the main window settings.
0193: */
0194: // public static String KEY_MAINWINDOW = "mainWindow";
0195: /**
0196: * Defines the key used to identify the recent files settings.
0197: */
0198: // public static String KEY_RECENTFILES = "recentFiles";
0199: /**
0200: * Defines the key used to identify the group prototype settings.
0201: */
0202: public static final String KEY_GROUPPROTOTYPE = "groupPrototype";
0203:
0204: /**
0205: * Defines the key used to identify the vertex prototype settings.
0206: */
0207: public static final String KEY_VERTEXPROTOTYPE = "vertexPrototype";
0208:
0209: /**
0210: * Defines the key used to identify the edge prototype settings.
0211: */
0212: public static final String KEY_EDGEPROTOTYPE = "edgePrototype";
0213:
0214: /**
0215: * Defines the name for the selectTool.
0216: */
0217: public static final String NAME_SELECTTOOL = "selectTool";
0218:
0219: /**
0220: * Defines the name for the textTool.
0221: */
0222: public static final String NAME_TEXTTOOL = "textTool";
0223:
0224: /**
0225: * Defines the name for the vertexTool.
0226: */
0227: public static final String NAME_VERTEXTOOL = JGraphpadVertexTool.NAME_VERTEXTOOL;
0228:
0229: /**
0230: * Defines the name for the roundedTool.
0231: */
0232: public static final String NAME_ROUNDEDTOOL = "roundedTool";
0233:
0234: /**
0235: * Defines the name for the circleTool.
0236: */
0237: public static final String NAME_CIRCLETOOL = "circleTool";
0238:
0239: /**
0240: * Defines the name for the diamondTool.
0241: */
0242: public static final String NAME_DIAMONDTOOL = "diamondTool";
0243:
0244: /**
0245: * Defines the name for the triangleTool.
0246: */
0247: public static final String NAME_TRIANGLETOOL = "triangleTool";
0248:
0249: /**
0250: * Defines the name for the diamondTool.
0251: */
0252: public static final String NAME_CYLINDERTOOL = "cylinderTool";
0253:
0254: /**
0255: * Defines the name for the imageTool.
0256: */
0257: public static final String NAME_IMAGETOOL = "imageTool";
0258:
0259: /**
0260: * Defines the name for the imageTool.
0261: */
0262: public static final String NAME_HEAVYTOOL = "heavyTool";
0263:
0264: /**
0265: * Defines the name for the edgeTool.
0266: */
0267: public static final String NAME_EDGETOOL = JGraphpadEdgeTool.NAME_EDGETOOL;
0268:
0269: /**
0270: * Defines the name for the orthogonalEdgeTool.
0271: */
0272: public static final String NAME_ORTHOGONALEDGETOOL = "orthogonalEdgeTool";
0273:
0274: /**
0275: * Defines the name of the createShapeCombo factory method.
0276: */
0277: public static final String METHOD_CREATESHAPECOMBO = "createShapeCombo";
0278:
0279: /**
0280: * Defines the name of the createGradientCombo factory method.
0281: */
0282: public static final String METHOD_CREATEGRADIENTCOMBO = "createGradientCombo";
0283:
0284: /**
0285: * Defines the name of the createGradientCombo factory method.
0286: */
0287: public static final String METHOD_CREATELINECOLORCOMBO = "createLineColorCombo";
0288:
0289: /**
0290: * Adds resources bundles and prepares classes for xml encoding.
0291: *
0292: * @see JGraphEditorResources#addBundles
0293: * @see JGraphEditorModel#makeCellViewFieldsTransient(Class)
0294: * @see JGraphEditorModel#makeTransient
0295: */
0296: static {
0297: info("Static initialization");
0298: // Adds resource bundles
0299: JGraphEditorResources.addBundles(new String[] {
0300: "com.jgraph.pad.resources.actions",
0301: "biz.hammurapi.web.diagrameditor.actions",
0302: "com.jgraph.pad.resources.menus",
0303: "com.jgraph.pad.resources.strings",
0304: "com.jgraph.pad.resources.tools" });
0305:
0306: // Prepares cell views for xml encoding (recommended for all cell views)
0307: JGraphEditorModel
0308: .makeCellViewFieldsTransient(JGraphpadVertexView.class);
0309: JGraphEditorModel
0310: .makeCellViewFieldsTransient(JGraphpadPortView.class);
0311: JGraphEditorModel
0312: .makeCellViewFieldsTransient(JGraphpadEdgeView.class);
0313:
0314: // Prepares class bean infos for xml encoding
0315: JGraphEditorModel.makeTransient(DefaultPort.class, "edges");
0316: JGraphEditorModel.makeTransient(DefaultEdge.class, "source");
0317: JGraphEditorModel.makeTransient(DefaultEdge.class, "target");
0318: JGraphEditorModel.makeTransient(GraphLayoutCache.class,
0319: "visibleSet");
0320: JGraphEditorModel
0321: .makeTransient(JGraphpadFile.class, "modified");
0322: JGraphEditorModel.makeTransient(JGraphpadFile.class,
0323: "userObject");
0324: JGraphEditorModel
0325: .makeTransient(JGraphpadFile.class, "filename");
0326: JGraphEditorModel.makeTransient(JGraphpadFile.class, "new");
0327: JGraphEditorModel.makeTransient(JGraphpadLibrary.class,
0328: "modified");
0329: JGraphEditorModel.makeTransient(JGraphpadLibrary.class,
0330: "userObject");
0331: JGraphEditorModel.makeTransient(JGraphpadLibrary.class,
0332: "filename");
0333: JGraphEditorModel.makeTransient(JGraphpadLibrary.class, "new");
0334: JGraphEditorModel.makeTransient(ConnectionSet.class, "edges");
0335:
0336: // Installs an additional border in the border combo box
0337: JGraphEditorComboBox.defaultBorders = new Border[] {
0338: BorderFactory.createRaisedBevelBorder(),
0339: BorderFactory.createLoweredBevelBorder(),
0340: BorderFactory.createEtchedBorder(),
0341: BorderFactory.createLineBorder(Color.black),
0342: JGraphpadShadowBorder.sharedInstance };
0343:
0344: // Installs basic authentication dialog
0345: try {
0346: Authenticator.setDefault(new JGraphpadAuthenticator());
0347: } catch (Exception e) {
0348: // ignore
0349: }
0350: }
0351:
0352: /**
0353: * The class names for the defaut plugins.
0354: */
0355: public String[] defaultPlugins = new String[] {
0356: // "com.jgraph.l2fplugin.JGraphpadL2FPlugin",
0357: // "com.jgraph.layoutplugin.JGraphpadLayoutPlugin",
0358: // "com.jgraph.svgplugin.JGraphpadSVGPlugin",
0359: // "com.jgraph.bshplugin.JGraphpadBshPlugin",
0360: // "com.jgraph.jgxplugin.JGraphpadJGXPlugin",
0361: // "com.jgraph.codecplugin.JGraphpadCodecPlugin",
0362: // "com.jgraph.epsplugin.JGraphpadEPSPlugin",
0363: // "com.jgraph.pdfplugin.JGraphpadPDFPlugin",
0364: // "com.jgraph.browserplugin.JGraphpadBrowserPlugin",
0365: // "com.jgraph.twikiplugin.JGraphpadTWikiPlugin"
0366: };
0367:
0368: /**
0369: * Defines the default port locations.
0370: */
0371: public Point2D[] defaultPortLocations = new Point2D[] { null };
0372:
0373: /**
0374: * Defines the default vertex bounds.
0375: */
0376: public Rectangle2D defaultBounds = new Rectangle2D.Double(0, 0, 20,
0377: 20);
0378:
0379: /**
0380: * Defines the default border color.
0381: */
0382: public Color defaultBorderColor = Color.BLACK;
0383:
0384: /**
0385: * Defines the default edge font.
0386: */
0387: public Font defaultEdgeFont = GraphConstants.DEFAULTFONT
0388: .deriveFont(10);
0389:
0390: /**
0391: * Defines the default end and begin decorations for edges.
0392: */
0393: public int defaultEndDecoration = GraphConstants.ARROW_TECHNICAL,
0394: defaultBeginDecoration = GraphConstants.ARROW_NONE;
0395:
0396: private String cookie;
0397:
0398: private String downloadUrl;
0399:
0400: private String uploadUrl;
0401:
0402: private JGraphEditor editor;
0403:
0404: private String exitUrl;
0405:
0406: private String ownerId;
0407:
0408: private String ownerType;
0409:
0410: private String parentFileId;
0411:
0412: /**
0413: * Constructs the editor settings. This implementation constructs a new
0414: * instance of JGraphEditorSettings using args as the initial object map and
0415: * passes it to the {@link #configureSettings(JGraphEditorSettings)}method.
0416: *
0417: * @param args
0418: * The arguments passed to the command line.
0419: * @return Returns a configured editor settings object.
0420: */
0421: protected JGraphEditorSettings createSettings(Map args) {
0422: try {
0423: JGraphEditorSettings settings = new JGraphEditorSettings(
0424: args);
0425: // Parses the ui configuration file. We have to use the resources'
0426: // getInputStream because we have no model yet. This means the
0427: // user configuration must not be compressed, which is acceptable.
0428: settings.add(NAME_UICONFIG, JGraphEditorSettings
0429: .parse(JGraphEditorResources
0430: .getInputStream(PATH_UICONFIG)));
0431:
0432: // Reads the user settings if they exist. Note: User settings do
0433: // never exist on the first run of this program. They are created
0434: // or updated when the program exits.
0435: // if (PATH_USERSETTINGS != null && new File(PATH_USERSETTINGS).canRead()) {
0436: // settings.add(NAME_USERSETTINGS, JGraphEditorResources.getInputStream(PATH_USERSETTINGS));
0437: // } else {
0438: // settings.add(NAME_USERSETTINGS, JGraphEditorResources.getInputStream(PATH_DEFAULTSETTINGS));
0439: // }
0440:
0441: // Adds prototypes for groups, vertices and edges to the
0442: // settings for later use by plugins and other interested
0443: // parties.
0444: settings.putObject(KEY_GROUPPROTOTYPE, createGroup());
0445: settings.putObject(KEY_VERTEXPROTOTYPE, createVertex());
0446: settings.putObject(KEY_EDGEPROTOTYPE, createEdge());
0447: return settings;
0448: } catch (IOException e) {
0449: throw new RuntimeException(e);
0450: } catch (ParserConfigurationException e) {
0451: throw new RuntimeException(e);
0452: } catch (SAXException e) {
0453: throw new RuntimeException(e);
0454: }
0455: }
0456:
0457: /**
0458: * Hook for subclassers to configure new document models. This
0459: * implementation adds persistence delegates for the following classes:
0460: * {@link JGraphpadDiagram},{@link JGraphpadGraphModel},
0461: * com.jgraph.graph.ConnectionSet, {@link JGraphpadGraphLayoutCache},
0462: * com.jgraph.graph.DefaultGraphCell, com.jgraph.graph.DefaultEdge,
0463: * com.jgraph.graph.DefaultPort,{@link JGraphpadBusinessObject},
0464: * {@link JGraphpadRichTextValue}and {@link JGraphpadShadowBorder}.<br>
0465: * <b>JGraphpadDiagram </b> <br>
0466: * Constructs a persistence delegate for the diagram class. This uses the
0467: * fact that all information is stored in the model, not the layout cache by
0468: * ignoring the layout cache and accessing the model stored in the layout
0469: * cache directly through the model bean property. Note: To allow this kind
0470: * of encoding the diagram class offers a special constructor that takes a
0471: * model and constructs a new graph layout cache for it. <br>
0472: * <b>JGraphpadGraphModel </b> <br>
0473: * To encode graph models we do not want the files to contain redundant
0474: * connectivity information in the ports.edges and edges.source and target
0475: * fields, so we add a method to the graph model that returns a connection
0476: * set which describes the connections without redundancy. (Note: In the
0477: * static initializer of this class we make sure that the edges, source and
0478: * target of the respective classes or not encoded.) <br>
0479: * <b>ConnectionSet </b> <br>
0480: * The complete information of a connection set is stored in the actual
0481: * connections, thus we only store the connections and use special
0482: * constructor to restore the state of the complete object when de- coding.
0483: * (Note: For connection sets this will update the edges field.) <br>
0484: * <b>JGraphpadGraphLayoutCache </b> <br>
0485: * The graph layout cache is encoded by encoding the various member fields,
0486: * using a special constructor to restore the state of the layout cache upon
0487: * decoding. Note that this is currently not used. <br>
0488: * <b>DefaultGraphCell, DefaultEdge, DefaultPort </b> <br>
0489: * Makes sure the cells are only encoded along with their user objects, the
0490: * attributes, connections and tree-structure is stored in other objects and
0491: * does not need to be encoded here. <br>
0492: * <b>JGraphpadBusinessObject, JGraphpadRichTextData </b> <br>
0493: * Allows to encode custom business objects used in JGraphpad. Since this
0494: * object implements the bean interface we do only require a default
0495: * persistence delegates with no special constructor calls to decode the
0496: * object. Same holds for the rich text data object, which is a special
0497: * value that can hold text formatting information. <br>
0498: * <b>JGraphShadowBorder </b> <br>
0499: * Since the shadow border is a singleton we must tell the decoder which
0500: * method to use in order to find the shared instance of the class.
0501: *
0502: * @param model
0503: * The document model to be configured.
0504: */
0505: protected void configureModel(JGraphEditorModel model) {
0506: model.addPersistenceDelegate(JGraphpadDiagram.class,
0507: new DefaultPersistenceDelegate(new String[] { "name",
0508: "graphLayoutCache", "properties" }));
0509: model.addPersistenceDelegate(JGraphpadLibrary.class,
0510: new DefaultPersistenceDelegate(new String[] {
0511: "filename", "graphLayoutCache" }));
0512: model.addPersistenceDelegate(JGraphpadGraphModel.class,
0513: new DefaultPersistenceDelegate(new String[] { "roots",
0514: "attributes", "connectionSet" }));
0515: model.addPersistenceDelegate(ConnectionSet.class,
0516: new DefaultPersistenceDelegate(
0517: new String[] { "connections" }));
0518:
0519: model.addPersistenceDelegate(JGraphpadGraphLayoutCache.class,
0520: new DefaultPersistenceDelegate(new String[] { "model",
0521: "visibleSet", "partial" }));
0522:
0523: model.addPersistenceDelegate(DefaultGraphCell.class,
0524: new DefaultPersistenceDelegate(
0525: new String[] { "userObject" }));
0526: model.addPersistenceDelegate(DefaultEdge.class,
0527: new DefaultPersistenceDelegate(
0528: new String[] { "userObject" }));
0529: model.addPersistenceDelegate(DefaultPort.class,
0530: new DefaultPersistenceDelegate(
0531: new String[] { "userObject" }));
0532:
0533: model.addPersistenceDelegate(JGraphpadBusinessObject.class,
0534: new DefaultPersistenceDelegate());
0535: model.addPersistenceDelegate(JGraphpadRichTextValue.class,
0536: new DefaultPersistenceDelegate());
0537:
0538: // Shadow Border instance
0539: model.addPersistenceDelegate(JGraphpadShadowBorder.class,
0540: new PersistenceDelegate() {
0541: protected Expression instantiate(
0542: Object oldInstance, Encoder out) {
0543: return new Expression(oldInstance,
0544: JGraphpadShadowBorder.class,
0545: "getSharedInstance", null);
0546: }
0547: });
0548:
0549: // Two shared routing instances
0550: model.addPersistenceDelegate(JGraphpadParallelEdgeRouter.class,
0551: new PersistenceDelegate() {
0552: protected Expression instantiate(
0553: Object oldInstance, Encoder out) {
0554: return new Expression(oldInstance,
0555: JGraphpadGraphConstants.class,
0556: "getParallelEdgeRouting", null);
0557: }
0558: });
0559: model.addPersistenceDelegate(
0560: JGraphpadParallelSplineRouter.class,
0561: new PersistenceDelegate() {
0562: protected Expression instantiate(
0563: Object oldInstance, Encoder out) {
0564: return new Expression(oldInstance,
0565: JGraphpadGraphConstants.class,
0566: "getParallelSplineRouting", null);
0567: }
0568: });
0569: }
0570:
0571: /**
0572: * Boilerplate method for configuring new editor kits. This implementation
0573: * calls {@link #addActions(JGraphEditor, JGraphEditorKit)},
0574: * {@link #addTools(JGraphEditor, JGraphEditorKit)}and registers the kit
0575: * with the listeners required to update the state. This method is called
0576: * from {@link #createKit(JGraphEditor)}.
0577: *
0578: * @param editor
0579: * The editor for which to configure the editor kit.
0580: * @param kit
0581: * The new editor kit to be configured.
0582: */
0583: protected void configureKit(JGraphEditor editor,
0584: final JGraphEditorKit kit) {
0585: addActions(editor, kit);
0586: addTools(editor, kit);
0587:
0588: // A selection listener for library pane's backing graph that
0589: // needs to be listened to for updating the actions in the kit.
0590: final GraphSelectionListener selectionListener = new GraphSelectionListener() {
0591:
0592: /**
0593: * Updates the actions in the factory kit when the selection of a
0594: * library pane (ie of its backing graph) changes.
0595: */
0596: public void valueChanged(GraphSelectionEvent e) {
0597: kit.update();
0598: }
0599:
0600: };
0601:
0602: KeyboardFocusManager focusManager = KeyboardFocusManager
0603: .getCurrentKeyboardFocusManager();
0604: focusManager
0605: .addPropertyChangeListener(new PropertyChangeListener() {
0606:
0607: /*
0608: * (non-Javadoc)
0609: */
0610: public void propertyChange(PropertyChangeEvent e) {
0611: if (e.getPropertyName().equals(
0612: "permanentFocusOwner")) {
0613: kit.update();
0614: }
0615:
0616: // Keeps the selection listener installed with the library
0617: // pane's backing graph. Travels along with the focus.
0618: if (e.getOldValue() instanceof JGraphpadLibraryPane) {
0619: ((JGraphpadLibraryPane) e.getOldValue())
0620: .getBackingGraph()
0621: .getSelectionModel()
0622: .removeGraphSelectionListener(
0623: selectionListener);
0624: }
0625:
0626: if (e.getNewValue() instanceof JGraphpadLibraryPane) {
0627: ((JGraphpadLibraryPane) e.getNewValue())
0628: .getBackingGraph()
0629: .getSelectionModel()
0630: .addGraphSelectionListener(
0631: selectionListener);
0632: }
0633: }
0634: });
0635:
0636: JGraphpadFocusManager.getCurrentGraphFocusManager()
0637: .addPropertyChangeListener(
0638: new PropertyChangeListener() {
0639:
0640: /*
0641: * (non-Javadoc)
0642: */
0643: public void propertyChange(
0644: PropertyChangeEvent e) {
0645: kit.update();
0646: }
0647: });
0648: kit.update();
0649: }
0650:
0651: //
0652: // Actions
0653: //
0654:
0655: /**
0656: * Adds the action bundles for {@link JGraphpadEditAction},
0657: * {@link JGraphpadFileAction},{@link JGraphpadViewAction},
0658: * {@link JGraphpadFormatAction}and {@link JGraphpadCellAction}. Uses the
0659: * createVertex and createEdge method to construct prototypes for
0660: * {@link JGraphpadCellAction#NAME_GROUP}and
0661: * {@link JGraphpadCellAction#NAME_CONNECT}. This method is called from
0662: * configureEditorKit.
0663: *
0664: * @param editor
0665: * The editor for which to create the actions.
0666: * @param kit
0667: * The editor kit to add the actions to.
0668: *
0669: * @see #configureKit(JGraphEditor, JGraphEditorKit)
0670: * @see JGraphEditorKit#addBundle(JGraphEditorAction.Bundle)
0671: * @see #createVertex()
0672: * @see #createEdge()
0673: */
0674: protected void addActions(JGraphEditor editor, JGraphEditorKit kit) {
0675:
0676: // Adds action bundles for each of the menus. To simplify
0677: // searching for specific actions all actions reside in
0678: // the classes corresponding to the menu they are in.
0679: kit.addBundle(new JGraphpadEditAction.AllActions());
0680: kit.addBundle(new JGraphpadViewAction.AllActions());
0681: kit.addBundle(new JGraphpadFormatAction.AllActions());
0682: //kit.addBundle(new JGraphpadHelpAction.AllActions());
0683:
0684: // Adds actions that require prototype cells
0685: // kit.addBundle(new JGraphpadFileAction.AllActions(editor));
0686: kit.addAction(new JGraphpadFileAction(
0687: JGraphpadFileAction.NAME_PRINT, editor));
0688:
0689: kit.addBundle(new JGraphpadCellAction.AllActions(editor));
0690: }
0691:
0692: //
0693: // Editor Tools
0694: //
0695:
0696: /**
0697: * Adds the following tools to <code>kit</code>:{@link #NAME_SELECTTOOL},
0698: * {@link #NAME_VERTEXTOOL},{@link #NAME_ROUNDEDTOOL},
0699: * {@link #NAME_CIRCLETOOL},{@link #NAME_DIAMONDTOOL},{@link #NAME_TRIANGLETOOL},
0700: * {@link #NAME_IMAGETOOL},{@link #NAME_HEAVYTOOL},{@link #NAME_EDGETOOL}and
0701: * {@link #NAME_ORTHOGONALEDGETOOL}. This method is called from
0702: * configureEditorKit.
0703: *
0704: * @param editor
0705: * The editor for which to create the tools.
0706: * @param kit
0707: * The editor kit to add the tools to.
0708: *
0709: * @see #configureKit(JGraphEditor, JGraphEditorKit)
0710: * @see JGraphEditorKit#addTool(JGraphEditorTool)
0711: * @see #createVertexTool(String, Object, int, ImageIcon)
0712: * @see #createEdgeTool(String, String, Edge.Routing)
0713: */
0714: protected void addTools(JGraphEditor editor, JGraphEditorKit kit) {
0715: kit.addTool(new JGraphEditorTool(NAME_SELECTTOOL, false));
0716: JGraphpadVertexTool tool = createVertexTool(NAME_TEXTTOOL,
0717: new JGraphpadRichTextValue(""), -1, null, true);
0718: tool.setPreviewEnabled(false);
0719: kit.addTool(tool);
0720: kit.addTool(createVertexTool(NAME_VERTEXTOOL,
0721: new JGraphpadRichTextValue(""),
0722: JGraphpadVertexRenderer.SHAPE_RECTANGLE, null));
0723: JComponent c = new JGraphpadHeavyweightRenderer();
0724: kit.addTool(createVertexTool(NAME_HEAVYTOOL, c,
0725: JGraphpadVertexRenderer.SHAPE_RECTANGLE, null));
0726: kit.addTool(createVertexTool(NAME_ROUNDEDTOOL,
0727: new JGraphpadRichTextValue(""),
0728: JGraphpadVertexRenderer.SHAPE_ROUNDED, null));
0729: kit.addTool(createVertexTool(NAME_CIRCLETOOL,
0730: new JGraphpadRichTextValue(""),
0731: JGraphpadVertexRenderer.SHAPE_CIRCLE, null));
0732:
0733: kit.addTool(createVertexTool(NAME_DIAMONDTOOL,
0734: new JGraphpadRichTextValue(""),
0735: JGraphpadVertexRenderer.SHAPE_DIAMOND, null));
0736: kit.addTool(createVertexTool(NAME_TRIANGLETOOL,
0737: new JGraphpadRichTextValue(""),
0738: JGraphpadVertexRenderer.SHAPE_TRIANGLE, null));
0739: kit.addTool(createVertexTool(NAME_CYLINDERTOOL,
0740: new JGraphpadRichTextValue(""),
0741: JGraphpadVertexRenderer.SHAPE_CYLINDER, null));
0742: // Uses default image resource from classpath
0743: JGraphpadImageIcon icon = new JGraphpadImageIcon(
0744: "/com/jgraph/pad/images/noimage.gif");
0745: kit.addTool(createVertexTool(NAME_IMAGETOOL, "",
0746: JGraphpadVertexRenderer.SHAPE_RECTANGLE, icon));
0747: kit.addTool(createEdgeTool(NAME_EDGETOOL,
0748: new JGraphpadRichTextValue(""), null));
0749: kit.addTool(createEdgeTool(NAME_ORTHOGONALEDGETOOL,
0750: new JGraphpadRichTextValue(""),
0751: GraphConstants.ROUTING_SIMPLE));
0752: }
0753:
0754: /**
0755: * Invokes
0756: * {@link #createVertexTool(String, Object, int, ImageIcon, boolean)} with
0757: * post editing set to false.
0758: */
0759: protected JGraphpadVertexTool createVertexTool(String name,
0760: Object defaultValue, int shape, ImageIcon icon) {
0761: return createVertexTool(name, defaultValue, shape, icon, false);
0762: }
0763:
0764: /**
0765: * Helper method to create and return a new vertex tool. This uses the
0766: * createVertexUserObject or creates a new {@link JGraphpadRichTextValue}
0767: * object based on <code>isRichText</code> as the user object, which it
0768: * passes to createVertex to create the graph cell. The method sets the
0769: * shape on the created graph cell, and returns a new JGraphpadVertexTool
0770: * with the specified name.
0771: *
0772: * @param name
0773: * The name of the tool to be created.
0774: * @param defaultValue
0775: * The defaultValue for the vertices that this tool creates.
0776: * @param shape
0777: * The shape for the vertices that this tool creates. Use -1 for
0778: * no border.
0779: * @param icon
0780: * The icon for the vertices that this tool creates.
0781: * @param postEdit
0782: * If in-place editing should be triggered after inserting the
0783: * cell.
0784: * @return Returns a new vertex tool.
0785: *
0786: * @see JGraphpadRichTextValue
0787: * @see #createVertexUserObject(Object)
0788: * @see #createVertex(Object)
0789: * @see JGraphpadGraphConstants#setVertexShape(Map, int)
0790: * @see JGraphpadVertexTool
0791: */
0792: protected JGraphpadVertexTool createVertexTool(String name,
0793: Object defaultValue, int shape, ImageIcon icon,
0794: boolean postEdit) {
0795: Object userObject = createVertexUserObject(defaultValue);
0796: GraphCell vertex = createVertex(userObject);
0797: if (shape >= 0) {
0798: JGraphpadGraphConstants.setVertexShape(vertex
0799: .getAttributes(), shape);
0800: } else {
0801: vertex.getAttributes().remove(GraphConstants.BORDERCOLOR);
0802: vertex.getAttributes().remove(GraphConstants.BORDER);
0803: }
0804: if (icon != null) {
0805: GraphConstants.setIcon(vertex.getAttributes(), icon);
0806: }
0807: if (postEdit) {
0808: return new JGraphpadVertexTool(name, vertex) {
0809: protected void execute(JGraph graph, Object cell) {
0810: super .execute(graph, cell);
0811: graph.startEditingAtCell(cell);
0812: }
0813: };
0814: }
0815:
0816: return new JGraphpadVertexTool(name, vertex);
0817: }
0818:
0819: /**
0820: * Helper method to create and return a new edge tool. This passes the
0821: * return value of createEdgeUserObject to createEdge to create the graph
0822: * cell. The method sets the routing on the created graph cell if it is not
0823: * <code>null</code>, and returns a new JGraphpadEdgeTool with the
0824: * specified name.
0825: *
0826: * @param name
0827: * The name of the tool to be created.
0828: * @param defaultValue
0829: * The defaultValue for the edges that this tool creates.
0830: * @param routing
0831: * The routing for the edges that this tool creates.
0832: * @return Returns a new edge tool.
0833: *
0834: * @see #createEdgeUserObject(Object)
0835: * @see #createEdge(Object)
0836: * @see GraphConstants#setRouting(Map, Edge.Routing)
0837: * @see JGraphpadEdgeTool
0838: */
0839: protected JGraphpadEdgeTool createEdgeTool(String name,
0840: Object defaultValue, Edge.Routing routing) {
0841: DefaultEdge edge = createEdge(createEdgeUserObject(defaultValue));
0842: if (routing != null)
0843: GraphConstants.setRouting(edge.getAttributes(), routing);
0844: return new JGraphpadEdgeTool(name, edge);
0845: }
0846:
0847: /**
0848: * Constructs a default factory for new editors. This implementation
0849: * constructs a new instance of JGraphEditorFactory and overrides
0850: * {@link JGraphEditorFactory#createGraph(GraphLayoutCache)} to call
0851: * {@link #createGraph(JGraphEditor, GraphLayoutCache)} and configures the
0852: * factory using
0853: * {@link #configureFactory(JGraphEditor, JGraphEditorFactory)}.
0854: *
0855: * @param editor
0856: * The editor for which to create an editor factory.
0857: * @return Returns a configured editor factory for the specified editor.
0858: */
0859: protected JGraphEditorFactory createFactory(
0860: final JGraphEditor editor) {
0861: JGraphEditorFactory factory = new JGraphEditorFactory(editor
0862: .getKit()) {
0863: public JGraph createGraph(GraphLayoutCache graphLayoutCache) {
0864: return DiagramEditorApplet.this .createGraph(editor,
0865: graphLayoutCache);
0866: }
0867: };
0868: configureFactory(editor, factory);
0869: return factory;
0870: }
0871:
0872: /**
0873: * Hook for subclassers to configure new editor factories. This
0874: * implementation adds various following factory methods.
0875: *
0876: * @param editor
0877: * The editor to create the factory methods for.
0878: * @param factory
0879: * The factory to be configured.
0880: */
0881: protected void configureFactory(JGraphEditor editor,
0882: JGraphEditorFactory factory) {
0883:
0884: // Adds the factory methods from the Editor Framework
0885: factory.addMethod(new JGraphEditorNavigator.FactoryMethod(
0886: editor));
0887: factory
0888: .addMethod(new JGraphEditorComboBox.BorderComboFactoryMethod());
0889: factory
0890: .addMethod(new JGraphEditorComboBox.LineDecorationComboFactoryMethod());
0891: factory
0892: .addMethod(new JGraphEditorComboBox.LineWidthComboFactoryMethod());
0893: factory
0894: .addMethod(new JGraphEditorComboBox.DashPatternComboFactoryMethod());
0895:
0896: // Adds custom factory methods
0897: factory
0898: .addMethod(new JGraphpadComboBox.VertexShapeComboFactoryMethod());
0899: factory
0900: .addMethod(new JGraphpadComboBox.ColorComboFactoryMethod());
0901: factory
0902: .addMethod(new JGraphpadComboBox.ColorComboFactoryMethod(
0903: METHOD_CREATELINECOLORCOMBO,
0904: JGraphpadComboBox.TYPE_LINECOLOR));
0905: factory
0906: .addMethod(new JGraphpadComboBox.ColorComboFactoryMethod(
0907: METHOD_CREATEGRADIENTCOMBO,
0908: JGraphpadComboBox.TYPE_GRADIENT));
0909: factory
0910: .addMethod(new JGraphpadLibraryPane.FactoryMethod(
0911: editor));
0912: factory
0913: .addMethod(new JGraphpadWindowMenu.FactoryMethod(editor));
0914: factory.addMethod(new JGraphpadOpenRecentMenu(editor));
0915: factory.addMethod(new JGraphpadConsole.FactoryMethod());
0916: factory.addMethod(new JGraphpadStatusBar.FactoryMethod(editor));
0917: }
0918:
0919: /**
0920: * Hook for subclassers to create plugins for a new editor. This
0921: * implementation creates the {@link #defaultPlugins}. This method is
0922: * called from {@link #configureEditor(JGraphEditor, Map)}.
0923: *
0924: * @param editor
0925: * The editor for which to create the plugins.
0926: */
0927: protected void createPlugins(JGraphEditor editor) {
0928: if (defaultPlugins != null) {
0929: for (int i = 0; i < defaultPlugins.length; i++) {
0930: try {
0931: System.out.print("Loading " + defaultPlugins[i]
0932: + "... ");
0933: JGraphEditorPlugin plugin = (JGraphEditorPlugin) Class
0934: .forName(defaultPlugins[i]).newInstance();
0935: plugin.initialize(editor, null);
0936: System.out.println("Done");
0937: } catch (Throwable e) {
0938: System.out.println("Not Available");
0939: }
0940: }
0941: }
0942: }
0943:
0944: //
0945: // Custom graph and factory methods
0946: //
0947:
0948: /**
0949: * Hook for subclassers to provide a custom graph for the user interface.
0950: * This method is invoked by the default custom factory returned by the
0951: * createEditorFactory method. It invokes
0952: * {@link #configureGraph(JGraphEditor, JGraph)} to configure the new graph
0953: * instance.
0954: *
0955: * @see #createFactory(JGraphEditor)
0956: */
0957: protected JGraph createGraph(JGraphEditor editor,
0958: GraphLayoutCache graphLayoutCache) {
0959: JGraph graph = new JGraphpadGraph(graphLayoutCache);
0960: configureGraph(editor, graph);
0961: return graph;
0962: }
0963:
0964: /**
0965: * Hook for subclassers to configure a new graph. This implementation adds a
0966: * {@link JGraphpadTransferHandler} and {@link JGraphpadMarqueeHandler} to
0967: * the instance. (Note: {@link #createVertex()} is used to create the
0968: * prototype cell for the transfer handler.)
0969: *
0970: * @param graph
0971: * The graph to be configured
0972: */
0973: protected void configureGraph(JGraphEditor editor, JGraph graph) {
0974: ToolTipManager.sharedInstance().registerComponent(graph);
0975: graph.setTransferHandler(new JGraphpadTransferHandler(
0976: createVertex()));
0977: graph.setMarqueeHandler(new JGraphpadMarqueeHandler(editor));
0978: graph.setInvokesStopCellEditing(true);
0979: graph.setJumpToDefaultPort(true);
0980: graph.setMoveOutOfGroups(true);
0981: graph.setMoveIntoGroups(true);
0982: graph.setDragEnabled(true);
0983: graph.setCloneable(true);
0984: graph.setOpaque(false);
0985: }
0986:
0987: //
0988: // Custom Cells (Vertices, Groups, Edges & Ports) and User Objects
0989: //
0990:
0991: /**
0992: * Hook for subclassers to construct vertices with default user objects.
0993: * This implementation invokes {@link #createVertexUserObject(Object)}and
0994: * passes the return value to {@link #createVertex(Object)}.
0995: *
0996: * @return Returns a new vertex with a default user object.
0997: */
0998: public GraphCell createVertex() {
0999: return createVertex(createVertexUserObject(null));
1000: }
1001:
1002: /**
1003: * Returns a new DefaultGraphCell containing the specified user object. This
1004: * implementation uses {@link #createAttributeMap()}to create the map that
1005: * holds the attributes for the new vertex, and
1006: * {@link #configureVertex(GraphCell)}to configure the vertex.
1007: *
1008: * @param userObj
1009: * The user object that the vertex should contain.
1010: * @return Returns a new vertex.
1011: */
1012: public GraphCell createVertex(Object userObj) {
1013: DefaultGraphCell vertex = new DefaultGraphCell(userObj,
1014: createAttributeMap());
1015: configureVertex(vertex);
1016: return vertex;
1017: }
1018:
1019: /**
1020: * Hook for subclassers to configure the specified vertex. This
1021: * implementation sets the {@link #defaultBorderColor}and adds ports if the
1022: * vertex implements the {@link MutableTreeNode}interface.
1023: *
1024: * @param vertex
1025: * The vertex to be configured.
1026: *
1027: * @see #addPorts(MutableTreeNode, Point2D[])
1028: */
1029: protected void configureVertex(GraphCell vertex) {
1030: AttributeMap attributes = vertex.getAttributes();
1031: if (defaultBorderColor != null) {
1032: GraphConstants.setOpaque(attributes, false);
1033: GraphConstants.setBorderColor(attributes,
1034: defaultBorderColor);
1035: GraphConstants.setGroupOpaque(attributes, false);
1036: JGraphpadGraphConstants.setGroupResize(attributes, true);
1037: JGraphpadGraphConstants.setInset(attributes, 4);
1038: }
1039: if (vertex instanceof MutableTreeNode)
1040: addPorts((MutableTreeNode) vertex, defaultPortLocations);
1041: }
1042:
1043: /**
1044: * Hook for subclassers to construct groups with default user objects. This
1045: * implementation invokes {@link #createVertexUserObject(Object)}and passes
1046: * the return value to {@link #createGroup(Object)}.
1047: *
1048: * @return Returns a new group with a default user object.
1049: */
1050: public GraphCell createGroup() {
1051: return createVertex(createVertexUserObject(null));
1052: }
1053:
1054: /**
1055: * Returns a new DefaultGraphCell containing the specified user object. This
1056: * implementation uses {@link #createAttributeMap()}to create the map that
1057: * holds the attributes for the new vertex, and
1058: * {@link #configureVertex(GraphCell)}to configure the vertex.
1059: *
1060: * @param userObj
1061: * The user object that the group should contain.
1062: * @return Returns a new group.
1063: */
1064: public GraphCell createGroup(Object userObj) {
1065: DefaultGraphCell vertex = new DefaultGraphCell(userObj,
1066: createAttributeMap());
1067: configureVertex(vertex);
1068: return vertex;
1069: }
1070:
1071: /**
1072: * Adds ports to <code>parent</code> using <code>offsets</code> as the
1073: * port relative offsets. The method uses
1074: * {@link #createPortUserObject(Object)},
1075: * {@link #createPort(MutableTreeNode, Object)}and
1076: * {@link #configurePort(GraphCell, Point2D)}to create the ports and their
1077: * user objects, configure them and add them to the parent.
1078: *
1079: * @param parent
1080: * The parent to add the ports to.
1081: * @param offsets
1082: * The points defining the port locations.
1083: */
1084: protected void addPorts(MutableTreeNode parent, Point2D[] offsets) {
1085: for (int i = 0; i < offsets.length; i++) {
1086: GraphCell port = createPort(parent,
1087: createPortUserObject(null));
1088: configurePort(port, offsets[i]);
1089: }
1090: }
1091:
1092: /**
1093: * Creates a port containing the specified user object and adds it to
1094: * <code>parent</code>.
1095: *
1096: * @param userObject
1097: * The user object that the port should contain.
1098: * @return Returns a new port.
1099: */
1100: public GraphCell createPort(MutableTreeNode parent,
1101: Object userObject) {
1102: DefaultGraphCell port = new DefaultPort(userObject);
1103: parent.insert(port, parent.getChildCount());
1104: port.setParent(parent);
1105: return port;
1106: }
1107:
1108: /**
1109: * Hook for subclassers to configure the specified port using the
1110: * <code>offset</code> as the relative location.
1111: *
1112: * @param port
1113: * The port to be configured.
1114: * @param offset
1115: * The relative offset of the port.
1116: */
1117: public void configurePort(GraphCell port, Point2D offset) {
1118: AttributeMap map = port.getAttributes();
1119: if (offset != null)
1120: GraphConstants.setOffset(map, offset);
1121: }
1122:
1123: /**
1124: * Hook for subclassers to construct edgges with default user objects. This
1125: * implementation invokes {@link #createEdgeUserObject(Object)}and passes
1126: * the return value to {@link #createEdge(Object)}.
1127: *
1128: * @return Returns a new edge with a default user object.
1129: */
1130: public DefaultEdge createEdge() {
1131: return createEdge(createEdgeUserObject(null));
1132: }
1133:
1134: /**
1135: * Returns a new DefaultEdge containing the specified user object. This
1136: * implementation uses {@link #createAttributeMap()}to create the map that
1137: * holds the attributes for the new edge and
1138: * {@link #configureEdge(GraphCell)}to configure the edge.
1139: *
1140: * @param userObj
1141: * The user object that the edge should contain.
1142: * @return Returns a new edge.
1143: */
1144: public DefaultEdge createEdge(Object userObj) {
1145: DefaultEdge edge = new DefaultEdge(userObj,
1146: createAttributeMap());
1147: configureEdge(edge);
1148: return edge;
1149: }
1150:
1151: /**
1152: * Hook for subclassers to configure the specified edge. This implementation
1153: * sets the {@link #defaultEdgeFont},{@link #defaultEndDecoration}and
1154: * {@link #defaultBeginDecoration}.
1155: *
1156: * @param edge
1157: * The edge to be configured.
1158: */
1159: protected void configureEdge(GraphCell edge) {
1160: AttributeMap attributes = edge.getAttributes();
1161: if (defaultEdgeFont != null)
1162: GraphConstants.setFont(attributes, defaultEdgeFont);
1163: if (defaultEndDecoration != GraphConstants.ARROW_NONE)
1164: GraphConstants.setLineEnd(attributes, defaultEndDecoration);
1165: if (defaultBeginDecoration != GraphConstants.ARROW_NONE)
1166: GraphConstants.setLineBegin(attributes,
1167: defaultBeginDecoration);
1168: if (edge instanceof MutableTreeNode)
1169: addPorts((MutableTreeNode) edge, defaultPortLocations);
1170: }
1171:
1172: /**
1173: * Hook for subclassers to create a user object for edges that contains the
1174: * specified value. This implementation calls
1175: * {@link #createVertexUserObject(Object)}.
1176: *
1177: * @param value
1178: * The value that the user object should contain.
1179: * @return Returns a new user object containing <code>value</code>.
1180: */
1181: protected Object createEdgeUserObject(Object value) {
1182: return createVertexUserObject(value);
1183: }
1184:
1185: /**
1186: * Hook for subclassers to create a user object for ports that contains the
1187: * specified value. This implementation calls
1188: * {@link #createVertexUserObject(Object)}.
1189: *
1190: * @param value
1191: * The value that the user object should contain.
1192: * @return Returns a new user object containing <code>value</code>.
1193: */
1194: protected Object createPortUserObject(Object value) {
1195: return createVertexUserObject(value);
1196: }
1197:
1198: /**
1199: * Returns a new {@link JGraphpadBusinessObject}for the specified value.
1200: * This implementation replaces all <code>null</code> values with an empty
1201: * {@link JGraphpadRichTextValue}.
1202: *
1203: * @param value
1204: * The value that the user object should contain.
1205: * @return Returns a new user object containing <code>value</code>.
1206: *
1207: * @see JGraphpadBusinessObject
1208: */
1209: protected Object createVertexUserObject(Object value) {
1210: return new JGraphpadBusinessObject((value != null) ? value
1211: : new JGraphpadRichTextValue(""));
1212: }
1213:
1214: /**
1215: * Hook for subclassers to construct attribute map for cells. This
1216: * implementation returns a new instance of {@link AttributeMap}.
1217: *
1218: * @return Returns a new attribute map.
1219: */
1220: protected AttributeMap createAttributeMap() {
1221: return new AttributeMap();
1222: }
1223:
1224: /**
1225: * Returns true if the specified filename has an image extension, namely one
1226: * in {@link javax.imageio.ImageIO#getReaderFormatNames()}.
1227: *
1228: * @param filename
1229: * The filename to be checked.
1230: * @return Returns true if the filename is an image file.
1231: */
1232: public static boolean isImage(String filename) {
1233: String[] formats = ImageIO.getReaderFormatNames();
1234: filename = filename.toLowerCase();
1235: for (int j = 0; j < formats.length; j++) {
1236: if (filename.endsWith(formats[j].toLowerCase()))
1237: return true;
1238: }
1239: return false;
1240: }
1241:
1242: /**
1243: * Node name used for menu configurations.
1244: */
1245: private static final String NODENAME_MENUBAR = "menubar";
1246:
1247: /**
1248: * Node name used for toolbar configurations.
1249: */
1250: private static final String NODENAME_TOOLBAR = "toolbar";
1251:
1252: /**
1253: * Node name used for toolbox configurations.
1254: */
1255: private static final String NODENAME_TOOLBOX = "toolbox";
1256:
1257: /**
1258: * Constructs and displays a new application window.
1259: */
1260: public static void main(String[] args) throws Exception {
1261: JApplet applet = new DiagramEditorApplet();
1262: applet.init();
1263: applet.start();
1264: applet.setVisible(true);
1265: JFrame frame = new JFrame();
1266: frame.add(applet);
1267: frame.setSize(300, 300);
1268: frame.setVisible(true);
1269: System.out.println("Done");
1270: Thread.sleep(5000);
1271: applet.stop();
1272: applet.start();
1273: //applet.destroy();
1274:
1275: }
1276:
1277: // public String getParameter(String name) {
1278: // return null;
1279: // }
1280:
1281: private DbFileImpl dbFile;
1282: private DiagramEditorAppletPane editorPane;
1283: private long loadTime = System.currentTimeMillis();
1284:
1285: private JGraphpadFile diagramFile;
1286:
1287: public DiagramEditorApplet() {
1288: info("New instance");
1289: }
1290:
1291: private JPanel replaceablePanel;
1292:
1293: public void start() {
1294: super .start();
1295:
1296: replaceablePanel = new JPanel();
1297: getContentPane().add(replaceablePanel, BorderLayout.CENTER);
1298:
1299: info("Starting diagram editor");
1300: cookie = getParameter("Cookie");
1301: downloadUrl = getParameter("DownloadURL");
1302: uploadUrl = getParameter("UploadURL");
1303: exitUrl = getParameter("ExitURL");
1304: ownerId = getParameter("OwnerId");
1305: ownerType = getParameter("OwnerType");
1306: parentFileId = getParameter("Parent");
1307:
1308: // Constructs the editor
1309: editor = new JGraphEditor();
1310:
1311: // Configures the editor kit, factory and constructs plugins
1312: editor.setSettings(createSettings(new HashMap()));
1313: JGraphEditorModel model = new JGraphEditorModel();
1314: configureModel(model);
1315: editor.setModel(model);
1316: JGraphEditorKit kit = new JGraphEditorKit();
1317: configureKit(editor, kit);
1318:
1319: if (uploadUrl != null) {
1320: kit.addAction(new JGraphEditorAction("save") {
1321:
1322: public void actionPerformed(ActionEvent e) {
1323: save();
1324: }
1325:
1326: });
1327:
1328: if (exitUrl != null) {
1329: kit.addAction(new JGraphEditorAction("saveAndClose") {
1330:
1331: public void actionPerformed(ActionEvent e) {
1332: saveAndClose();
1333: }
1334:
1335: });
1336: }
1337: }
1338:
1339: kit.addAction(new JGraphEditorAction("fileProperties") {
1340:
1341: public void actionPerformed(ActionEvent e) {
1342: Container owner = DiagramEditorApplet.this ;
1343: while (owner != null && !(owner instanceof JFrame)) {
1344: owner = owner.getParent();
1345: }
1346: DiagramPropertiesDialog dpd = new DiagramPropertiesDialog(
1347: owner instanceof JFrame ? (JFrame) owner : null,
1348: DiagramEditorApplet.this );
1349: dpd.setVisible(true);
1350: }
1351:
1352: });
1353:
1354: kit.addAction(new JGraphEditorAction("editDialog") {
1355:
1356: public void actionPerformed(ActionEvent e) {
1357: JGraph graph = editorPane.getGraph();
1358: Object cell = graph.getSelectionCell();
1359: if (cell != null && graph.isCellEditable(cell)
1360: && cell instanceof DefaultMutableTreeNode) {
1361: Container owner = DiagramEditorApplet.this ;
1362: while (owner != null && !(owner instanceof JFrame)) {
1363: owner = owner.getParent();
1364: }
1365: CellTextDialog ctd = new CellTextDialog(
1366: owner instanceof JFrame ? (JFrame) owner
1367: : null,
1368: (DefaultMutableTreeNode) cell);
1369: ctd.setVisible(true);
1370: GraphLayoutCache graphLayoutCache = graph
1371: .getGraphLayoutCache();
1372: CellView cellView = graphLayoutCache.getMapping(
1373: cell, false);
1374: cellView.update(graphLayoutCache);
1375: graph.repaint();
1376: }
1377:
1378: }
1379:
1380: });
1381:
1382: editor.setKit(kit);
1383: editor.setFactory(createFactory(editor));
1384:
1385: // Adds the plugins settings, actions, tools and methods
1386: // and initializes the plugins.
1387: createPlugins(editor);
1388:
1389: Element configuration = editor.getSettings().getDocument(
1390: NAME_UICONFIG).getDocumentElement();
1391: replaceablePanel.setLayout(new BorderLayout());
1392:
1393: // Fetches the menu bar configuration and constructs
1394: // the menubar for the frame.
1395: Node menuBarConfiguration = JGraphEditorSettings.getNodeByName(
1396: configuration.getChildNodes(), NODENAME_MENUBAR);
1397: setJMenuBar(editor.getFactory().createMenuBar(
1398: menuBarConfiguration));
1399:
1400: // Creates container for multiple toolbars and
1401: // adds it to the main window.
1402: JPanel toolbars = new JPanel(new GridLayout(2, 1));
1403: replaceablePanel.add(toolbars, BorderLayout.NORTH);
1404:
1405: // Fetches the toolbar configuration and create the toolbar
1406: Node toolbarConfiguration = JGraphEditorSettings.getNodeByName(
1407: configuration.getChildNodes(), NODENAME_TOOLBAR);
1408: JToolBar toolbar = editor.getFactory().createToolBar(
1409: toolbarConfiguration);
1410: toolbars.add(toolbar);
1411:
1412: // Fetches the toolbox configuration and creates the toolbox
1413: Node toolboxConfiguration = JGraphEditorSettings.getNodeByName(
1414: configuration.getChildNodes(), NODENAME_TOOLBOX);
1415: final JGraphEditorToolbox toolbox = editor.getFactory()
1416: .createToolbox(toolboxConfiguration);
1417: toolbars.add(toolbox);
1418:
1419: // Adds the status bar using its factory method
1420: Component statusBar = editor.getFactory().executeMethod(
1421: JGraphpadStatusBar.FactoryMethod.NAME);
1422: if (statusBar != null) {
1423: replaceablePanel.add(statusBar, BorderLayout.SOUTH);
1424: }
1425:
1426: JGraphpadFocusManager focusedGraph = JGraphpadFocusManager
1427: .getCurrentGraphFocusManager();
1428: focusedGraph
1429: .addPropertyChangeListener(new PropertyChangeListener() {
1430: public void propertyChange(PropertyChangeEvent e) {
1431:
1432: // Updates the installed graph in the toolbox
1433: String prop = e.getPropertyName();
1434: if (prop
1435: .equals(JGraphpadFocusManager.FOCUSED_GRAPH_PROPERTY)
1436: && e.getNewValue() instanceof JGraph) {
1437: toolbox.setGraph((JGraph) e.getNewValue());
1438: }
1439: }
1440: });
1441:
1442: // ** Application construction complete **
1443:
1444: // Puts the main window into the settings map and
1445: // restores its bounds from the user settings.
1446: // editor.getSettings().putObject(KEY_MAINWINDOW, this);
1447: // editor.getSettings().restoreWindow(NAME_USERSETTINGS, KEY_MAINWINDOW);
1448:
1449: try {
1450: if (downloadUrl == null) {
1451: final String fileName = "Document 1";
1452: // Creates and adds the editor pane and adds a diagram tracker to
1453: // listen to the model and update the internal frames and tabs in
1454: // the editor pane.
1455: dbFile = new DbFileImpl();
1456: dbFile.setAttribute(CREATE_ID, Long
1457: .toHexString(loadTime)
1458: + ":"
1459: + Long.toHexString(System.currentTimeMillis()));
1460: dbFile.setAttribute(IS_NEW, Boolean.TRUE);
1461: dbFile.setName(fileName);
1462: dbFile.setOwnerId(ownerId);
1463: dbFile.setOwnerType(ownerType);
1464: if (parentFileId != null) {
1465: dbFile.setParent(new Integer(parentFileId));
1466: }
1467:
1468: diagramFile = new JGraphpadFile(fileName);
1469: editor.getModel().addRoot(diagramFile);
1470: JGraphpadDiagram newDiagram = new JGraphpadDiagram(
1471: "Diagram 1");
1472: editor.getModel().addChild(newDiagram, diagramFile);
1473: editorPane = new DiagramEditorAppletPane(editor,
1474: newDiagram);
1475: replaceablePanel.add(editorPane, BorderLayout.CENTER);
1476: } else {
1477: HttpClient httpClient = new HttpClient();
1478: HttpMethod method = new GetMethod(downloadUrl);
1479: if (cookie != null) {
1480: method.setRequestHeader("Cookie", cookie);
1481: }
1482: int statusCode = httpClient.executeMethod(method);
1483: if (statusCode == HttpStatus.SC_OK) {
1484: ByteArrayInputStream bis = new ByteArrayInputStream(
1485: method.getResponseBody());
1486: method.releaseConnection();
1487: ObjectInputStream ois = new ObjectInputStream(bis);
1488: dbFile = (DbFileImpl) ois.readObject();
1489: ois.close();
1490: bis.close();
1491:
1492: bis = new ByteArrayInputStream(dbFile
1493: .getFileContent());
1494: DataInputStream dis = new DataInputStream(
1495: new GZIPInputStream(bis));
1496: int offset = dis.readInt();
1497: dis.skip(offset);
1498: diagramFile = (JGraphpadFile) editor.getModel()
1499: .readObject(dis);
1500: dis.close();
1501: bis.close();
1502: diagramFile.setFilename(dbFile.getName());
1503: System.out.println("Loaded diagram: "
1504: + diagramFile.getFilename());
1505: editor.getModel().addRoot(diagramFile);
1506: JGraphpadDiagram diagram = (JGraphpadDiagram) diagramFile
1507: .getFirstChild();
1508: editorPane = new DiagramEditorAppletPane(editor,
1509: diagram);
1510: replaceablePanel.add(editorPane,
1511: BorderLayout.CENTER);
1512: } else {
1513: JOptionPane.showMessageDialog(this ,
1514: "Could not load diagram from "
1515: + downloadUrl
1516: + ".\nHttp error code: "
1517: + statusCode + "\n"
1518: + method.getResponseBodyAsString(),
1519: "Error", JOptionPane.ERROR_MESSAGE);
1520: statusMessage("Disabled");
1521: setEnabled(false);
1522: }
1523: }
1524: //saveAction.setEnabled(false);
1525: toolbox.setGraph(editorPane.getGraph());
1526: kit.update();
1527: editorPane.requestFocus();
1528: } catch (Exception e) {
1529: e.printStackTrace();
1530: JOptionPane.showMessageDialog(this ,
1531: "Could not load diagram:\n" + e, "Exception",
1532: JOptionPane.ERROR_MESSAGE);
1533: statusMessage("Disabled");
1534: setEnabled(false);
1535: } catch (Error er) {
1536: JOptionPane.showMessageDialog(this ,
1537: "Could not load diagram:\n" + er, "Error",
1538: JOptionPane.ERROR_MESSAGE);
1539: statusMessage("Disabled");
1540: setEnabled(false);
1541: throw er;
1542: }
1543: }
1544:
1545: public void stop() {
1546: if (replaceablePanel != null) {
1547: getContentPane().remove(replaceablePanel);
1548: replaceablePanel = null;
1549: }
1550: info("Diagram editor stopped");
1551: }
1552:
1553: public void destroy() {
1554: info("Destroying diagram editor");
1555: }
1556:
1557: private void statusMessage(String msg) {
1558: System.out.println(msg); // TODO output to status bar
1559: }
1560:
1561: private void save() {
1562: save(true);
1563: }
1564:
1565: private void save(boolean showSavedDialog) {
1566: try {
1567: setEnabled(false);
1568: JGraph graph = editorPane.getGraph();
1569: Color bg = graph.getBackground();
1570: ByteArrayOutputStream baos = new ByteArrayOutputStream();
1571: DataOutputStream dos = new DataOutputStream(
1572: new GZIPOutputStream(baos));
1573: BufferedImage img = graph.getImage(bg, 5);
1574: if (img == null) {
1575: dos.writeInt(0);
1576: } else {
1577: ByteArrayOutputStream imageOut = new ByteArrayOutputStream();
1578: ImageIO.write(img, "PNG", imageOut);
1579: imageOut.flush();
1580: imageOut.close();
1581: byte[] iBytes = imageOut.toByteArray();
1582: dos.writeInt(iBytes.length);
1583: dos.write(iBytes);
1584: }
1585: editor.getModel().writeObject(diagramFile, dos);
1586: dos.close();
1587: baos.close();
1588: dbFile.setFileContent(baos.toByteArray());
1589: dbFile.setContentType("argun/diagram");
1590:
1591: baos = new ByteArrayOutputStream();
1592: ObjectOutputStream oos = new ObjectOutputStream(baos);
1593: oos.writeObject(dbFile);
1594: oos.close();
1595: baos.close();
1596:
1597: HttpClient client = new HttpClient();
1598: PostMethod method = new PostMethod(uploadUrl);
1599: method.setRequestEntity(new ByteArrayRequestEntity(baos
1600: .toByteArray()));
1601: if (cookie != null) {
1602: method.setRequestHeader("Cookie", cookie);
1603: }
1604: int status = client.executeMethod(method);
1605: if (status != HttpStatus.SC_OK) {
1606: String errorMessage = "HTTP Error: " + status + "\n"
1607: + method.getResponseBodyAsString();
1608: JOptionPane.showMessageDialog(this ,
1609: "Could not save diagram:\n" + errorMessage,
1610: "Error", JOptionPane.ERROR_MESSAGE);
1611: statusMessage("Save failed: " + errorMessage);
1612: setEnabled(false);
1613: }
1614: statusMessage("Last saved on " + new Date());
1615: setEnabled(true);
1616: if (showSavedDialog) {
1617: JOptionPane.showMessageDialog(this , "Diagram saved",
1618: "Save", JOptionPane.INFORMATION_MESSAGE);
1619: }
1620: } catch (Exception ex) {
1621: JOptionPane.showMessageDialog(this ,
1622: "Could not save diagram:\n" + ex, "Error",
1623: JOptionPane.ERROR_MESSAGE);
1624: ex.printStackTrace();
1625: statusMessage("Save failed: " + ex);
1626: }
1627: }
1628:
1629: private void saveAndClose() {
1630: save(false);
1631: if (exitUrl != null) {
1632: try {
1633: getAppletContext().showDocument(new URL(exitUrl));
1634: } catch (MalformedURLException e) {
1635: statusMessage("Could not navigate to exit URL: "
1636: + e.toString());
1637: e.printStackTrace();
1638: }
1639: }
1640: }
1641:
1642: public String getFileName() {
1643: return dbFile == null ? null : dbFile.getName();
1644: }
1645:
1646: public String getFileDescription() {
1647: return dbFile == null ? null : dbFile.getDescription();
1648: }
1649:
1650: public void setFileName(String text) {
1651: if (dbFile != null) {
1652: dbFile.setName(text);
1653: }
1654: if (diagramFile != null) {
1655: diagramFile.setFilename(text);
1656: }
1657:
1658: }
1659:
1660: public void setFileDescription(String text) {
1661: if (dbFile != null) {
1662: dbFile.setDescription(text);
1663: }
1664: }
1665:
1666: private static void info(String message) {
1667: System.out.println(Thread.currentThread().getName()
1668: + " [Diagram editor] " + message);
1669: }
1670:
1671: }
|