blob: ebacd0855e8ac08ad6e967d48036e278f162cded [file] [log] [blame]
/*********************************************************************
* Copyright (c) 2005, 2019 SAP SE
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* Contributors:
* SAP SE - initial API, implementation and documentation
* mwenz - Bug 355347 - Remove setters of Graphiti's Font Interface
* cbrand - Bug 376585 - Clean-up deprecations in Graphiti
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
package org.eclipse.graphiti.examples.common.pattern.grid;
import java.util.List;
import org.eclipse.graphiti.features.IReason;
import org.eclipse.graphiti.features.context.IAddContext;
import org.eclipse.graphiti.features.context.ILayoutContext;
import org.eclipse.graphiti.features.context.IUpdateContext;
import org.eclipse.graphiti.features.impl.Reason;
import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
import org.eclipse.graphiti.mm.algorithms.Polyline;
import org.eclipse.graphiti.mm.algorithms.Rectangle;
import org.eclipse.graphiti.mm.algorithms.Text;
import org.eclipse.graphiti.mm.algorithms.styles.Orientation;
import org.eclipse.graphiti.mm.algorithms.styles.Point;
import org.eclipse.graphiti.mm.pictograms.ContainerShape;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.mm.pictograms.PictogramLink;
import org.eclipse.graphiti.mm.pictograms.Shape;
import org.eclipse.graphiti.pattern.AbstractPattern;
import org.eclipse.graphiti.pattern.mapping.ILinkCreationInfo;
import org.eclipse.graphiti.pattern.mapping.IStructureMapping;
import org.eclipse.graphiti.pattern.mapping.IStructureMappingGrid;
import org.eclipse.graphiti.pattern.mapping.IStructureMappingMulti;
import org.eclipse.graphiti.pattern.mapping.data.IDataMapping;
import org.eclipse.graphiti.pattern.mapping.data.ITextDataMapping;
import org.eclipse.graphiti.services.Graphiti;
import org.eclipse.graphiti.services.IGaService;
/**
* The Class GridPattern.
*/
public abstract class GridPattern extends AbstractPattern {
private IStructureMappingGrid gridMapping;
/**
* Instantiates a new grid pattern.
*/
public GridPattern() {
super(new DefaultGridPatternConfiguration());
}
@Override
final public PictogramElement add(IAddContext context) {
Object mainBusinessObject = context.getNewObject();
ContainerShape parentContainerShape = context.getTargetContainer();
// CONTAINER SHAPE WITH RECTANGLE
ContainerShape containerShape = Graphiti.getPeCreateService().createContainerShape(parentContainerShape, true);
// check whether valid size is available, e.g. if called from the create
// feature
int minWidth = getConfiguration().getMinimumWidth();
int minHeight = getConfiguration().getMinimumHeight();
int width = context.getWidth() <= minWidth ? minWidth : context.getWidth();
int height = context.getHeight() <= minHeight ? minHeight : context.getHeight();
IGaService gaService = Graphiti.getGaService();
{
// create and set graphics algorithm
Rectangle rectangle = gaService.createRectangle(containerShape);
rectangle.setForeground(manageColor(getConfiguration().getForegroundColor()));
rectangle.setBackground(manageColor(getConfiguration().getBackgroundColor()));
rectangle.setLineWidth(getConfiguration().getLineWidth() * 2);
rectangle.setTransparency(getConfiguration().getTransparency());
gaService.setLocationAndSize(rectangle, context.getX(), context.getY(), width, height);
// create link and wire it
link(containerShape, mainBusinessObject);
// create cell separators
createSeparators(rectangle, getColumnCount() - 1, getConfiguration().getMajorUnitX());
createSeparators(rectangle, getRowCount() - 1, getConfiguration().getMajorUnitY());
}
updatePictogramElement(containerShape);
return containerShape;
}
private void createSeparators(GraphicsAlgorithm parentGraphicsAlgorithm, int separators, int majorUnit) {
for (int i = 1; i <= separators; i++) {
Polyline polyline = Graphiti.getGaCreateService().createPolyline(parentGraphicsAlgorithm, new int[] { 0, 0, 0, 0 });
polyline.setForeground(manageColor(getConfiguration().getForegroundColor()));
int lineWidth;
if (majorUnit > 0 && (i % majorUnit) == 0) {
lineWidth = getConfiguration().getMajorUnitSeparatorWidth();
} else {
lineWidth = getConfiguration().getMinorSeparatorWidth();
}
polyline.setLineWidth(lineWidth);
}
}
@Override
public boolean layout(ILayoutContext context) {
boolean ret = true;
IGaService gaService = Graphiti.getGaService();
ContainerShape containerShape = (ContainerShape) context.getPictogramElement();
int cellWidth = containerShape.getGraphicsAlgorithm().getWidth() / getColumnCount();
int cellHeight = containerShape.getGraphicsAlgorithm().getHeight() / getRowCount();
List<Shape> children = containerShape.getChildren();
for (int x = 0; x < getColumnCount(); x++) {
for (int y = 0; y < getRowCount(); y++) {
int cellIndex = (y * getColumnCount()) + x;
PictogramElement cellShape = children.get(cellIndex);
int xPos = x * cellWidth;
int yPos = y * cellHeight;
gaService.setLocationAndSize(cellShape.getGraphicsAlgorithm(), xPos, yPos, cellWidth, cellHeight);
}
}
List<GraphicsAlgorithm> polylines = containerShape.getGraphicsAlgorithm().getGraphicsAlgorithmChildren();
int xSep = getColumnCount() - 1;
int currentX = cellWidth;
for (int i = 0; i < xSep; i++) {
List<Point> points = ((Polyline) polylines.get(i)).getPoints();
points.set(0, gaService.createPoint(currentX, 0));
points.set(1, gaService.createPoint(currentX, containerShape.getGraphicsAlgorithm().getHeight()));
currentX += cellWidth;
}
int currentY = cellHeight;
for (int i = xSep; i < polylines.size(); i++) {
List<Point> points = ((Polyline) polylines.get(i)).getPoints();
points.set(0, gaService.createPoint(0, currentY));
points.set(1, gaService.createPoint(containerShape.getGraphicsAlgorithm().getWidth(), currentY));
currentY += cellHeight;
}
return ret;
}
@Override
public boolean update(IUpdateContext context) {
boolean ret = false;
PictogramElement pe = context.getPictogramElement();
if (isPatternRoot(pe)) {
ret = updateRoot((ContainerShape) pe);
} else {
ContainerShape rootContainer = getPatternRoot(pe);
if (rootContainer != null) {
ret = updateRoot(rootContainer);
}
}
return ret;
}
@Override
public IReason updateNeeded(IUpdateContext context) {
// check only if the given pictogram element is the outer container
// shape
PictogramElement pe = context.getPictogramElement();
if (isPatternRoot(pe)) {
ContainerShape containerShape = (ContainerShape) pe;
List<Shape> shapes = containerShape.getChildren();
// check cell structure
int cells = getRowCount() * getColumnCount();
if (cells != shapes.size()) {
return Reason.createTrueReason();
}
// check cell content
for (Shape shape : shapes) {
IReason ret = updateCellNeeded(shape, getGridMapping());
if (ret.toBoolean()) {
return ret;
}
}
}
return Reason.createFalseReason();
}
/**
* Creates the grid mapping.
*
* @return the i structure mapping grid
*/
abstract protected IStructureMappingGrid createGridMapping();
private IStructureMappingGrid getGridMapping() {
if (gridMapping == null) {
gridMapping = createGridMapping();
}
return gridMapping;
}
private ContainerShape getPatternRoot(PictogramElement pe) {
ContainerShape ret = null;
// Check that a pictogram element was provided and that it is alive
if (pe != null && pe.eResource() != null) {
int i = 0;
do {
if (isPatternRoot(pe)) {
ret = (ContainerShape) pe;
} else if (pe instanceof Shape) {
pe = ((Shape) pe).getContainer();
}
i++;
} while (ret == null && i < 2);
}
return ret;
}
@Override
protected boolean isPatternControlled(PictogramElement pictogramElement) {
ContainerShape patternRoot = getPatternRoot(pictogramElement);
return patternRoot != null;
}
@Override
protected boolean isPatternRoot(PictogramElement pe) {
boolean ret = false;
// Check if not null, of right instance and alive
if (pe instanceof ContainerShape && pe.eResource() != null) {
GraphicsAlgorithm ga = pe.getGraphicsAlgorithm();
if (ga instanceof Rectangle) {
Object bo = getBusinessObjectForPictogramElement(pe);
ret = isMainBusinessObjectApplicable(bo);
}
}
return ret;
}
private IReason updateCellNeeded(Shape shape, IStructureMappingMulti mapping) {
IReason ret = Reason.createFalseReason();
PictogramLink linkForPictogramElement = Graphiti.getLinkService().getLinkForPictogramElement(shape);
if (linkForPictogramElement != null) {
Text textGa = (Text) shape.getGraphicsAlgorithm();
boolean booleanRet = !getText(mapping, linkForPictogramElement).equals(textGa.getValue());
if (booleanRet) {
ret = Reason.createTrueReason(mapping.getDataMapping().getUpdateWarning(linkForPictogramElement));
}
}
return ret;
}
private boolean updateRoot(ContainerShape outerContainerShape) {
boolean ret = false;
Object mainBusinessObject = getBusinessObjectForPictogramElement(outerContainerShape);
// check cell structure
int cells = getRowCount() * getColumnCount();
if (cells != outerContainerShape.getChildren().size()) {
// remove old cells
Object[] a = outerContainerShape.getChildren().toArray();
for (int i = 0; i < a.length; i++) {
Graphiti.getPeService().deletePictogramElement((PictogramElement) a[i]);
}
// create new cells
createCellShapes(outerContainerShape, getGridMapping().getLinkCreationInfos(mainBusinessObject));
}
updateCellShapes(outerContainerShape);
return ret;
}
private void updateCellShapes(ContainerShape outerContainerShape) {
List<Shape> shapes = outerContainerShape.getChildren();
for (Shape shape : shapes) {
PictogramLink linkForPictogramElement = Graphiti.getLinkService().getLinkForPictogramElement(shape);
if (linkForPictogramElement != null) {
Text textGa = (Text) shape.getGraphicsAlgorithm();
textGa.setValue(getText(getGridMapping(), linkForPictogramElement));
}
}
}
private void createCellShapes(ContainerShape containerShape, List<ILinkCreationInfo> linkCreationInfos) {
IGaService gaService = Graphiti.getGaService();
// add text shapes for each BO
for (ILinkCreationInfo linkCreationInfo : linkCreationInfos) {
Shape shape = Graphiti.getPeCreateService().createShape(containerShape, false);
Text text = Graphiti.getGaService().createText(shape);
text.setForeground(manageColor(getConfiguration().getTextColor()));
text.setHorizontalAlignment(Orientation.ALIGNMENT_CENTER);
text.setVerticalAlignment(Orientation.ALIGNMENT_CENTER);
text.setFont(gaService.manageFont(getDiagram(), "Baskerville Old Face", 10, true, false)); //$NON-NLS-1$
// create link and wire it
link(shape, linkCreationInfo.getBusinessObjects());
String linkProperty = linkCreationInfo.getProperty();
if (linkProperty != null) {
Graphiti.getLinkService().setLinkProperty(shape, linkProperty);
}
}
}
/**
* Gets the configuration.
*
* @return the configuration
*/
protected IGridPatternConfiguration getConfiguration() {
return (IGridPatternConfiguration) getPatternConfiguration();
}
private int getColumnCount() {
return getGridMapping().getColumns();
}
private int getRowCount() {
return getGridMapping().getRows();
}
/**
* Gets the text.
*
* @param structureMapping
* the structure mapping
* @param link
* the pictogram link
* @return the text
*/
protected String getText(IStructureMapping structureMapping, PictogramLink link) {
String ret = null;
IDataMapping dm = structureMapping.getDataMapping();
if (dm instanceof ITextDataMapping) {
ret = ((ITextDataMapping) dm).getText(link);
}
return ret;
}
}