Package net.cakenet.jsaton.ui.tools.script

Source Code of net.cakenet.jsaton.ui.tools.script.DebugWindow$FrameListCellRenderer

package net.cakenet.jsaton.ui.tools.script;

import net.cakenet.jsaton.script.Script;
import net.cakenet.jsaton.script.debug.BreakInformation;
import net.cakenet.jsaton.script.debug.DebugBreakListener;
import net.cakenet.jsaton.script.debug.DebugFrame;
import net.cakenet.jsaton.script.debug.DebugObject;
import net.cakenet.jsaton.ui.tools.ToolWindow;
import net.cakenet.jsaton.util.ImageUtil;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

public class DebugWindow extends ToolWindow implements PropertyChangeListener, DebugBreakListener, ListSelectionListener, TreeSelectionListener {
    private JList frameList;
    private JPanel panel1;
    private JTree variableTree;
    private ScriptEditor editor;

    public DebugWindow() {
        super("Debug");
        frameList.addListSelectionListener(this);
        frameList.setCellRenderer(new FrameListCellRenderer());
        variableTree.setRootVisible(false);
        variableTree.setShowsRootHandles(true);
        DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
        renderer.setLeafIcon(null);
        renderer.setOpenIcon(null);
        renderer.setClosedIcon(null);
        variableTree.setCellRenderer(renderer);
        variableTree.addTreeSelectionListener(this);
    }

    public Component getContents() {
        return panel1;
    }

    public Icon getIcon() {
        return ImageUtil.loadIcon("icons/bug.png");
    }

    public void setEditor(ScriptEditor editor) {
        if (this.editor != null) {
            this.editor.script.removePropertyChangeListener(this);
            this.editor.script.removeDebugListener(this);
        }
        this.editor = editor;
        if (editor != null) {
            editor.script.addPropertyChangeListener(this);
            editor.script.addDebugListener(this);
        }
        updateComponents();
    }

    private void updateComponents() {
        if (editor != null) {
            setTitle("Debug - " + editor.script.getName());
            Script s = editor.script;
            if (!s.isDebug()) {
                updateWithMessage("Not currently debugging", true);
            } else {
                switch (s.getState()) {
                    case INITIALISING:
                    case STOPPED:
                        updateWithMessage("Not running", true);
                        break;
                    case RUNNING:
                        updateWithMessage("Running", true);
                        break;
                    case SUSPENDED:
                        if (s.getBreakInfo() == null)
                            updateWithMessage("Not available during suspend", true);
                        break;
                }
            }
        } else {
            setTitle("Debug");
            updateWithMessage("No script open", true);
        }
    }

    private void updateWithMessage(String message, boolean removeFrameModel) {
        if(removeFrameModel)
            frameList.setModel(new DefaultListModel());
        DefaultMutableTreeNode root = new DefaultMutableTreeNode("root", true);
        root.add(new DefaultMutableTreeNode(message, false));
        variableTree.setModel(new DefaultTreeModel(root));
    }

    public void onBreak(Script source, BreakInformation info) {
        frameList.setModel(new FrameListModel(info));
        frameList.setSelectedIndex(0);
    }

    public void propertyChange(PropertyChangeEvent evt) {
        String name = evt.getPropertyName();
        if (name.equals("state") || name.equals("name"))
            updateComponents();
    }

    public void valueChanged(ListSelectionEvent e) {
        Object selected = frameList.getSelectedValue();
        if (selected == null || !(selected instanceof DebugFrame))
            return;
        DebugFrame frame = (DebugFrame) selected;
        if (frame.source.equals(editor.script.getName())) {
            variableTree.setModel(new FrameTreeModel(frame));
            editor.highlightBreakpoint(frame);
        } else {
            editor.unhighlightLastHighlightedBreakpoint();
            updateWithMessage("Out of scope", false);
        }
    }

    public void valueChanged(TreeSelectionEvent e) {
        TreePath selected = e.getPath();
        if (selected.getLastPathComponent() == FrameTreeModel.EXPAND_OBJ) {
            int sel = variableTree.getMaxSelectionRow();
            variableTree.setSelectionRow(-1);
            FrameTreeModel ftm = (FrameTreeModel) variableTree.getModel();
            ftm.loadMore(selected.getParentPath());
            variableTree.treeDidChange();
            variableTree.setSelectionRow(sel);
        }
    }

    private static class FrameListModel implements ListModel<DebugFrame> {
        private BreakInformation info;

        public FrameListModel(BreakInformation info) {
            this.info = info;
        }

        public int getSize() {
            return info.frames.size();
        }

        public DebugFrame getElementAt(int index) {
            return info.frames.get(index);
        }

        public void addListDataListener(ListDataListener l) {
            //To change body of implemented methods use File | Settings | File Templates.
        }

        public void removeListDataListener(ListDataListener l) {
            //To change body of implemented methods use File | Settings | File Templates.
        }
    }

    private static class FrameListCellRenderer extends DefaultListCellRenderer {
        public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            if (value instanceof DebugFrame) {
                DebugFrame frame = (DebugFrame) value;
                JLabel label = new JLabel(frame.name + ":" + frame.line);
                label.setOpaque(true);
                if (isSelected) {
                    label.setBackground(list.getSelectionBackground());
                    label.setForeground(list.getSelectionForeground());
                } else {
                    label.setBackground(list.getBackground());
                    label.setForeground(list.getForeground());
                }
                return label;
            }
            return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);    //To change body of overridden methods use File | Settings | File Templates.
        }
    }

    private static class FrameTreeModel implements TreeModel {
        private LinkedList<TreeModelListener> listeners = new LinkedList<>();
        public static final Object EXPAND_OBJ = "Load more...";
        private Map<Object, Integer> max_index = new HashMap<>();
        private DebugFrame frame;

        public FrameTreeModel(DebugFrame frame) {
            this.frame = frame;
        }

        public Object getRoot() {
            return frame;
        }

        private int getMax(Object parent) {
            if (parent == EXPAND_OBJ)
                return 0;
            if (!max_index.containsKey(parent))
                max_index.put(parent, 100); // Start off at 100...
            return max_index.get(parent);
        }

        public void loadMore(TreePath path) {
            Object parent = path.getLastPathComponent();
            int max = getMax(parent);
            max += 100;
            max = Math.min(max, getActualChildCount(parent));
            max_index.put(parent, max);
            if (listeners.isEmpty())
                return;
            // CBF'D, just reload the entire node...
            TreeModelEvent ev = new TreeModelEvent(this, path);
            for (int i = 0; i < listeners.size(); i++) {
                TreeModelListener l = listeners.get(i);
                l.treeStructureChanged(ev);
            }
        }

        private int getActualChildCount(Object parent) {
            int count = 0;
            if (parent instanceof DebugFrame) {
                DebugFrame frame = (DebugFrame) parent;
                count = frame.variables.size();
                if (frame.self != null)
                    count++;
            } else if (parent instanceof DebugObject) {
                count = ((DebugObject) parent).size();
            }
            return count;
        }

        public Object getChild(Object parent, int index) {
            int max = getMax(parent);
            if (index >= max)
                return EXPAND_OBJ;
            if (parent instanceof DebugFrame) {
                DebugFrame frame = (DebugFrame) parent;
                if (frame.self != null) {
                    if (index == 0)
                        return frame.self;
                    return frame.variables.get(index - 1);
                }
                return frame.variables.get(index);
            } else if (parent instanceof DebugObject) {
                return ((DebugObject) parent).get(index);
            }
            return null;
        }

        public int getChildCount(Object parent) {
            int count = getActualChildCount(parent);

            return Math.min(getMax(parent) + 1, count);
        }

        public boolean isLeaf(Object node) {
            return getChildCount(node) == 0;
        }

        public void valueForPathChanged(TreePath path, Object newValue) {
        }

        public int getIndexOfChild(Object parent, Object child) {
            if (parent instanceof DebugFrame) {
                DebugFrame frame = (DebugFrame) parent;
                if (frame.self != null) {
                    if (child == frame.self)
                        return 0;
                    return frame.variables.indexOf(child) + 1;
                }
                return frame.variables.indexOf(child);
            } else if (parent instanceof DebugObject) {
                return ((DebugObject) parent).indexOf(child);
            }
            return 0;
        }

        public void addTreeModelListener(TreeModelListener l) {
            listeners.add(l);
        }

        public void removeTreeModelListener(TreeModelListener l) {
            listeners.remove(l);
        }
    }


}
TOP

Related Classes of net.cakenet.jsaton.ui.tools.script.DebugWindow$FrameListCellRenderer

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.