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

lphystudio.app.graphicalmodelpanel.NarrativePanel Maven / Gradle / Ivy

The newest version!
package lphystudio.app.graphicalmodelpanel;

import lphy.core.model.*;
import lphy.core.parser.graphicalmodel.GraphicalModelListener;
import lphystudio.app.graphicalmodelcomponent.GraphicalModelComponent;
import lphystudio.core.narrative.NarrativeLayeredGraph;
import lphystudio.core.narrative.Section;

import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.EditorKit;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Objects;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;


public class NarrativePanel extends JComponent {
    GraphicalModelParserDictionary parserDictionary;
    JTextPane pane = new JTextPane();
    JScrollPane scrollPane;
    NarrativeLayeredGraph narrative;
    JPanel narrativeInnerPanel;
    GraphicalModelComponent graphicalModelComponent;

    JPopupMenu popupMenu = new JPopupMenu("Preferences");

    JList include = createJListWithDragAndDrop();

    static Preferences preferences = Preferences.userNodeForPackage(NarrativePanel.class);

    public NarrativePanel(GraphicalModelParserDictionary parserDictionary, NarrativeLayeredGraph narrative, GraphicalModelComponent component) {
        this(parserDictionary, narrative,  component,null);
    }


    public NarrativePanel(GraphicalModelParserDictionary parserDictionary, NarrativeLayeredGraph narrative, GraphicalModelComponent component, EditorKit editorKit) {
        this.parserDictionary = parserDictionary;
        this.narrative = narrative;
        this.graphicalModelComponent = component;

        setLayout(new BorderLayout());

        pane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        pane.setEditable(false);

        if (editorKit != null) pane.setEditorKit(editorKit);

        pane.addHyperlinkListener(e -> {
            if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
                if (Desktop.isDesktopSupported()) {
                    try {
                        Desktop.getDesktop().browse(e.getURL().toURI());
                    } catch (IOException ioException) {
                        ioException.printStackTrace();
                    } catch (URISyntaxException uriSyntaxException) {
                        uriSyntaxException.printStackTrace();
                    }
                }
            }
        });


        scrollPane = new JScrollPane(pane);

        setText();

        narrativeInnerPanel = new JPanel();

        BoxLayout boxLayout = new BoxLayout(narrativeInnerPanel, BoxLayout.PAGE_AXIS);
        narrativeInnerPanel.setLayout(boxLayout);

        include.setModel(createIncludeListModel());

        include.getModel().addListDataListener(new ListDataListener() {
            @Override
            public void intervalAdded(ListDataEvent e) { setText(); }

            @Override
            public void intervalRemoved(ListDataEvent e) { setText(); }

            @Override
            public void contentsChanged(ListDataEvent e) { setText(); }
        });

        JList exclude = createJListWithDragAndDrop();
        exclude.setModel(createExcludeListModel());
        exclude.setBorder(BorderFactory.createTitledBorder(exclude.getBorder(), "Exclude"));

        include.setBorder(BorderFactory.createTitledBorder(include.getBorder(), "Include"));

        JSplitPane includeExcludePane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, include, exclude);

        add(includeExcludePane, BorderLayout.SOUTH);

        add(scrollPane, BorderLayout.CENTER);

        parserDictionary.addGraphicalModelChangeListener(this::setText);

        component.addGraphicalModelListener(new GraphicalModelListener() {
            @Override
            public void valueSelected(Value value) {

            }

            @Override
            public void generativeDistributionSelected(GenerativeDistribution g) {

            }

            @Override
            public void functionSelected(DeterministicFunction f) {

            }

            @Override
            public void layout() {
                setText();
            }
        });

        parserDictionary.addGraphicalModelChangeListener(() -> {
            popupMenu = new JPopupMenu();
            setupPreferencesMenu(narrative);
            pane.setComponentPopupMenu(popupMenu);
        });

    }

    private void setupPreferencesMenu(Narrative narrative) {
        Preferences preferences = narrative.getPreferences();

        try {
            for (String key : preferences.keys()) {
                String val = preferences.get(key, "");
                if (val.equals("true") || val.equals("false")) {
                    Boolean bool = Boolean.parseBoolean(val);
                    JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(key, bool);
                    popupMenu.add(menuItem);
                    menuItem.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            preferences.putBoolean(key, menuItem.getState());
                            setText();
                        }
                    });
                }

            }
        } catch (BackingStoreException e) {
            e.printStackTrace();
        }

    }


    private JList createJListWithDragAndDrop() {
        JList list = new JList<>();
        list.setDragEnabled(true);
        list.setDropMode(DropMode.INSERT);
        StringMoveHandler.createFor(list);

        return list;
    }

    /**
     * Handles the moving of one or multiple strings between {@link JList}s.
     *
     * @author Matthias Braun
     */
    private static class StringMoveHandler extends TransferHandler {
        private static final long serialVersionUID = 1L;
        private DataFlavor objectArrayFlavor = new DataFlavor(Object[].class, "Array of items");
        // We'll be moving the strings of this list
        private JList list;

        // Clients should use a static factory method to instantiate the handler
        private StringMoveHandler() {
        }

        ;

        public static StringMoveHandler createFor(JList list) {
            StringMoveHandler handler = new StringMoveHandler();
            list.setTransferHandler(handler);
            handler.list = list;
            return handler;
        }

        @Override
        public boolean canImport(TransferSupport info) {
            return info.isDataFlavorSupported(objectArrayFlavor);
        }

        @Override
        public boolean importData(TransferSupport transferSupport) {
            Transferable t = transferSupport.getTransferable();

            boolean success = false;
            try {
                Object[] importedData = (Object[]) t.getTransferData(objectArrayFlavor);
                addToListModel(importedData);
                success = true;
            } catch (UnsupportedFlavorException | IOException e) {
                e.printStackTrace();
            }
            return success;
        }

        private void addToListModel(Object[] importedData) {
            JList.DropLocation loc = list.getDropLocation();
            int dropIndex = loc.getIndex();

            DefaultListModel listModel = (DefaultListModel) list.getModel();
            for (int i = 0; i < importedData.length; i++) {
                Object elem = importedData[i];
                if (elem instanceof String) {
                    listModel.add(dropIndex + i, (String) elem);
                } else {
                    System.err.println("Imported data contained something else than strings: " + elem);
                }
            }
        }

        @Override
        public int getSourceActions(JComponent c) {
            return TransferHandler.COPY_OR_MOVE;
        }

        @Override
        public Transferable createTransferable(JComponent source) {
            // We need the values from the list as an object array, otherwise the data flavor won't match in importData
            @SuppressWarnings("deprecation")
            Object[] valuesToTransfer = list.getSelectedValues();
            return new Transferable() {
                @Override
                public DataFlavor[] getTransferDataFlavors() {
                    return new DataFlavor[]{objectArrayFlavor};
                }

                @Override
                public boolean isDataFlavorSupported(DataFlavor flavor) {
                    return Objects.equals(objectArrayFlavor, flavor);
                }

                @Override
                public Object getTransferData(DataFlavor flavor)
                        throws UnsupportedFlavorException, IOException {
                    if (isDataFlavorSupported(flavor)) {
                        return valuesToTransfer;
                    } else {
                        throw new UnsupportedFlavorException(flavor);
                    }
                }
            };
        }

        @Override
        protected void exportDone(JComponent source, Transferable data, int action) {
            if (action == TransferHandler.MOVE) {
                try {
                    Object[] exportedData = (Object[]) data.getTransferData(objectArrayFlavor);
                    removeFromListModel(exportedData);
                } catch (UnsupportedFlavorException | IOException e) {
                    e.printStackTrace();
                }
            }
        }

        private void removeFromListModel(Object[] dataToRemove) {
            DefaultListModel listModel = (DefaultListModel) list.getModel();
            for (Object elemToRemove : dataToRemove) {
                boolean removedSuccessfully = listModel.removeElement(elemToRemove);
                if (!removedSuccessfully) {
                    System.err.println("Source model did not contain exported data");
                }
            }
        }
    }

    private static ListModel createExcludeListModel() {
        DefaultListModel listModel = new DefaultListModel<>();
        return listModel;
    }

    private static DefaultListModel createIncludeListModel() {
        DefaultListModel listModel = new DefaultListModel<>();
        for (Section section :Section.values()) {
            listModel.addElement(section.name);
        }
        return listModel;
    }

//    private void buildNarrativeMenu() {
//
//        narrativeMenu = new JMenu("Narrative");
//
//        JCheckBoxMenuItem showCodeMenuItem = new JCheckBoxMenuItem("Show Code");
//        showCodeMenuItem.setState(getShowCode());
//        narrativeMenu.add(showCodeMenuItem);
//
//        showCodeMenuItem.addActionListener(e -> setShowCode(showCodeMenuItem.getState()));
//
//        JCheckBoxMenuItem showPosteriorMenuItem = new JCheckBoxMenuItem("Show Posterior");
//        showPosteriorMenuItem.setState(getShowPosterior());
//        narrativeMenu.add(showPosteriorMenuItem);
//
//        showPosteriorMenuItem.addActionListener(e -> setShowPosterior(showPosteriorMenuItem.getState()));
//
//        JCheckBoxMenuItem showGraphicalModel = new JCheckBoxMenuItem("Show Graphical Model");
//        showGraphicalModel.setState(getShowGraphicalModel());
//        narrativeMenu.add(showGraphicalModel);
//
//        showGraphicalModel.addActionListener(e -> setShowGraphicalodel(showGraphicalModel.getState()));
//
//        JCheckBoxMenuItem showReferences = new JCheckBoxMenuItem("Show Graphical Model");
//        showGraphicalModel.setState(getShowGraphicalModel());
//        narrativeMenu.add(showGraphicalModel);
//
//        showGraphicalModel.addActionListener(e -> setShowGraphicalodel(showGraphicalModel.getState()));
//
//    }


    private void setText() {

        try {
            pane.getDocument().remove(0, pane.getDocument().getLength());
        } catch (BadLocationException e) {
            e.printStackTrace();
        }

        String text = narrative.beginDocument(parserDictionary.getName());

        for (int i = 0; i < include.getModel().getSize(); i++) {
            String item = include.getModel().getElementAt(i);

            Section section = Section.Model;
            try {
                section  = Section.valueOf(item);
            } catch (IllegalArgumentException e) {
                for (Section s : Section.values()) {
                    if (s.name.equals(item)) {
                        section = s;
                        break;
                    }
                }
            }

            switch (section) {
                case Data:
                    text += NarrativeUtils.getNarrative(parserDictionary, narrative, true, false);
                    break;
                case Model:
                    text += NarrativeUtils.getNarrative(parserDictionary, narrative, false, true);
                    break;
                case Code:
                    text += narrative.section("Code");
                    text += narrative.codeBlock(parserDictionary, 11);
                    break;
                case Posterior:
                    text += narrative.section("Posterior");
                    text += narrative.posterior(parserDictionary);
                    break;
                case References:
                    text += narrative.referenceSection();
                    break;
                case GraphicalModel:
                    text += narrative.section("Graphical Model");
                    if (graphicalModelComponent.properLayeredGraph != null)
                        text += narrative.graphicalModelBlock(parserDictionary, graphicalModelComponent.properLayeredGraph);
                    break;
            }
        }
        text += narrative.endDocument();

        pane.setText(text);

        pane.setCaretPosition(0);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy