Package com.cburch.logisim.gui.log

Source Code of com.cburch.logisim.gui.log.ComponentSelector$MyCellRenderer

/* Copyright (c) 2010, Carl Burch. License information is located in the
* com.cburch.logisim.Main source code and at www.cburch.com/logisim/. */

package com.cburch.logisim.gui.log;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;

import javax.swing.JLabel;
import javax.swing.JTree;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

import com.cburch.logisim.circuit.CircuitEvent;
import com.cburch.logisim.circuit.CircuitListener;
import com.cburch.logisim.circuit.CircuitState;
import com.cburch.logisim.circuit.SubcircuitFactory;
import com.cburch.logisim.comp.Component;
import com.cburch.logisim.instance.StdAttr;

@SuppressWarnings("serial")
class ComponentSelector extends JTree {
    private static class CompareByName implements Comparator<Object> {
        @Override
        public int compare(Object a, Object b) {
            return a.toString().compareToIgnoreCase(b.toString());
        }
    }

    private class CircuitNode implements TreeNode, CircuitListener,
            Comparator<Component> {
        private CircuitNode parent;
        private CircuitState circuitState;
        private Component subcircComp;
        private ArrayList<TreeNode> children;

        public CircuitNode(CircuitNode parent, CircuitState circuitState,
                Component subcircComp) {
            this.parent = parent;
            this.circuitState = circuitState;
            this.subcircComp = subcircComp;
            this.children = new ArrayList<TreeNode>();
            circuitState.getCircuit().addCircuitListener(this);
            computeChildren();
        }

        @Override
        public String toString() {
            if (subcircComp != null) {
                String label = subcircComp.getAttributeSet().getValue(StdAttr.LABEL);
                if (label != null && !label.equals("")) {
                    return label;
                }
            }
            String ret = circuitState.getCircuit().getName();
            if (subcircComp != null) {
                ret += subcircComp.getLocation();
            }
            return ret;
        }

        @Override
        public TreeNode getChildAt(int index) {
            return children.get(index);
        }

        @Override
        public int getChildCount() {
            return children.size();
        }

        @Override
        public TreeNode getParent() {
            return parent;
        }

        @Override
        public int getIndex(TreeNode node) {
            return children.indexOf(node);
        }

        @Override
        public boolean getAllowsChildren() {
            return true;
        }

        @Override
        public boolean isLeaf() {
            return false;
        }

        @Override
        public Enumeration<TreeNode> children() {
            return Collections.enumeration(children);
        }

        @Override
        public void circuitChanged(CircuitEvent event) {
            int action = event.getAction();
            DefaultTreeModel model = (DefaultTreeModel) getModel();
            if (action == CircuitEvent.ACTION_SET_NAME) {
                model.nodeChanged(this);
            } else {
                if (computeChildren()) {
                    model.nodeStructureChanged(this);
                } else if (action == CircuitEvent.ACTION_INVALIDATE) {
                    Object o = event.getData();
                    for (int i = children.size() - 1; i >= 0; i--) {
                        Object o2 = children.get(i);
                        if (o2 instanceof ComponentNode) {
                            ComponentNode n = (ComponentNode) o2;
                            if (n.comp == o) {
                                int[] changed = { i };
                                children.remove(i);
                                model.nodesWereRemoved(this, changed, new Object[] { n });
                                children.add(i, new ComponentNode(this, n.comp));
                                model.nodesWereInserted(this, changed);
                            }
                        }
                    }
                }
            }
        }

        // returns true if changed
        private boolean computeChildren() {
            ArrayList<TreeNode> newChildren = new ArrayList<TreeNode>();
            ArrayList<Component> subcircs = new ArrayList<Component>();
            for (Component comp : circuitState.getCircuit().getNonWires()) {
                if (comp.getFactory() instanceof SubcircuitFactory) {
                    subcircs.add(comp);
                } else {
                    Object o = comp.getFeature(Loggable.class);
                    if (o != null) {
                        ComponentNode toAdd = null;
                        for (TreeNode o2 : children) {
                            if (o2 instanceof ComponentNode) {
                                ComponentNode n = (ComponentNode) o2;
                                if (n.comp == comp) {
                                    { toAdd = n;
                                }
break; }
                            }
                        }
                        if (toAdd == null) {
                            toAdd = new ComponentNode(this, comp);
                        }

                        newChildren.add(toAdd);
                    }
                }
            }
            Collections.sort(newChildren, new CompareByName());
            Collections.sort(subcircs, this);
            for (Component comp : subcircs) {
                SubcircuitFactory factory = (SubcircuitFactory) comp.getFactory();
                CircuitState state = factory.getSubstate(circuitState, comp);
                CircuitNode toAdd = null;
                for (TreeNode o : children) {
                    if (o instanceof CircuitNode) {
                        CircuitNode n = (CircuitNode) o;
                        if (n.circuitState == state) {
                            { toAdd = n;
                        }
break; }
                    }
                }
                if (toAdd == null) {
                    toAdd = new CircuitNode(this, state, comp);
                }
                newChildren.add(toAdd);
            }

            if (!children.equals(newChildren)) {
                children = newChildren;
                return true;
            } else {
                return false;
            }
        }

        @Override
        public int compare(Component a, Component b) {
            if (a != b) {
                String aName = a.getFactory().getDisplayName();
                String bName = b.getFactory().getDisplayName();
                int ret = aName.compareToIgnoreCase(bName);
                if (ret != 0) {
                    return ret;
                }

            }
            return a.getLocation().toString().compareTo(b.getLocation().toString());
        }
    }

    private class ComponentNode implements TreeNode {
        private CircuitNode parent;
        private Component comp;
        private OptionNode[] opts;

        public ComponentNode(CircuitNode parent, Component comp) {
            this.parent = parent;
            this.comp = comp;
            this.opts = null;

            Loggable log = (Loggable) comp.getFeature(Loggable.class);
            if (log != null) {
                Object[] opts = log.getLogOptions(parent.circuitState);
                if (opts != null && opts.length > 0) {
                    this.opts = new OptionNode[opts.length];
                    for (int i = 0; i < opts.length; i++) {
                        this.opts[i] = new OptionNode(this, opts[i]);
                    }
                }
            }
        }

        @Override
        public String toString() {
            Loggable log = (Loggable) comp.getFeature(Loggable.class);
            if (log != null) {
                String ret = log.getLogName(null);
                if (ret != null && !ret.equals("")) {
                    return ret;
                }

            }
            return comp.getFactory().getDisplayName() + " " + comp.getLocation();
        }

        @Override
        public TreeNode getChildAt(int index) {
            return opts[index];
        }

        @Override
        public int getChildCount() {
            return opts == null ? 0 : opts.length;
        }

        @Override
        public TreeNode getParent() {
            return parent;
        }

        @Override
        public int getIndex(TreeNode n) {
            for (int i = 0; i < opts.length; i++) {
                if (opts[i] == n) {
                    return i;
                }

            }
            return -1;
        }

        @Override
        public boolean getAllowsChildren() {
            return false;
        }

        @Override
        public boolean isLeaf() {
            return opts == null || opts.length == 0;
        }

        @Override
        public Enumeration<OptionNode> children() {
            return Collections.enumeration(Arrays.asList(opts));
        }
    }

    private class OptionNode implements TreeNode {
        private ComponentNode parent;
        private Object option;

        public OptionNode(ComponentNode parent, Object option) {
            this.parent = parent;
            this.option = option;
        }

        @Override
        public String toString() {
            return option.toString();
        }

        @Override
        public TreeNode getChildAt(int arg0) {
            return null;
        }

        @Override
        public int getChildCount() {
            return 0;
        }

        @Override
        public TreeNode getParent() {
            return parent;
        }

        @Override
        public int getIndex(TreeNode n) {
            return -1;
        }

        @Override
        public boolean getAllowsChildren() {
            return false;
        }

        @Override
        public boolean isLeaf() {
            return true;
        }

        @Override
        public Enumeration<?> children() {
            return Collections.enumeration(Collections.emptySet());
        }
    }

    private class MyCellRenderer extends DefaultTreeCellRenderer {
        @Override
        public java.awt.Component getTreeCellRendererComponent(JTree tree,
                Object value, boolean selected, boolean expanded,
                boolean leaf, int row, boolean hasFocus) {
            java.awt.Component ret = super.getTreeCellRendererComponent(tree,
                    value, selected, expanded, leaf, row, hasFocus);
            if (ret instanceof JLabel && value instanceof ComponentNode) {
                ComponentNode node = (ComponentNode) value;
                ComponentIcon icon = new ComponentIcon(node.comp);
                if (node.getChildCount() > 0) {
                    icon.setTriangleState(expanded
                            ? ComponentIcon.TRIANGLE_OPEN : ComponentIcon.TRIANGLE_CLOSED);
                }
                ((JLabel) ret).setIcon(icon);
            }
            return ret;
        }
    }

    private Model logModel;

    public ComponentSelector(Model logModel) {
        DefaultTreeModel model = new DefaultTreeModel(null);
        model.setAsksAllowsChildren(false);
        setModel(model);
        setRootVisible(false);
        setLogModel(logModel);
        setCellRenderer(new MyCellRenderer());
    }

    public void setLogModel(Model value) {
        this.logModel = value;

        DefaultTreeModel model = (DefaultTreeModel) getModel();
        CircuitNode curRoot = (CircuitNode) model.getRoot();
        CircuitState state = logModel == null ? null : logModel.getCircuitState();
        if (state == null) {
            if (curRoot != null) {
                model.setRoot(null);
            }

            return;
        }
        if (curRoot == null || curRoot.circuitState != state) {
            curRoot = new CircuitNode(null, state, null);
            model.setRoot(curRoot);
        }
    }

    public List<SelectionItem> getSelectedItems() {
        TreePath[] sel = getSelectionPaths();
        if (sel == null || sel.length == 0) {
            return Collections.emptyList();
        }


        ArrayList<SelectionItem> ret = new ArrayList<SelectionItem>();
        for (int i = 0; i < sel.length; i++) {
            TreePath path = sel[i];
            Object last = path.getLastPathComponent();
            ComponentNode n = null;
            Object opt = null;
            if (last instanceof OptionNode) {
                OptionNode o = (OptionNode) last;
                n = o.parent;
                opt = o.option;
            } else if (last instanceof ComponentNode) {
                n = (ComponentNode) last;
                if (n.opts != null) {
                    n = null;
                }

            }
            if (n != null) {
                int count = 0;
                for (CircuitNode cur = n.parent; cur != null; cur = cur.parent) {
                    count++;
                }
                Component[] nPath = new Component[count - 1];
                CircuitNode cur = n.parent;
                for (int j = nPath.length - 1; j >= 0; j--) {
                    nPath[j] = cur.subcircComp;
                    cur = cur.parent;
                }
                ret.add(new SelectionItem(logModel, nPath, n.comp, opt));
            }
        }
        return ret.size() == 0 ? null : ret;
    }

    public boolean hasSelectedItems() {
        TreePath[] sel = getSelectionPaths();
        if (sel == null || sel.length == 0) {
            return false;
        }


        for (int i = 0; i < sel.length; i++) {
            Object last = sel[i].getLastPathComponent();
            if (last instanceof OptionNode) {
                return true;
            } else if (last instanceof ComponentNode) {
                if (((ComponentNode) last).opts == null) {
                    return true;
                }

            }
        }
        return false;
    }

    public void localeChanged() {
        repaint();
    }
}
TOP

Related Classes of com.cburch.logisim.gui.log.ComponentSelector$MyCellRenderer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.