how to validate incoming edge towards source from target in mxgraph
Asked Answered
M

1

7

Hi i'm facing a problem with respect to edge validation

Note: any approach is most welcomed but should solve the problem

below is my requirement

  1. source can have any following Action_* like this

Source -> Action_1 -> Action_2

  1. i want to avoid any Action_* coming against/towards source

Source -> Action_1 <- Action_2

Below Gif shows my requirement

enter image description here

in above gif the text appears is This one i want to avoid

here is what i have tried

graph.multiplicities.push(new mxMultiplicity(
   true, 'Source', null, null, 1, 1, ['Action_1','Action_2'],
   'Source can have 1 Action and from there it can be multiple',
   null));

graph.multiplicities.push(new mxMultiplicity(
    false, 'Source', null, null, 0, 0, null,
   'Source Must Have No Incoming Edge',
   null)); // Type does not matter

here is demo what i have referred https://jgraph.github.io/mxgraph/javascript/examples/validation.html and here is its code https://github.com/jgraph/mxgraph/blob/master/javascript/examples/validation.html

Here is the Multiplicity params

mxMultiplicity(source,type,attr,value,min,max,validNeighbors,countError,typeError,validNeighborsAllowed) 

Here is its documentation : https://jgraph.github.io/mxgraph/docs/js-api/files/view/mxMultiplicity-js.html

Here is what I have tried

<!--
  Copyright (c) 2006-2013, JGraph Ltd
  
  Validation example for mxGraph. This example demonstrates using
  multiplicities for automatically validating a graph.
-->
<html>
<head>
    <title>Validation example for mxGraph</title>

    <!-- Sets the basepath for the library if not in same directory -->
   <script type="text/javascript">
            mxBasePath = 'https://jgraph.github.io/mxgraph/javascript/src';
        </script>
        <script src="https://jgraph.github.io/mxgraph/javascript/src/js/mxClient.js"></script>

    <!-- Example code -->
    <script type="text/javascript">
        // Program starts here. Creates a sample graph in the
        // DOM node with the specified ID. This function is invoked
        // from the onLoad event handler of the document (see below).
         graph = {};
        function main(container)
        {
            // Checks if the browser is supported
            if (!mxClient.isBrowserSupported())
            {
                // Displays an error message if the browser is not supported.
                mxUtils.error('Browser is not supported!', 200, false);
            }
            else
            {
                var xmlDocument = mxUtils.createXmlDocument();
                var sourceNode = xmlDocument.createElement('Source');
                var action_1 = xmlDocument.createElement('Action_1');
                var action_2 = xmlDocument.createElement('Action_2');
                
                // Creates the graph inside the given container
                graph = new mxGraph(container);
                graph.setConnectable(true);
                graph.setTooltips(true);
                graph.setAllowDanglingEdges(false);
                graph.setMultigraph(false);


  /** mxMultiplicity accepts the following below params (source,type,attr,value,min,max,validNeighbors,countError,typeError,validNeighborsAllowed)
                
  */

    
                graph.multiplicities.push(new mxMultiplicity(
                   true, 'Source', null, null, 1, 1, ['Action_1','Action_2'],
                   'Source can have 1 Action and from there it can be multiple',
                   null));

                graph.multiplicities.push(new mxMultiplicity(
                   false, 'Source', null, null, 0, 0, null,
                   'Source Must Have No Incoming Edge',
                   null)); // Type does not matter

                
                // Enables rubberband selection
                new mxRubberband(graph);


                // Removes cells when [DELETE] is pressed
                var keyHandler = new mxKeyHandler(graph);
                keyHandler.bindKey(46, function(evt)
                {
                    if (graph.isEnabled())
                    {
                        graph.removeCells();
                    }
                });

                // Installs automatic validation (use editor.validation = true
                // if you are using an mxEditor instance)
                var listener = function(sender, evt)
                {
                    graph.validateGraph();
                };
                
                graph.getModel().addListener(mxEvent.CHANGE,listener);
                
                // Gets the default parent for inserting new cells. This
                // is normally the first child of the root (ie. layer 0).
                var parent = graph.getDefaultParent();
                                
                // Adds cells to the model in a single step
                graph.getModel().beginUpdate();
                try
                {
                    var v1 = graph.insertVertex(parent, null, sourceNode, 20, 20, 80, 30);
                    var v2 = graph.insertVertex(parent, null, action_1, 200, 20, 80, 30);
                    var v5 = graph.insertVertex(parent, null, action_2, 200, 120, 80, 30);
    
                }
                finally
                {
                    // Updates the display
                    graph.getModel().endUpdate();
                }
            }
        };
    </script>
</head>

<!-- Page passes the container for the graph to the program -->
<body onload="main(document.getElementById('graphContainer'))">

    <!-- Creates a container for the graph with a grid wallpaper -->
    <div id="graphContainer"
        style="position:relative;overflow:hidden;width:321px;height:281px;background:url('editors/images/grid.gif');cursor:default;">
    </div>
</body>
</html>
Moorfowl answered 3/7, 2021 at 10:41 Comment(2)
Any kind of solution(s) most welcomed, but it should solve the problemMoorfowl
Despite of more than 100 views I'm not getting answer. Please let me know if anyone don't understand the questionMoorfowl
E
2

I understood that problem is that you was facing, you want to validation the graph that:

  • From source vertex (source node), you can make any edge to any another vertex (node)
  • If any target vertex(Action 1) already connected to source vertex, If any other target vertex (Action 2 3 4 5) want connect to source vertex, it must be connected to those which already connect to source vertex instead.
  • Any vertex connected to source could not be target

Unfortunately, your current way is using mxMultiplicity cannot solve the problem because several reason(s):

  • It only support 1-depth level neighbor (which mean you can specific rules for it's neighbor, not neighbor of neighbor
  • It only support built-in validation, no support custom validation

So the solution is:

  • Try to validation graph model yourself using graph model at change listener instead using mxMultiplicity and update the array of mxMultiplicity every time you create a edge
  • Using another library for graph visualize
  • No create edge if any condition is not satisfied (my way) (actually, it doesn't pop up a warning message)

Here is my template for you. You can check this out about it documentation here (connection handler)

mxConnectionHandlerInsertEdge = mxConnectionHandler.prototype.insertEdge;
mxConnectionHandler.prototype.insertEdge = function (parent, id, value, source, target, style) {
var check
//    check if you are allow to insert edge

if (check) {
    return mxConnectionHandlerInsertEdge.apply(this, arguments);
}
return null

};

<html>

<head>
<title>Validation example for mxGraph</title>

<!-- Sets the basepath for the library if not in same directory -->
<script type="text/javascript">
    mxBasePath = 'https://jgraph.github.io/mxgraph/javascript/src';
</script>
<script src="https://jgraph.github.io/mxgraph/javascript/src/js/mxClient.js"></script>

<!-- Example code -->
<script type="text/javascript">
    // Program starts here. Creates a sample graph in the
    // DOM node with the specified ID. This function is invoked
    // from the onLoad event handler of the document (see below).
    graph = {};
    function main(container) {
        // Checks if the browser is supported
        if (!mxClient.isBrowserSupported()) {
            // Displays an error message if the browser is not supported.
            mxUtils.error('Browser is not supported!', 200, false);
        }
        else {
            var xmlDocument = mxUtils.createXmlDocument();
            var sourceNode = xmlDocument.createElement('Source');
            var action_1 = xmlDocument.createElement('Action_1');
            var action_2 = xmlDocument.createElement('Action_2');
            var action_3 = xmlDocument.createElement('Action_3');
            var action_4 = xmlDocument.createElement('Action_4');

            // Creates the graph inside the given container
            graph = new mxGraph(container);
            graph.setConnectable(true);
            graph.setTooltips(true);
            graph.setAllowDanglingEdges(false);
            graph.setMultigraph(false);


            /** mxMultiplicity accepts the following below params (source,type,attr,value,min,max,validNeighbors,countError,typeError,validNeighborsAllowed)
                          
            */


            graph.multiplicities.push(new mxMultiplicity(
                true, 'Source', null, null, 1, 1, ['Action_1', 'Action_2'],
                'Source can have 1 Action and from there it can be multiple',
                null));

            graph.multiplicities.push(new mxMultiplicity(
                false, 'Source', null, null, 0, 0, null,
                'Source Must Have No Incoming Edge',
                null)); // Type does not matter


            // Enables rubberband selection
            new mxRubberband(graph);


            // Removes cells when [DELETE] is pressed
            var keyHandler = new mxKeyHandler(graph);
            keyHandler.bindKey(46, function (evt) {
                if (graph.isEnabled()) {
                    graph.removeCells();
                }
            });

            // Installs automatic validation (use editor.validation = true
            // if you are using an mxEditor instance)
            var listener = function (sender, evt) {
                graph.validateGraph();
                // sender is the graph model

            };
            // complete the validation function here
            mxConnectionHandlerInsertEdge = mxConnectionHandler.prototype.insertEdge;
            mxConnectionHandler.prototype.insertEdge = function (parent, id, value, source, target, style) {
                var check
                //    check if you are allow to insert edge

                if (check) {
                    return mxConnectionHandlerInsertEdge.apply(this, arguments);
                }
                return null

            };


            graph.getModel().addListener(mxEvent.CHANGE, listener);

            // Gets the default parent for inserting new cells. This
            // is normally the first child of the root (ie. layer 0).
            var parent = graph.getDefaultParent();

            // Adds cells to the model in a single step
            graph.getModel().beginUpdate();
            try {
                var v1 = graph.insertVertex(parent, null, sourceNode, 20, 20, 80, 30);
                var v2 = graph.insertVertex(parent, null, action_1, 200, 20, 80, 30);
                var v5 = graph.insertVertex(parent, null, action_2, 200, 120, 80, 30);
                var v6 = graph.insertVertex(parent, null, action_3, 400, 120, 80, 30);
                var v7 = graph.insertVertex(parent, null, action_4, 600, 120, 80, 30);
            }
            finally {
                // Updates the display
                graph.getModel().endUpdate();
            }
        }
    };
</script>
</head>

<!-- Page passes the container for the graph to the program -->

<body onload="main(document.getElementById('graphContainer'))">

<!-- Creates a container for the graph with a grid wallpaper -->
<div id="graphContainer"
    style="position:relative;overflow:hidden;width:1000px;height:1000px;background:url('editors/images/grid.gif');cursor:default;">
</div>
</body>

</html>
Equidistant answered 12/7, 2021 at 13:13 Comment(7)
that's great you understood my problem, i'm not able to write the working code through your reference. can you please produce a snippet here (can be done by clicking <> icon)Moorfowl
still i have bounty grace period of 20hrs i will definitely award bountyMoorfowl
I updated the snippet. Recently, I am interest in graph theory but I am busy :DCautery
Great !!! but not able to connect any of them expected is from source to any actions .Moorfowl
You should spend time for better validation function. It just a template for meCautery
After spending time I found solution with your template, thanks alot !!Moorfowl
I am happy that you figured out the solution. You're welcome.Cautery

© 2022 - 2024 — McMap. All rights reserved.