/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.dm.view.erdiagram;
import java.awt.Color;
import java.util.logging.Logger;
import org.jdom2.Verifier;
import org.openflexo.fge.ConnectorGraphicalRepresentation;
import org.openflexo.fge.Drawing;
import org.openflexo.fge.GraphicalRepresentation;
import org.openflexo.fge.ShapeGraphicalRepresentation;
import org.openflexo.fge.connectors.Connector.ConnectorType;
import org.openflexo.fge.connectors.ConnectorSymbol.EndSymbolType;
import org.openflexo.fge.connectors.rpc.RectPolylinConnector;
import org.openflexo.fge.connectors.rpc.RectPolylinConnector.RectPolylinAdjustability;
import org.openflexo.fge.connectors.rpc.RectPolylinConnector.RectPolylinConstraints;
import org.openflexo.fge.controller.CustomClickControlAction;
import org.openflexo.fge.controller.DrawingController;
import org.openflexo.fge.controller.MouseClickControl;
import org.openflexo.fge.geom.FGERectPolylin;
import org.openflexo.fge.graphics.ForegroundStyle;
import org.openflexo.fge.graphics.TextStyle;
import org.openflexo.foundation.dm.DMEntity;
import org.openflexo.toolbox.ToolBox;
public class EntitySpecializationGR extends ConnectorGraphicalRepresentation<EntitySpecialization> implements ERDiagramConstants {
@SuppressWarnings("unused")
private static final Logger logger = Logger.getLogger(EntitySpecializationGR.class.getPackage().getName());
private TextStyle propertyNameStyle;
private ForegroundStyle foreground;
public EntitySpecializationGR(EntitySpecialization anEntitySpecialization, Drawing<?> aDrawing) {
super(ConnectorType.RECT_POLYLIN, (ShapeGraphicalRepresentation<?>) aDrawing.getGraphicalRepresentation(anEntitySpecialization
.getSpecializedEntity()), (ShapeGraphicalRepresentation<?>) aDrawing.getGraphicalRepresentation(anEntitySpecialization
.getParentEntity()), anEntitySpecialization, aDrawing);
// setText(getRole().getName());
updateStyles();
propertyNameStyle = TextStyle.makeTextStyle(Color.DARK_GRAY, ATTRIBUTE_FONT);
setTextStyle(propertyNameStyle);
getConnector().setIsRounded(true);
getConnector().setRectPolylinConstraints(RectPolylinConstraints.VERTICAL_LAYOUT);
getConnector().setAdjustability(RectPolylinAdjustability.FULLY_ADJUSTABLE);
getConnector().setStraightLineWhenPossible(true);
getConnector().setPixelOverlap(30);
setEndSymbol(EndSymbolType.PLAIN_ARROW);
setEndSymbolSize(15);
if (getSpecializedEntity().hasGraphicalPropertyForKey(getStoredPolylinKey())) {
ensurePolylinConverterIsRegistered();
polylinIWillBeAdustedTo = (FGERectPolylin) getSpecializedEntity()._graphicalPropertyForKey(getStoredPolylinKey());
getConnector().setWasManuallyAdjusted(true);
}
setForeground(ForegroundStyle.makeStyle(Color.DARK_GRAY, 1.6f));
setIsFocusable(true);
addToMouseClickControls(new ResetLayout(), true);
addToMouseClickControls(new ERDiagramController.ShowContextualMenuControl());
if (ToolBox.getPLATFORM() != ToolBox.MACOS) {
addToMouseClickControls(new ERDiagramController.ShowContextualMenuControl(true));
}
// addToMouseDragControls(new DrawRoleSpecializationControl());
}
@Override
public RectPolylinConnector getConnector() {
return (RectPolylinConnector) super.getConnector();
}
private void updateStyles() {
/*foreground = ForegroundStyle.makeStyle(getEntity().getColor());
foreground.setLineWidth(2);
background = BackgroundStyle.makeColorGradientBackground(getRole().getColor(), Color.WHITE, ColorGradientDirection.SOUTH_WEST_NORTH_EAST);
setForeground(foreground);
setBackground(background);*/
}
@Override
public ERDiagramRepresentation getDrawing() {
return (ERDiagramRepresentation) super.getDrawing();
}
public EntitySpecialization getEntitySpecialization() {
return getDrawable();
}
public DMEntity getSpecializedEntity() {
return getEntitySpecialization().getSpecializedEntity();
}
public class ResetLayout extends MouseClickControl {
public ResetLayout() {
super("ResetLayout", MouseButton.LEFT, 2, new CustomClickControlAction() {
@Override
public boolean handleClick(GraphicalRepresentation<?> graphicalRepresentation, DrawingController<?> controller,
java.awt.event.MouseEvent event) {
// logger.info("Reset layout for edge");
resetLayout();
return true;
}
}, false, false, false, false);
}
}
public void resetLayout() {
getConnector().setWasManuallyAdjusted(false);
}
private FGERectPolylin polylinIWillBeAdustedTo;
@Override
public void notifyObjectHierarchyHasBeenUpdated() {
super.notifyObjectHierarchyHasBeenUpdated();
if (polylinIWillBeAdustedTo != null && !getSpecializedEntity().isDeleted()) {
getConnector().manuallySetPolylin(polylinIWillBeAdustedTo);
polylinIWillBeAdustedTo = null;
refreshConnector();
}
}
@Override
public void refreshConnector() {
if (!isConnectorConsistent()) {
// Dont' go further for connector that are inconsistent (this may happen
// during big model restructurations (for example during a multiple delete)
return;
}
super.refreshConnector();
storeNewLayout();
}
@Override
public void notifyConnectorChanged() {
super.notifyConnectorChanged();
storeNewLayout();
}
private static String escapeStringForXML(String s) {
if (s == null) {
return null;
}
StringBuffer sb = new StringBuffer();
int n = s.length();
for (int i = 0; i < n; i++) {
char c = s.charAt(i);
if (Verifier.isXMLNameCharacter(c)) {
sb.append(c);
} else {
sb.append("_");
}
}
return sb.toString();
}
private String getContext() {
return "inheritance_" + escapeStringForXML(getEntitySpecialization().getSpecialization().getStringRepresentation()) + "_diagram_"
+ getDrawing().getDiagram().getFlexoID();
}
private String getStoredPolylinKey() {
return "polylin_" + getContext();
}
private void storeNewLayout() {
if (isRegistered()) {
ensurePolylinConverterIsRegistered();
if (getConnector().getWasManuallyAdjusted() && getConnector()._getPolylin() != null) {
if (polylinIWillBeAdustedTo == null) { // Store this layout only in no other layout is beeing registering
// logger.info("Post "+getPostCondition().getName()+": store new layout to "+connector._getPolylin());
getSpecializedEntity()._setGraphicalPropertyForKey(getConnector()._getPolylin(), getStoredPolylinKey());
}
} else {
if (getSpecializedEntity().hasGraphicalPropertyForKey(getStoredPolylinKey())) {
getSpecializedEntity()._removeGraphicalPropertyWithKey(getStoredPolylinKey());
}
}
}
}
private boolean isPolylinConverterRegistered = false;
private void ensurePolylinConverterIsRegistered() {
if (!isPolylinConverterRegistered) {
if (getSpecializedEntity().getProject().getStringEncoder()._converterForClass(FGERectPolylin.class) == null) {
getSpecializedEntity().getProject().getStringEncoder()._addConverter(RECT_POLYLIN_CONVERTER);
}
isPolylinConverterRegistered = true;
}
}
@Override
public String getText() {
return getEntitySpecialization().getLabel();
}
@Override
public double getAbsoluteTextX() {
if (!getSpecializedEntity().hasLabelLocationForContext(getContext())) {
getSpecializedEntity().getLabelX(getContext(), getDefaultLabelX());
}
return getSpecializedEntity().getLabelX(getContext());
}
@Override
public void setAbsoluteTextXNoNotification(double posX) {
getSpecializedEntity().setLabelX(posX, getContext());
}
@Override
public double getAbsoluteTextY() {
if (!getSpecializedEntity().hasLabelLocationForContext(getContext())) {
getSpecializedEntity().getLabelY(getContext(), getDefaultLabelY());
}
return getSpecializedEntity().getLabelY(getContext());
}
@Override
public void setAbsoluteTextYNoNotification(double posY) {
getSpecializedEntity().setLabelY(posY, getContext());
}
// Override to implement defaut automatic layout
public double getDefaultLabelX() {
return Math.sin(getConnector().getMiddleSymbolAngle()) * 10;
}
// Override to implement defaut automatic layout
public double getDefaultLabelY() {
return Math.cos(getConnector().getMiddleSymbolAngle()) * 10;
}
}