All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.primefaces.component.diagram.DiagramRenderer Maven / Gradle / Ivy

There is a newer version: 14.0.0
Show newest version
/*
 * The MIT License
 *
 * Copyright (c) 2009-2023 PrimeTek Informatics
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.primefaces.component.diagram;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;

import org.primefaces.model.diagram.Connection;
import org.primefaces.model.diagram.DiagramModel;
import org.primefaces.model.diagram.Element;
import org.primefaces.model.diagram.connector.Connector;
import org.primefaces.model.diagram.endpoint.EndPoint;
import org.primefaces.model.diagram.overlay.Overlay;
import org.primefaces.renderkit.CoreRenderer;
import org.primefaces.util.ComponentUtils;
import org.primefaces.util.SharedStringBuilder;
import org.primefaces.util.WidgetBuilder;

public class DiagramRenderer extends CoreRenderer {

    private static final String SB_DIAGRAM = CoreRenderer.class.getName() + "#diagram";

    @Override
    public void decode(FacesContext context, UIComponent component) {
        Diagram diagram = (Diagram) component;

        if (diagram.isConnectRequest(context)) {
            decodeNewConnection(context, diagram);
        }
        else if (diagram.isDisconnectRequest(context)) {
            decodeDisconnection(context, diagram);
        }
        else if (diagram.isConnectionChangeRequest(context)) {
            decodeConnectionChange(context, diagram);
        }
        else if (diagram.isPositionChangeRequest(context)) {
            decodePositionChange(context, diagram);
        }

        decodeBehaviors(context, component);
    }

    private void decodeNewConnection(FacesContext context, Diagram diagram) {
        //no need to decode since state is synced in previous connection move request
        if (context.getExternalContext().getRequestParameterMap().containsKey(diagram.getClientId(context) + "_connectionChanged")) {
            return;
        }

        DiagramModel model = (DiagramModel) diagram.getValue();
        if (model != null) {
            Connection connection = decodeConnection(context, diagram, true);
            if (connection != null) {
                model.connect(connection);
            }
        }
    }

    private void decodeDisconnection(FacesContext context, Diagram diagram) {
        DiagramModel model = (DiagramModel) diagram.getValue();
        if (model != null) {
            Connection connection = decodeConnection(context, diagram, false);
            if (connection != null) {
                model.disconnect(connection);
            }
        }
    }

    private void decodeConnectionChange(FacesContext context, Diagram diagram) {
        DiagramModel model = (DiagramModel) diagram.getValue();
        if (model != null) {
            Map params = context.getExternalContext().getRequestParameterMap();
            String clientId = diagram.getClientId(context);

            Element originalSourceElement = model.findElement(params.get(clientId + "_originalSourceId"));
            Element newSourceElement = model.findElement(params.get(clientId + "_newSourceId"));
            Element originalTargetElement = model.findElement(params.get(clientId + "_originalTargetId"));
            Element newTargetElement = model.findElement(params.get(clientId + "_newTargetId"));
            EndPoint originalSourceEndPoint = model.findEndPoint(originalSourceElement, params.get(clientId + "_originalSourceEndPointId"));
            EndPoint newSourceEndPoint = model.findEndPoint(newSourceElement, params.get(clientId + "_newSourceEndPointId"));
            EndPoint originalTargetEndPoint = model.findEndPoint(originalTargetElement, params.get(clientId + "_originalTargetEndPointId"));
            EndPoint newTargetEndPoint = model.findEndPoint(newTargetElement, params.get(clientId + "_newTargetEndPointId"));

            model.disconnect(findConnection(model, originalSourceEndPoint, originalTargetEndPoint));
            model.connect(new Connection(newSourceEndPoint, newTargetEndPoint));
        }
    }

    private void decodePositionChange(FacesContext context, Diagram diagram) {
        DiagramModel model = (DiagramModel) diagram.getValue();
        if (model != null) {
            Map params = context.getExternalContext().getRequestParameterMap();
            String clientId = diagram.getClientId(context);

            Element element = model.findElement(params.get(clientId + "_elementId"));
            String[] position = params.get(clientId + "_position").split(",");

            if (element != null) {
                element.setX(position[0] + "px");
                element.setY(position[1] + "px");
            }
        }
    }

    private Connection decodeConnection(FacesContext context, Diagram diagram, boolean createNew) {
        DiagramModel model = (DiagramModel) diagram.getValue();
        Connection connection = null;

        if (model != null) {
            Map params = context.getExternalContext().getRequestParameterMap();
            String clientId = diagram.getClientId(context);

            Element sourceElement = model.findElement(params.get(clientId + "_sourceId"));
            Element targetElement = model.findElement(params.get(clientId + "_targetId"));
            EndPoint sourceEndPoint = model.findEndPoint(sourceElement, params.get(clientId + "_sourceEndPointId"));
            EndPoint targetEndPoint = model.findEndPoint(targetElement, params.get(clientId + "_targetEndPointId"));

            if (createNew) {
                connection = new Connection(sourceEndPoint, targetEndPoint);
            }
            else {
                connection = findConnection(model, sourceEndPoint, targetEndPoint);
            }
        }

        return connection;
    }

    private Connection findConnection(DiagramModel model, EndPoint source, EndPoint target) {
        Connection connection = null;

        if (model != null) {
            List connections = model.getConnections();
            if (connections != null) {
                int connectionsSize = connections.size();
                for (int i = 0; i < connectionsSize; i++) {
                    Connection conn = connections.get(i);

                    if (conn.getSource().equals(source) && conn.getTarget().equals(target)) {
                        connection = conn;
                        break;
                    }
                }
            }
        }

        return connection;
    }

    @Override
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
        Diagram diagram = (Diagram) component;

        encodeMarkup(context, diagram);
        encodeScript(context, diagram);
    }

    protected void encodeScript(FacesContext context, Diagram diagram) throws IOException {
        String clientId = diagram.getClientId(context);
        WidgetBuilder wb = getWidgetBuilder(context);
        wb.init("Diagram", diagram);

        DiagramModel model = (DiagramModel) diagram.getValue();
        if (model != null) {
            encodeDefaults(wb, model);

            encodeEndPoints(wb, model, clientId);
            encodeConnections(wb, model);
        }

        encodeClientBehaviors(context, diagram);

        wb.finish();
    }

    protected void encodeDefaults(WidgetBuilder wb, DiagramModel model) throws IOException {
        StringBuilder sb = SharedStringBuilder.get(SB_DIAGRAM);

        Connector defaultConnector = model.getDefaultConnector();
        if (defaultConnector != null) {
            String paintStyle = defaultConnector.getPaintStyle();
            String hoverPaintStyle = defaultConnector.getHoverPaintStyle();

            wb.append(",defaultConnector:").append(defaultConnector.toJS(sb));
            wb.append(",containment:").append("" + model.isContainment());

            if (paintStyle != null) {
                wb.append(",paintStyle:").append(paintStyle);
            }
            if (hoverPaintStyle != null) {
                wb.append(",hoverPaintStyle:").append(hoverPaintStyle);
            }

            sb.setLength(0);
        }

        encodeOverlays(wb, model.getDefaultConnectionOverlays(), "connectionOverlays");

        if (!model.isConnectionsDetachable()) {
            wb.append(",connectionsDetachable:false");
        }

        int maxConnections = model.getMaxConnections();
        if (maxConnections != 0) {
            wb.append(",maxConnections:").append(maxConnections);
        }
    }

    protected void encodeEndPoints(WidgetBuilder wb, DiagramModel model, String clientId) throws IOException {
        List elements = model.getElements();
        if (elements != null && !elements.isEmpty()) {
            int elementsSize = elements.size();

            wb.append(",endPoints:[");
            for (int i = 0; i < elementsSize; i++) {
                Element element = elements.get(i);
                String elementClientId = clientId + "-" + element.getId();
                List endPoints = element.getEndPoints();

                if (endPoints != null && !endPoints.isEmpty()) {
                    int endPointsSize = endPoints.size();

                    for (int j = 0; j < endPointsSize; j++) {
                        EndPoint endPoint = endPoints.get(j);
                        encodeEndPoint(wb, endPoint, elementClientId);

                        if (j < (endPointsSize - 1)) {
                            wb.append(",");
                        }
                    }
                }

                if (i < (elementsSize - 1)) {
                    wb.append(",");
                }
            }
            wb.append("]");
        }
    }

    protected void encodeEndPoint(WidgetBuilder wb, EndPoint endPoint, String elementClientId) throws IOException {
        String type = endPoint.getType();
        StringBuilder sb = SharedStringBuilder.get(SB_DIAGRAM);
        String styleClass = endPoint.getStyleClass();
        String hoverStyleClass = endPoint.getHoverStyleClass();
        String style = endPoint.getStyle();
        String hoverStyle = endPoint.getHoverStyle();
        int maxConnections = endPoint.getMaxConnections();
        String scope = endPoint.getScope();

        wb.append("{uuid:'").append(endPoint.getId()).append("'")
                .append(",element:'").append(elementClientId).append("'")
                .append(",anchor:'").append(endPoint.getAnchor().toString()).append("'");

        if (maxConnections != 1) {
            wb.append(",maxConnections:").append(maxConnections);
        }
        if (style != null) {
            wb.append(",paintStyle:").append(style);
        }
        if (hoverStyle != null) {
            wb.append(",hoverPaintStyle:").append(hoverStyle);
        }
        if (endPoint.isSource()) {
            wb.append(",isSource:true");
        }
        if (endPoint.isTarget()) {
            wb.append(",isTarget:true");
        }
        if (styleClass != null) {
            wb.append(",cssClass:'").append(styleClass).append("'");
        }
        if (hoverStyleClass != null) {
            wb.append(",hoverClass:'").append(hoverStyleClass).append("'");
        }
        if (scope != null) {
            wb.append(",scope:'").append(scope).append("'");
        }

        if (type != null) {
            wb.append(",endpoint:").append(endPoint.toJS(sb));
        }

        encodeOverlays(wb, endPoint.getOverlays(), "overlays");

        wb.append("}");
    }

    protected void encodeConnections(WidgetBuilder wb, DiagramModel model) throws IOException {
        List connections = model.getConnections();
        if (connections != null && !connections.isEmpty()) {
            int connectionsSize = connections.size();

            wb.append(",connections:[");
            for (int i = 0; i < connectionsSize; i++) {
                Connection connection = connections.get(i);
                StringBuilder sb = SharedStringBuilder.get(SB_DIAGRAM);
                Connector connector = connection.getConnector();
                List overlays = connection.getOverlays();

                wb.append("{uuids:['").append(connection.getSource().getId()).append("'")
                        .append(",'").append(connection.getTarget().getId()).append("']");

                if (connector != null && connector.getType() != null) {
                    wb.append(",connector:").append(connector.toJS(sb));

                    String paintStyle = connector.getPaintStyle();
                    String hoverPaintStyle = connector.getHoverPaintStyle();

                    if (paintStyle != null) {
                        wb.append(",paintStyle:").append(paintStyle);
                    }
                    if (hoverPaintStyle != null) {
                        wb.append(",hoverPaintStyle:").append(hoverPaintStyle);
                    }
                }

                if (!connection.isDetachable()) {
                    wb.append(",detachable:false");
                }

                encodeOverlays(wb, overlays, "overlays");

                wb.append("}");

                if (i < (connectionsSize - 1)) {
                    wb.append(",");
                }

            }
            wb.append("]");
        }
    }

    protected void encodeOverlays(WidgetBuilder wb, List overlays, String propertyName) throws IOException {
        StringBuilder sb = SharedStringBuilder.get(SB_DIAGRAM);

        if (overlays != null && !overlays.isEmpty()) {
            int overlaysSize = overlays.size();

            wb.append(",").append(propertyName).append(":[");
            for (int j = 0; j < overlaysSize; j++) {
                Overlay overlay = overlays.get(j);
                sb.setLength(0);

                wb.append(overlay.toJS(sb));

                if (j < (overlaysSize - 1)) {
                    wb.append(",");
                }
            }
            wb.append("]");
        }
    }

    protected void encodeMarkup(FacesContext context, Diagram diagram) throws IOException {
        ResponseWriter writer = context.getResponseWriter();
        DiagramModel model = (DiagramModel) diagram.getValue();
        String clientId = diagram.getClientId(context);
        String style = diagram.getStyle();
        String styleClass = diagram.getStyleClass();
        styleClass = (styleClass == null) ? Diagram.CONTAINER_CLASS : Diagram.CONTAINER_CLASS + " " + styleClass;
        UIComponent elementFacet = diagram.getFacet("element");
        Map requestMap = context.getExternalContext().getRequestMap();
        String var = diagram.getVar();

        writer.startElement("div", diagram);
        writer.writeAttribute("id", diagram.getClientId(context), null);
        writer.writeAttribute("class", styleClass, null);
        if (style != null) {
            writer.writeAttribute("style", style, null);
        }

        if (model != null) {
            List elements = model.getElements();
            if (elements != null && !elements.isEmpty()) {
                for (int i = 0; i < elements.size(); i++) {
                    Element element = elements.get(i);
                    String elementClass = element.getStyleClass();
                    elementClass = (elementClass == null) ? Diagram.ELEMENT_CLASS : Diagram.ELEMENT_CLASS + " " + elementClass;
                    if (element.isDraggable()) {
                        elementClass = elementClass + " " + Diagram.DRAGGABLE_ELEMENT_CLASS;
                    }
                    Object data = element.getData();
                    String x = element.getX();
                    String y = element.getY();
                    String coords = "left:" + x + ";top:" + y;
                    String title = element.getTitle();

                    writer.startElement("div", null);
                    writer.writeAttribute("id", clientId + "-" + element.getId(), null);
                    writer.writeAttribute("class", elementClass, null);
                    writer.writeAttribute("style", coords, null);
                    writer.writeAttribute("data-tooltip", title, null);

                    if (var != null) {
                        requestMap.put(var, data);
                    }

                    if (ComponentUtils.shouldRenderFacet(elementFacet)) {
                        elementFacet.encodeAll(context);
                    }
                    else if (data != null) {
                        writer.writeText(data, null);
                    }
                    writer.endElement("div");
                }
            }

            if (var != null) {
                requestMap.remove(var);
            }
        }

        writer.endElement("div");
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy