com.objetdirect.gwt.umlapi.client.artifacts.object.ObjectRelationLinkArtifact.java Source code

Java tutorial

Introduction

Here is the source code for com.objetdirect.gwt.umlapi.client.artifacts.object.ObjectRelationLinkArtifact.java

Source

/*
 * This file is part of the GWTUML project and was written by Mounier Florian <mounier-dot-florian.at.gmail'dot'com> for Objet Direct
 * <http://wwww.objetdirect.com>
 * 
 * Copyright  2009 Objet Direct Contact: gwtuml@googlegroups.com
 * 
 * GWTUML is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * GWTUML is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License along with GWTUML. If not, see <http://www.gnu.org/licenses/>.
 */
package com.objetdirect.gwt.umlapi.client.artifacts.object;

import static com.objetdirect.gwt.umlapi.client.gfx.GfxStyle.SOLID;
import static com.objetdirect.gwt.umlapi.client.umlcomponents.umlrelation.LinkAdornment.NONE;
import static com.objetdirect.gwt.umlapi.client.umlcomponents.umlrelation.LinkAdornment.WIRE_ARROW;
import static com.objetdirect.gwt.umlapi.client.umlcomponents.umlrelation.LinkKind.OBJECT_RELATION;

import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.ui.MenuBar;
import com.objetdirect.gwt.umlapi.client.artifacts.RelationLinkArtifact;
import com.objetdirect.gwt.umlapi.client.contextMenu.MenuBarAndTitle;
import com.objetdirect.gwt.umlapi.client.editors.EditorPart;
import com.objetdirect.gwt.umlapi.client.editors.SimpleFieldEditor;
import com.objetdirect.gwt.umlapi.client.engine.GeometryManager;
import com.objetdirect.gwt.umlapi.client.engine.Point;
import com.objetdirect.gwt.umlapi.client.gfx.GfxManager;
import com.objetdirect.gwt.umlapi.client.gfx.GfxObject;
import com.objetdirect.gwt.umlapi.client.helpers.OptionsManager;
import com.objetdirect.gwt.umlapi.client.helpers.ThemeManager;
import com.objetdirect.gwt.umlapi.client.umlCanvas.UMLCanvas;
import com.objetdirect.gwt.umlapi.client.umlcomponents.umlrelation.LinkAdornment;
import com.objetdirect.gwt.umlapi.client.umlcomponents.umlrelation.ObjectRelation;

/**
 * This object represents any relation artifact between two objects
 * 
 * @author Florian Mounier (mounier-dot-florian.at.gmail'dot'com)
 */
public class ObjectRelationLinkArtifact extends RelationLinkArtifact {

    private transient GfxObject arrowVirtualGroup;
    private transient GfxObject line;
    private transient GfxObject textVirtualGroup;
    private transient GfxObject leftRoleGfxObject;
    private transient GfxObject rightRoleGfxObject;

    /**
     * /!\ Don't forget to increment the serialVersionUID if you change any of the fields above /!\
     */
    private static final long serialVersionUID = 1L;

    private ObjectArtifact leftObjectArtifact;
    private ObjectArtifact rightObjectArtifact;
    private ObjectRelation objectRelation;

    private int current_delta;

    /** Default constructor ONLY for gwt-rpc serialization. */
    @Deprecated
    @SuppressWarnings("unused")
    private ObjectRelationLinkArtifact() {
    }

    /**
     * Constructor of {@link ObjectRelationLinkArtifact}
     * 
     * @param canvas
     *            Where the gfxObjects are displayed
     * @param id
     *            The artifacts's id
     * @param left
     *            The left {@link ObjectArtifact} of the relation
     * @param right
     *            The right {@link ObjectArtifact} of the relation
     */
    public ObjectRelationLinkArtifact(final UMLCanvas canvas, int id, final ObjectArtifact left,
            final ObjectArtifact right) {
        super(canvas, id, left, right, OBJECT_RELATION);

        if (right == left) { // An object instance can't reference itself
            throw new IllegalArgumentException();
        }

        leftObjectArtifact = left;
        left.addDependency(this, right);
        rightObjectArtifact = right;
        right.addDependency(this, left);

        objectRelation = new ObjectRelation(leftObjectArtifact.toUMLComponent(),
                rightObjectArtifact.toUMLComponent());
    }

    @Override
    public void edit(final GfxObject editedGfxObject) {
        if (editedGfxObject == null) {
            return;
        }

        if (editedGfxObject.equals(leftRoleGfxObject)) {
            edit(editedGfxObject, buildLeftRoleEditorPart());
        } else if (editedGfxObject.equals(rightRoleGfxObject)) {
            edit(editedGfxObject, buildRightRoleEditorPart());
        }
    }

    private void edit(final GfxObject editedGfxObject, EditorPart editorPart) {

        final SimpleFieldEditor editor = new SimpleFieldEditor(canvas, this, editorPart);
        editor.startEdition(editorPart.getText(), editedGfxObject.getLocation().getX(),
                editedGfxObject.getLocation().getY(), GfxManager.getPlatform().getTextWidthFor(editedGfxObject)
                        + RECTANGLE_RIGHT_PADDING + RECTANGLE_LEFT_PADDING,
                false, true);
    }

    public EditorPart buildLeftRoleEditorPart() {
        EditorPart editor = new EditorPart() {
            @Override
            public void setText(String newText) {
                objectRelation.setLeftRole(newText);
            }

            @Override
            public String getText() {
                return objectRelation.getLeftRole();
            }
        };

        return editor;
    }

    public EditorPart buildRightRoleEditorPart() {
        EditorPart editor = new EditorPart() {
            @Override
            public void setText(String newText) {
                objectRelation.setRightRole(newText);
            }

            @Override
            public String getText() {
                return objectRelation.getRightRole();
            }
        };

        return editor;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.objetdirect.gwt.umlapi.client.artifacts.links.RelationshipLinkArtifact #getRightMenu()
     */
    @Override
    public MenuBarAndTitle getRightMenu() {
        final MenuBarAndTitle rightMenu = new MenuBarAndTitle();
        String leftClassName = objectRelation.getLeftObject().getClassName();
        String rightClassName = objectRelation.getRightObject().getClassName();

        String menuName = leftClassName + " - " + rightClassName;
        rightMenu.setName(menuName);

        final MenuBar leftSide = buildRoleMenuBar(leftRoleGfxObject, buildLeftRoleEditorPart());
        final MenuBar rightSide = buildRoleMenuBar(rightRoleGfxObject, buildRightRoleEditorPart());

        rightMenu.addItem(leftClassName + " side", leftSide);
        rightMenu.addItem(rightClassName + " side", rightSide);
        return rightMenu;
    }

    /**
     * Build a menubar to edit or create a role. The role is the name for a side of the relation.
     * 
     * If the role is empty, the menu bar is just a "create" item.
     * 
     * Else, the menu has two items : edit or delete.
     * 
     * @param gfxObjectToEdit
     *            If the role is empty, null Else the gfxObject which display the role. Ie leftRoleGfxObject or
     *            rightRoleGfxObject.
     * @param editorPart
     *            The editor the edit the role
     * @return
     */
    private MenuBar buildRoleMenuBar(final GfxObject gfxObjectToEdit, final EditorPart editorPart) {
        MenuBar menu = new MenuBar(true);

        if (editorPart.getText().isEmpty()) {
            Command createCommand = new Command() {
                @Override
                public void execute() {
                    editorPart.setText("Role");
                    rebuildGfxObject();
                }
            };

            menu.addItem("Role", createCommand);
        } else {
            Command editCommand = new Command() {
                @Override
                public void execute() {
                    edit(gfxObjectToEdit);
                }
            };

            Command deleteCommand = new Command() {
                @Override
                public void execute() {
                    editorPart.setText("");
                    rebuildGfxObject();
                }
            };

            menu.addItem("Edit", editCommand);
            menu.addItem("Delete", deleteCommand);
        }

        return menu;
    }

    /**
     * Getter for the right {@link ObjectArtifact} of this relation
     * 
     * @return the right {@link ObjectArtifact} of this relation
     */
    public ObjectArtifact getRightObjectArtifact() {
        return rightObjectArtifact;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.objetdirect.gwt.umlapi.client.artifacts.LinkArtifact#removeCreatedDependency()
     */
    @Override
    public void removeCreatedDependency() {
        leftObjectArtifact.removeDependency(this);
        rightObjectArtifact.removeDependency(this);
    }

    /**
     * @return the relation in the metamodel level.
     */
    public ObjectRelation toUMLComponent() {
        return objectRelation;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.objetdirect.gwt.umlapi.client.artifacts.UMLArtifact#toURL()
     */
    @Override
    // TODO Should use the metamodel objectRelation, but need changes on the UrlParser.
    public String toURL() {
        return "ObjectRelationLink$<" + leftObjectArtifact.getId() + ">!<" + rightObjectArtifact.getId() + ">!"
                + relation.getLinkKind().getName() + "!" + relation.getName() + "!"
                + relation.getLinkStyle().getName() + "!" + relation.getLeftAdornment().getName() + "!"
                + relation.getRightAdornment().getName();
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.objetdirect.gwt.umlapi.client.artifacts.UMLArtifact#unselect()
     */
    @Override
    public void unselect() {
        super.unselect();
        line.setStroke(ThemeManager.getTheme().getObjectRelationForegroundColor(), 1);
        arrowVirtualGroup.setStroke(ThemeManager.getTheme().getObjectRelationForegroundColor(), 1);
    }

    Anchor getAnchorType(final ObjectArtifact objectArtifact, final Point point) {
        if (point.getX() == objectArtifact.getLocation().getX()) {
            return Anchor.LEFT;
        } else if (point.getY() == objectArtifact.getLocation().getY()) {
            return Anchor.TOP;
        } else if (point.getX() == objectArtifact.getLocation().getX() + objectArtifact.getWidth()) {
            return Anchor.RIGHT;
        } else if (point.getY() == objectArtifact.getLocation().getY() + objectArtifact.getHeight()) {
            return Anchor.BOTTOM;
        }
        return Anchor.UNKNOWN;
    }

    int getTextX(final GfxObject text, final boolean isLeft) {

        Point relative_point1 = leftPoint;
        Point relative_point2 = rightPoint;
        final int textWidth = GfxManager.getPlatform().getTextWidthFor(text);
        if (!isLeft) {
            relative_point1 = rightPoint;
            relative_point2 = leftPoint;
        }
        switch (this.getAnchorType(isLeft ? leftObjectArtifact : rightObjectArtifact, relative_point1)) {
        case LEFT:
            return relative_point1.getX() - textWidth - RECTANGLE_LEFT_PADDING;
        case RIGHT:
            return relative_point1.getX() + RECTANGLE_RIGHT_PADDING;
        case TOP:
        case BOTTOM:
        case UNKNOWN:
            if (relative_point1.getX() < relative_point2.getX()) {
                return relative_point1.getX() - textWidth - RECTANGLE_LEFT_PADDING;
            }
            return relative_point1.getX() + RECTANGLE_RIGHT_PADDING;
        }
        return 0;
    }

    int getTextY(final GfxObject text, final boolean isLeft) {
        Point relative_point1 = leftPoint;
        Point relative_point2 = rightPoint;
        if (!isLeft) {
            relative_point1 = rightPoint;
            relative_point2 = leftPoint;
        }
        final int textHeight = GfxManager.getPlatform().getTextHeightFor(text);
        final int delta = current_delta;
        current_delta += 8; // TODO : Fix Height
        switch (this.getAnchorType(isLeft ? leftObjectArtifact : rightObjectArtifact, relative_point1)) {
        case LEFT:
        case RIGHT:
            if (relative_point1.getY() > relative_point2.getY()) {
                return relative_point1.getY() + RECTANGLE_BOTTOM_PADDING + delta;
            }
            return relative_point1.getY() - textHeight - RECTANGLE_TOP_PADDING - delta;
        case TOP:
            return relative_point1.getY() - textHeight - RECTANGLE_TOP_PADDING - delta;
        case BOTTOM:
        case UNKNOWN:
            return relative_point1.getY() + RECTANGLE_BOTTOM_PADDING + delta;
        }
        return 0;
    }

    @Override
    protected void buildGfxObject() {
        line = this.buildLine();

        line.setStroke(ThemeManager.getTheme().getClassRelationForegroundColor(), 1);
        line.setStrokeStyle(SOLID);
        line.addToVirtualGroup(gfxObject);

        // Making arrows group :
        arrowVirtualGroup = GfxManager.getPlatform().buildVirtualGroup();
        arrowVirtualGroup.addToVirtualGroup(gfxObject);
        final GfxObject leftArrow = GeometryManager.getPlatform().buildAdornment(leftPoint, leftDirectionPoint,
                getAdornmentFromNavigability(true));
        final GfxObject rightArrow = GeometryManager.getPlatform().buildAdornment(rightPoint, rightDirectionPoint,
                getAdornmentFromNavigability(false));

        if (leftArrow != null) {
            leftArrow.addToVirtualGroup(arrowVirtualGroup);
        }
        if (rightArrow != null) {
            rightArrow.addToVirtualGroup(arrowVirtualGroup);
        }
        // Making the text group :
        textVirtualGroup = GfxManager.getPlatform().buildVirtualGroup();
        textVirtualGroup.addToVirtualGroup(gfxObject);

        current_delta = 0;
        if (!objectRelation.getLeftRole().equals("")) {
            leftRoleGfxObject = this.createText(objectRelation.getLeftRole(), true);
            leftRoleGfxObject.addToVirtualGroup(textVirtualGroup);
        }
        current_delta = 0;
        if (!objectRelation.getRightRole().equals("")) {
            rightRoleGfxObject = this.createText(objectRelation.getRightRole(), false);
            rightRoleGfxObject.addToVirtualGroup(textVirtualGroup);
        }

        gfxObject.moveToBack();
    }

    private LinkAdornment getAdornmentFromNavigability(boolean isLeft) {
        if (isLeft) {
            if (objectRelation.isLeftNavigable()) {
                return WIRE_ARROW;
            }
            return NONE;
        }
        if (objectRelation.isRightNavigable()) {
            return WIRE_ARROW;
        }
        return NONE;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.objetdirect.gwt.umlapi.client.artifacts.UMLArtifact#select()
     */
    @Override
    protected void select() {
        super.select();
        line.setStroke(ThemeManager.getTheme().getObjectRelationHighlightedForegroundColor(), 2);
        arrowVirtualGroup.setStroke(ThemeManager.getTheme().getObjectRelationHighlightedForegroundColor(), 2);
    }

    private GfxObject createText(final String text, boolean isLeft) {

        final GfxObject textGfxObject = GfxManager.getPlatform().buildText(text, Point.getOrigin());
        textGfxObject.setFont(OptionsManager.getSmallFont());
        textGfxObject.setStroke(ThemeManager.getTheme().getObjectRelationBackgroundColor(), 0);
        textGfxObject.setFillColor(ThemeManager.getTheme().getObjectRelationForegroundColor());
        textGfxObject
                .translate(new Point(this.getTextX(textGfxObject, isLeft), this.getTextY(textGfxObject, isLeft)));

        return textGfxObject;
    }

    @Override
    public void setUpAfterDeserialization() {
        buildGfxObject();
    }

    /**
     * @param rightRole
     */
    public void setRightRole(String rightRole) {
        objectRelation.setRightRole(rightRole);
    }
}