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

jlibs.nblr.editor.actions.NodePopupProvider Maven / Gradle / Ivy

/**
 * Copyright 2015 Santhosh Kumar Tekuri
 *
 * The JLibs authors license this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

package jlibs.nblr.editor.actions;

import jlibs.nblr.editor.RuleScene;
import jlibs.nblr.rules.Edge;
import jlibs.nblr.rules.Node;
import org.netbeans.api.visual.action.PopupMenuProvider;
import org.netbeans.api.visual.widget.Widget;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.HashSet;
import java.util.Set;

/**
 * @author Santhosh Kumar T
 */
public class NodePopupProvider implements PopupMenuProvider{
    private RuleScene scene;

    public NodePopupProvider(RuleScene scene){
        this.scene = scene;
    }

    private Node node;
    public JPopupMenu getPopupMenu(Widget widget, Point localLocation){
        node = (Node)scene.findObject(widget);

        JMenu insertNodeMenu = new JMenu("Insert Node");
        insertNodeMenu.add(new InsertBeforeNodeAction(scene, node));
        insertNodeMenu.add(new InsertAfterNodeAction(scene, node));
        insertNodeMenu.add(new AddBranchAction(scene, node));

        JMenu insertStringMenu = new JMenu("Insert String");
        insertStringMenu.add(new InsertStringBeforeNodeAction(scene, node));
        insertStringMenu.add(new InsertStringAfterNodeAction(scene, node));
        insertStringMenu.add(new AddStringBranchAction(scene, node));

        JMenu actionMenu = new JMenu("Set Action");
        actionMenu.add(new AssignBufferAction(scene, node));
        actionMenu.add(new AssignPublishAction(scene, node));
        actionMenu.add(new AssignEventAction(scene, node));
        actionMenu.add(new AssignErrorAction(scene, node));
        actionMenu.addSeparator();
        actionMenu.add(new ClearAction(scene, node));

        JPopupMenu popup = new JPopupMenu();
        popup.add(insertNodeMenu);
        popup.add(insertStringMenu);
        popup.add(actionMenu);
        popup.add(setNameAction);
        popup.addSeparator();
        popup.add(new ChoiceAction("Delete",
            deleteSourceAction,
            deleteSinkAction,
            deleteNodeWithEmptyOutgoingEdges,
            deleteNodeWithEmptyIncomingEdges
        ));

        return popup;
    }
    
    private Action setNameAction = new AbstractAction("Set Name..."){
        @Override
        public void actionPerformed(ActionEvent ae){
            String name = JOptionPane.showInputDialog(scene.getView(), "Name", node.name);
            if(name!=null){
                Node clashingNode = scene.getRule().nodeWithName(name);
                if(clashingNode!=null && clashingNode!=node){
                    JOptionPane.showMessageDialog(scene.getView(), "Node with name '"+name+"' already exists");
                    return;
                }
                node.name = name.isEmpty() ? null : name;
                scene.layout(node);
            }
        }
    };

    private Action deleteSourceAction = new AbstractAction(){
        @Override
        public void actionPerformed(ActionEvent ae){
            scene.getRule().node = newSource();
            for(Edge edge: node.outgoing())
                edge.delete();
            scene.refresh();
        }

        private Node newSource(){
            if(scene.getRule().node==node){
                Set targets = new HashSet();
                for(Edge outgoing: node.outgoing){
                    if(!outgoing.loop())
                        targets.add(outgoing.target);
                }

                Node newSource = null;
                for(Node target: targets){
                    boolean canBeSource = true;
                    for(Edge incoming: target.incoming){
                        if(!incoming.loop() && incoming.source!=node){
                            canBeSource = false;
                            break;
                        }
                    }
                    if(canBeSource){
                        if(newSource!=null) // multiple sources
                            return null;
                        newSource = target;
                    }
                }
                return newSource;
            }else
                return null;
        }

        @Override
        public boolean isEnabled(){
            return newSource()!=null;
        }
    };
    
    private Action deleteSinkAction = new AbstractAction(){
        @Override
        public void actionPerformed(ActionEvent ae){
            for(Edge edge: node.incoming())
                edge.delete();
            scene.refresh();
        }

        @Override
        public boolean isEnabled(){
            if(scene.getRule().node==node)
                return false;

            for(Edge edge: node.outgoing){
                if(!edge.loop())
                    return false;
            }
            return true;
        }
    };

    private Action deleteNodeWithEmptyOutgoingEdges = new AbstractAction(){
        @Override
        public void actionPerformed(ActionEvent ae){
            for(Edge incoming: node.incoming()){
                if(!incoming.loop()){
                    for(Edge outgoing: node.outgoing()){
                        if(!outgoing.loop()){
                            Edge newEdge = incoming.source.addEdgeTo(outgoing.target);
                            newEdge.matcher = incoming.matcher;
                            newEdge.ruleTarget = incoming.ruleTarget;
                            incoming.delete();
                        }
                    }
                }
            }
            for(Edge outgoing: node.outgoing()){
                if(!outgoing.loop())
                    outgoing.setTarget(null);
            }
            scene.refresh();
        }

        @Override
        public boolean isEnabled(){
            if(scene.getRule().node==node)
                return false;
            
            for(Edge edge: node.outgoing){
                if(!edge.loop()){
                    if(edge.matcher!=null || edge.ruleTarget!=null)
                        return false;
                }
            }
            return true;
        }
    };
    
    private Action deleteNodeWithEmptyIncomingEdges = new AbstractAction(){
        @Override
        public void actionPerformed(ActionEvent ae){
            for(Edge outgoing: node.outgoing()){
                if(!outgoing.loop()){
                    for(Edge incoming: node.incoming()){
                        if(!incoming.loop()){
                            Edge newEdge = outgoing.target.addEdgeFrom(incoming.source);
                            newEdge.matcher = outgoing.matcher;
                            newEdge.ruleTarget = outgoing.ruleTarget;
                            outgoing.delete();
                        }
                    }
                }
            }
            for(Edge incoming: node.incoming()){
                if(!incoming.loop())
                    incoming.setSource(null);
            }
            scene.refresh();
        }

        @Override
        public boolean isEnabled(){
            if(scene.getRule().node==node)
                return false;
            
            for(Edge edge: node.incoming){
                if(!edge.loop()){
                    if(edge.matcher!=null || edge.ruleTarget!=null)
                        return false;
                }
            }
            return true;
        }
    };
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy