<commit_before>package beast.app.beauti;

import beast.app.draw.BEASTObjectInputEditor;
import beast.core.BEASTInterface;
import beast.core.Input;
import beast.core.util.Log;
import beast.evolution.alignment.Taxon;
import beast.evolution.tree.TraitSet;
import beast.evolution.tree.Tree;

import javax.swing.*;
import javax.swing.event.CellEditorListener;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.text.DateFormat;
import java.time.format.DateTimeParseException;
import java.util.EventObject;
import java.util.List;

public class TipDatesInputEditor extends BEASTObjectInputEditor {

    private static String DATE_FORMAT_HELP_MESSAGE =
            "If the radio button on the second line is selected, this format string " +
                    "will be used to convert the entries in the second column of the table " +
                    "into heights (ages in years before the most recent sample) in the " +
                    "second column.\n" +
                    "\n" +
                    "The format string may be any combination of the following special characters " +
                    "and other delimiting characters such as '-' or '/'.\n" +
                    "\n" +
                    "  Symbol  Meaning                     Examples\n" +
                    "  ------  -------                     --------\n" +
                    "   G       era                         AD; Anno Domini; A\n" +
                    "   u       year                        2004; 04\n" +
                    "   y       year-of-era                 2004; 04\n" +
                    "   D       day-of-year                 189\n" +
                    "   M/L     month-of-year               7; 07; Jul; July; J\n" +
                    "   d       day-of-month                10\n" +
                    "\n" +
                    "   Q/q     quarter-of-year             3; 03; Q3; 3rd quarter\n" +
                    "   Y       week-based-year             1996; 96\n" +
                    "   w       week-of-week-based-year     27\n" +
                    "   W       week-of-month               4\n" +
                    "   E       day-of-week                 Tue; Tuesday; T\n" +
                    "   e/c     localized day-of-week       2; 02; Tue; Tuesday; T\n" +
                    "   F       week-of-month               3\n" +
                    "\n" +
                    "(The table above is an extract from the documentation for the DateTimeFormatter " +
                    "class which is used by BEAST to parse dates.)\n" +
                    "\n" +
                    "Symbols in the above table representing numeric quantities (e.g. day-of-month " +
                    "and month-of-year) may be repeated to allow for zero-padding.  For instance, " +
                    "the format string \"d/m/y\" will match dates such as \"1/3/2004\" while \"dd/mm/y\" " +
                    "will match \"01/03/2004\".  In addition, use \"yy\" to match the short form of the year.\n" +
                    "\n" +
                    "Be aware that in all cases it is necessary that the format chosen be able to pinpoint a " +
                    "single day in the calendar. For instance, \"d/m\" is not a valid format string as it " +
                    "doesn't allow days to be uniquely identified.";


    public TipDatesInputEditor(BeautiDoc doc) {
        super(doc);
    }
    private static final long serialVersionUID = 1L;

    DateFormat dateFormat = DateFormat.getDateInstance();

    @Override
    public Class<?> type() {
        return Tree.class;
    }
    Tree tree;
    TraitSet traitSet;
    JComboBox<TraitSet.Units> unitsComboBox;
    JComboBox<String> relativeToComboBox;
    List<String> taxa;
    Object[][] tableData;
    Boolean[] recordValid;
    JTable table;
    String m_sPattern = ".*(\\d\\d\\d\\d).*";
    JScrollPane scrollPane;
    List<Taxon> taxonsets;

    JRadioButton numericRadioButton, formattedDateRadioButton;
    ButtonGroup radioButtonGroup;
    JComboBox<String> dateFormatComboBox;

    @Override
    public void init(Input<?> input, BEASTInterface beastObject, int itemNr, ExpandOption isExpandOption, boolean addButtons) {
        m_bAddButtons = addButtons;
        this.itemNr = itemNr;
        if (itemNr >= 0) {
            tree = (Tree) ((List<?>) input.get()).get(itemNr);
        } else {
            tree = (Tree) input.get();
        }
        if (tree != null) {
            try {
                m_input = ((BEASTInterface) tree).getInput("trait");
            } catch (Exception e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            m_beastObject = tree;
            traitSet = tree.getDateTrait();

            Box box = Box.createVerticalBox();

            JCheckBox useTipDates = new JCheckBox("Use tip dates", traitSet != null);
            useTipDates.addActionListener(e -> {
                    JCheckBox checkBox = (JCheckBox) e.getSource();
                    try {
                        if (checkBox.isSelected()) {
                            if (traitSet == null) {
                                traitSet = new TraitSet();
                                traitSet.initByName("traitname", "date",
                                        "taxa", tree.getTaxonset(),
                                        "value", "");
                                traitSet.setID("dateTrait.t:" + BeautiDoc.parsePartition(tree.getID()));
                            }
                            tree.setDateTrait(traitSet);
                        } else {
                            tree.setDateTrait(null);
                        }

                        refreshPanel();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }

                });
            Box box2 = Box.createHorizontalBox();
            box2.add(useTipDates);
            box2.add(Box.createHorizontalGlue());
            box.add(box2);

            if (traitSet != null) {
                box.add(createButtonBox());
                box.add(createListBox());
            }
            add(box);
        }
    } // init

    private Component createListBox() {
        taxa = traitSet.taxaInput.get().asStringList();
        String[] columnData = new String[]{"Name", "Date (raw value)", "Height"};
        tableData = new Object[taxa.size()][3];
        recordValid = new Boolean[taxa.size()];
        convertTraitToTableData();
        // set up table.
        // special features: background shading of rows
        // custom editor allowing only Date column to be edited.
        table = new JTable(tableData, columnData) {
            private static final long serialVersionUID = 1L;

            // method that induces table row shading
            @Override
            public Component prepareRenderer(TableCellRenderer renderer, int Index_row, int Index_col) {
                Component comp = super.prepareRenderer(renderer, Index_row, Index_col);
                //even index, selected or not selected
                comp.setForeground(Color.black);
                if (isCellSelected(Index_row, Index_col)) {
                    comp.setBackground(Color.lightGray);
                } else if (!recordValid[Index_row]) {
                    comp.setForeground(Color.WHITE);
                    comp.setBackground(Color.RED);
                } else if (Index_row % 2 == 0 && !isCellSelected(Index_row, Index_col)) {
                    comp.setBackground(new Color(237, 243, 255));
                } else {<commit_msg>Fixed array init bug introduced in fix for issue #778.<commit_after>package beast.app.beauti;

import beast.app.draw.BEASTObjectInputEditor;
import beast.core.BEASTInterface;
import beast.core.Input;
import beast.core.util.Log;
import beast.evolution.alignment.Taxon;
import beast.evolution.tree.TraitSet;
import beast.evolution.tree.Tree;

import javax.swing.*;
import javax.swing.event.CellEditorListener;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.text.DateFormat;
import java.time.format.DateTimeParseException;
import java.util.EventObject;
import java.util.List;

public class TipDatesInputEditor extends BEASTObjectInputEditor {

    private static String DATE_FORMAT_HELP_MESSAGE =
            "If the radio button on the second line is selected, this format string " +
                    "will be used to convert the entries in the second column of the table " +
                    "into heights (ages in years before the most recent sample) in the " +
                    "second column.\n" +
                    "\n" +
                    "The format string may be any combination of the following special characters " +
                    "and other delimiting characters such as '-' or '/'.\n" +
                    "\n" +
                    "  Symbol  Meaning                     Examples\n" +
                    "  ------  -------                     --------\n" +
                    "   G       era                         AD; Anno Domini; A\n" +
                    "   u       year                        2004; 04\n" +
                    "   y       year-of-era                 2004; 04\n" +
                    "   D       day-of-year                 189\n" +
                    "   M/L     month-of-year               7; 07; Jul; July; J\n" +
                    "   d       day-of-month                10\n" +
                    "\n" +
                    "   Q/q     quarter-of-year             3; 03; Q3; 3rd quarter\n" +
                    "   Y       week-based-year             1996; 96\n" +
                    "   w       week-of-week-based-year     27\n" +
                    "   W       week-of-month               4\n" +
                    "   E       day-of-week                 Tue; Tuesday; T\n" +
                    "   e/c     localized day-of-week       2; 02; Tue; Tuesday; T\n" +
                    "   F       week-of-month               3\n" +
                    "\n" +
                    "(The table above is an extract from the documentation for the DateTimeFormatter " +
                    "class which is used by BEAST to parse dates.)\n" +
                    "\n" +
                    "Symbols in the above table representing numeric quantities (e.g. day-of-month " +
                    "and month-of-year) may be repeated to allow for zero-padding.  For instance, " +
                    "the format string \"d/m/y\" will match dates such as \"1/3/2004\" while \"dd/mm/y\" " +
                    "will match \"01/03/2004\".  In addition, use \"yy\" to match the short form of the year.\n" +
                    "\n" +
                    "Be aware that in all cases it is necessary that the format chosen be able to pinpoint a " +
                    "single day in the calendar. For instance, \"d/m\" is not a valid format string as it " +
                    "doesn't allow days to be uniquely identified.";


    public TipDatesInputEditor(BeautiDoc doc) {
        super(doc);
    }
    private static final long serialVersionUID = 1L;

    DateFormat dateFormat = DateFormat.getDateInstance();

    @Override
    public Class<?> type() {
        return Tree.class;
    }
    Tree tree;
    TraitSet traitSet;
    JComboBox<TraitSet.Units> unitsComboBox;
    JComboBox<String> relativeToComboBox;
    List<String> taxa;
    Object[][] tableData;
    boolean[] recordValid;
    JTable table;
    String m_sPattern = ".*(\\d\\d\\d\\d).*";
    JScrollPane scrollPane;
    List<Taxon> taxonsets;

    JRadioButton numericRadioButton, formattedDateRadioButton;
    ButtonGroup radioButtonGroup;
    JComboBox<String> dateFormatComboBox;

    @Override
    public void init(Input<?> input, BEASTInterface beastObject, int itemNr, ExpandOption isExpandOption, boolean addButtons) {
        m_bAddButtons = addButtons;
        this.itemNr = itemNr;
        if (itemNr >= 0) {
            tree = (Tree) ((List<?>) input.get()).get(itemNr);
        } else {
            tree = (Tree) input.get();
        }
        if (tree != null) {
            try {
                m_input = ((BEASTInterface) tree).getInput("trait");
            } catch (Exception e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            m_beastObject = tree;
            traitSet = tree.getDateTrait();

            Box box = Box.createVerticalBox();

            JCheckBox useTipDates = new JCheckBox("Use tip dates", traitSet != null);
            useTipDates.addActionListener(e -> {
                    JCheckBox checkBox = (JCheckBox) e.getSource();
                    try {
                        if (checkBox.isSelected()) {
                            if (traitSet == null) {
                                traitSet = new TraitSet();
                                traitSet.initByName("traitname", "date",
                                        "taxa", tree.getTaxonset(),
                                        "value", "");
                                traitSet.setID("dateTrait.t:" + BeautiDoc.parsePartition(tree.getID()));
                            }
                            tree.setDateTrait(traitSet);
                        } else {
                            tree.setDateTrait(null);
                        }

                        refreshPanel();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }

                });
            Box box2 = Box.createHorizontalBox();
            box2.add(useTipDates);
            box2.add(Box.createHorizontalGlue());
            box.add(box2);

            if (traitSet != null) {
                box.add(createButtonBox());
                box.add(createListBox());
            }
            add(box);
        }
    } // init

    private Component createListBox() {
        taxa = traitSet.taxaInput.get().asStringList();
        String[] columnData = new String[]{"Name", "Date (raw value)", "Height"};
        tableData = new Object[taxa.size()][3];
        recordValid = new boolean[taxa.size()];
        convertTraitToTableData();
        // set up table.
        // special features: background shading of rows
        // custom editor allowing only Date column to be edited.
        table = new JTable(tableData, columnData) {
            private static final long serialVersionUID = 1L;

            // method that induces table row shading
            @Override
            public Component prepareRenderer(TableCellRenderer renderer, int Index_row, int Index_col) {
                Component comp = super.prepareRenderer(renderer, Index_row, Index_col);
                //even index, selected or not selected
                comp.setForeground(Color.black);
                if (isCellSelected(Index_row, Index_col)) {
                    comp.setBackground(Color.lightGray);
                } else if (!recordValid[Index_row]) {
                    comp.setForeground(Color.WHITE);
                    comp.setBackground(Color.RED);
                } else if (Index_row % 2 == 0 && !isCellSelected(Index_row, Index_col)) {
                    comp.setBackground(new Color(237, 243, 255));
                } else {
{'fraction_non_alphanumeric': 0.10100486223662886, 'fraction_numerical': 0.009659643435980551, 'mean_word_length': 1.3809229819416577, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6072472', 'n_tokens_mistral': 4195, 'n_tokens_neox': 3916, 'n_words': 1067}