From c25a5c7301fa43bec8da032f93898d6133391f8a Mon Sep 17 00:00:00 2001 From: kiramt Date: Fri, 2 Dec 2016 13:49:27 +0000 Subject: [PATCH] JAL-2316 GUI updates to Connections tab in Preferences dialog --- resources/lang/Messages.properties | 4 +- resources/lang/Messages_es.properties | 4 +- src/jalview/gui/Preferences.java | 269 +++++++++++---- src/jalview/jbgui/GPreferences.java | 458 +++++++++++++++++++------- src/jalview/jbgui/GSequenceLink.java | 3 +- src/jalview/urls/CustomUrlProvider.java | 90 ++++- src/jalview/urls/IdentifiersUrlProvider.java | 77 ++++- src/jalview/urls/UrlLinkDisplay.java | 152 +++++++++ src/jalview/urls/UrlLinkTableModel.java | 204 ++++++++++++ src/jalview/urls/UrlProvider.java | 32 +- src/jalview/urls/UrlProviderI.java | 17 + src/jalview/urls/UrlProviderImpl.java | 26 +- 12 files changed, 1113 insertions(+), 223 deletions(-) create mode 100644 src/jalview/urls/UrlLinkDisplay.java create mode 100644 src/jalview/urls/UrlLinkTableModel.java diff --git a/resources/lang/Messages.properties b/resources/lang/Messages.properties index 7582568..045f58c 100644 --- a/resources/lang/Messages.properties +++ b/resources/lang/Messages.properties @@ -1273,4 +1273,6 @@ label.SEQUENCE_ID_for_DB_ACCESSION1 = Please review your URL links in the 'Conne label.SEQUENCE_ID_for_DB_ACCESSION2 = URL links using '$SEQUENCE_ID$' for DB accessions now use '$DB_ACCESSION$'. label.do_not_display_again = Do not display this message again exception.url_cannot_have_miriam_id = {0} is a MIRIAM id and cannot be used as a custom url name -exception.url_cannot_have_duplicate_id = {0} cannot be used as a label for more than one link \ No newline at end of file +exception.url_cannot_have_duplicate_id = {0} cannot be used as a label for more than one line +label.filter = Filter text: +action.customfilter = Custom only \ No newline at end of file diff --git a/resources/lang/Messages_es.properties b/resources/lang/Messages_es.properties index f3d782c..9922e46 100644 --- a/resources/lang/Messages_es.properties +++ b/resources/lang/Messages_es.properties @@ -1274,4 +1274,6 @@ label.SEQUENCE_ID_for_DB_ACCESSION1 = Por favor, revise sus URLs en la pesta label.SEQUENCE_ID_for_DB_ACCESSION2 = URL enlaza usando '$SEQUENCE_ID$' para accesiones DB ahora usar '$DB_ACCESSION$'. label.do_not_display_again = No mostrar este mensaje de nuevo exception.url_cannot_have_miriam_id = {0} is a MIRIAM id and cannot be used as a custom url name -exception.url_cannot_have_duplicate_id = {0} cannot be used as a label for more than one link \ No newline at end of file +exception.url_cannot_have_duplicate_id = {0} cannot be used as a label for more than one link +label.filter = Filter text: +action.customfilter = Custom only \ No newline at end of file diff --git a/src/jalview/gui/Preferences.java b/src/jalview/gui/Preferences.java index 56e076e..7a24aeb 100755 --- a/src/jalview/gui/Preferences.java +++ b/src/jalview/gui/Preferences.java @@ -29,6 +29,7 @@ import jalview.io.JalviewFileView; import jalview.jbgui.GPreferences; import jalview.jbgui.GSequenceLink; import jalview.schemes.ColourSchemeProperty; +import jalview.urls.UrlLinkTableModel; import jalview.urls.UrlProvider; import jalview.urls.UrlProviderI; import jalview.util.MessageManager; @@ -37,6 +38,7 @@ import jalview.ws.sifts.SiftsSettings; import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.event.ActionEvent; @@ -45,7 +47,6 @@ import java.awt.event.MouseEvent; import java.io.File; import java.util.ArrayList; import java.util.List; -import java.util.Vector; import javax.help.HelpSetException; import javax.swing.JColorChooser; @@ -53,6 +54,18 @@ import javax.swing.JFileChooser; import javax.swing.JInternalFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.ListSelectionModel; +import javax.swing.RowFilter; +import javax.swing.RowSorter; +import javax.swing.SortOrder; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; +import javax.swing.table.TableRowSorter; import ext.edu.ucsf.rbvi.strucviz2.StructureManager; @@ -100,6 +113,8 @@ public class Preferences extends GPreferences */ public static UrlProviderI sequenceUrlLinks; + public static UrlLinkTableModel dataModel; + /** * Holds name and link separated with | character. Sequence IDS and Sequences * must be $SEQUENCEIDS$ or $SEQUENCEIDS=/.possible | chars ./=$ and @@ -115,6 +130,14 @@ public class Preferences extends GPreferences UrlProviderI.DEFAULT_STRING); sequenceUrlLinks = new UrlProvider(UrlProviderI.DEFAULT_LABEL, string); + List colNames = new ArrayList(); + // colNames.add("ID"); + // TODO KM add to properties file + colNames.add("URL"); + colNames.add("In Menu"); + colNames.add("Default"); + dataModel = new UrlLinkTableModel(sequenceUrlLinks, colNames, "ID"); + /** * TODO: reformulate groupURL encoding so two or more can be stored in the * .properties file as '|' separated strings @@ -123,8 +146,6 @@ public class Preferences extends GPreferences groupURLLinks = new ArrayList(); } - Vector nameLinks, urlLinks; - JInternalFrame frame; DasSourceBrowser dasSource; @@ -308,13 +329,121 @@ public class Preferences extends GPreferences /* * Set Connections tab defaults */ - nameLinks = new Vector(); - urlLinks = new Vector(); - resetStoredLinks(); - updateLinkData(); + // set up sorting + linkUrlTable.setModel(dataModel); + final TableRowSorter sorter = new TableRowSorter<>( + linkUrlTable.getModel()); + linkUrlTable.setRowSorter(sorter); + List sortKeys = new ArrayList<>(); + + sortKeys.add(new RowSorter.SortKey(3, + SortOrder.DESCENDING)); + sortKeys.add(new RowSorter.SortKey(2, SortOrder.DESCENDING)); + sortKeys.add(new RowSorter.SortKey(0, SortOrder.ASCENDING)); + + sorter.setSortKeys(sortKeys); + sorter.sort(); + + // set up filtering + ActionListener onReset; + onReset = new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + filterTB.setText(""); + sorter.setRowFilter(RowFilter.regexFilter("")); + } + + }; + doReset.addActionListener(onReset); + + // filter to display only custom urls + final RowFilter customUrlFilter = new RowFilter() + { + @Override + public boolean include( + Entry entry) + { + String id = entry.getStringValue(4); + return sequenceUrlLinks.isUserEntry(id); + } + }; + + final TableRowSorter customSorter = new TableRowSorter<>( + linkUrlTable.getModel()); + customSorter.setRowFilter(customUrlFilter); + + ActionListener onCustomOnly; + onCustomOnly = new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + filterTB.setText(""); + sorter.setRowFilter(customUrlFilter); + } + }; + userOnly.addActionListener(onCustomOnly); + + filterTB.getDocument().addDocumentListener(new DocumentListener() + { + @Override + public void changedUpdate(DocumentEvent e) + { + sorter.setRowFilter(RowFilter.regexFilter("(?i)" + + filterTB.getText())); + } + + @Override + public void removeUpdate(DocumentEvent e) + { + sorter.setRowFilter(RowFilter.regexFilter("(?i)" + + filterTB.getText())); + } + + @Override + public void insertUpdate(DocumentEvent e) + { + sorter.setRowFilter(RowFilter.regexFilter("(?i)" + + filterTB.getText())); + } + }); + + // set up list selection functionality + linkUrlTable.getSelectionModel().addListSelectionListener( + new UrlListSelectionHandler()); + + // set up radio buttons + linkUrlTable.getColumn("Default").setCellRenderer( + new RadioButtonRenderer()); + linkUrlTable.getColumn("Default") + .setCellEditor(new RadioButtonEditor()); + + // get boolean columns and resize those to min possible + for (int column = 0; column < linkUrlTable.getColumnCount(); column++) + { + if (linkUrlTable.getModel().getColumnClass(column) + .equals(Boolean.class)) + { + TableColumn tableColumn = linkUrlTable.getColumnModel().getColumn( + column); + int preferredWidth = tableColumn.getMinWidth(); + + TableCellRenderer cellRenderer = linkUrlTable.getCellRenderer(0, + column); + Component c = linkUrlTable.prepareRenderer(cellRenderer, 0, column); + int cwidth = c.getPreferredSize().width + + linkUrlTable.getIntercellSpacing().width; + preferredWidth = Math.max(preferredWidth, cwidth); + + tableColumn.setPreferredWidth(preferredWidth); + } + } useProxy.setSelected(Cache.getDefault("USE_PROXY", false)); + useProxy_actionPerformed(); // make sure useProxy is correctly initialised proxyServerTB.setEnabled(useProxy.isSelected()); proxyPortTB.setEnabled(useProxy.isSelected()); proxyServerTB.setText(Cache.getDefault("PROXY_SERVER", "")); @@ -509,7 +638,7 @@ public class Preferences extends GPreferences jalview.util.BrowserLauncher.resetBrowser(); // save user-defined and selected links - String links = sequenceUrlLinks.writeUrlsAsString(); + String links = linkUrlTable.getModel().toString(); if (links.isEmpty()) { Cache.applicationProperties.remove("SEQUENCE_LINKS"); @@ -710,16 +839,9 @@ public class Preferences extends GPreferences { if (link.checkValid()) { - nameLinks.addElement(link.getName()); - urlLinks.addElement(link.getURL()); - if (updateLinkData()) - { - valid = true; - } - else - { - break; - } + ((UrlLinkTableModel) linkUrlTable.getModel()).insertRow( + link.getName(), link.getURL()); + valid = true; } } else @@ -734,9 +856,10 @@ public class Preferences extends GPreferences { GSequenceLink link = new GSequenceLink(); - int index = linkNameList.getSelectedIndex(); + int index = linkUrlTable.getSelectedRow(); if (index == -1) { + // no row was selected JOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager.getString("label.no_link_selected"), MessageManager.getString("label.no_link_selected"), @@ -744,8 +867,8 @@ public class Preferences extends GPreferences return; } - link.setName(nameLinks.elementAt(index).toString()); - link.setURL(urlLinks.elementAt(index).toString()); + link.setName(linkUrlTable.getValueAt(index, 0).toString()); + link.setURL(linkUrlTable.getValueAt(index, 1).toString()); boolean valid = false; while (!valid) @@ -757,19 +880,12 @@ public class Preferences extends GPreferences { if (link.checkValid()) { - nameLinks.setElementAt(link.getName(), index); - urlLinks.setElementAt(link.getURL(), index); - if (updateLinkData()) - { - valid = true; - } - else - { - break; - } + + linkUrlTable.setValueAt(link.getName(), index, 0); + linkUrlTable.setValueAt(link.getURL(), index, 1); + valid = true; } } - else { break; @@ -780,58 +896,27 @@ public class Preferences extends GPreferences @Override public void deleteLink_actionPerformed(ActionEvent e) { - int index = linkNameList.getSelectedIndex(); + int index = linkUrlTable.getSelectedRow(); + int modelIndex = -1; if (index == -1) { + // no row is selected JOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager.getString("label.no_link_selected"), MessageManager.getString("label.no_link_selected"), JOptionPane.WARNING_MESSAGE); return; } - nameLinks.removeElementAt(index); - urlLinks.removeElementAt(index); - updateLinkData(); - } - - private boolean updateLinkData() - { - try - { - sequenceUrlLinks.setUrlLinks(nameLinks, urlLinks); - linkNameList.setListData(nameLinks); - linkURLList.setListData(urlLinks); - } catch (IllegalArgumentException e) + else { - - // put back the old links - resetStoredLinks(); - - linkNameList.setListData(nameLinks); - linkURLList.setListData(urlLinks); - - JOptionPane.showInternalMessageDialog(Desktop.desktop, - e.getMessage(), MessageManager.getString("label.link_name"), - JOptionPane.WARNING_MESSAGE); - - return false; + modelIndex = linkUrlTable.convertRowIndexToModel(index); } - return true; - } - private void resetStoredLinks() - { - Vector nlinks = sequenceUrlLinks.getLinksForDisplay(); - - nameLinks.clear(); - urlLinks.clear(); - for (String entry : nlinks) - { - nameLinks.addElement(entry.split("\\|")[0]); - urlLinks.addElement(entry.split("\\|")[1]); - } + // make sure we use the model index to delete, and not the table index + ((UrlLinkTableModel) linkUrlTable.getModel()).removeRow(modelIndex); } + @Override public void defaultBrowser_mouseClicked(MouseEvent e) { @@ -1048,4 +1133,46 @@ public class Preferences extends GPreferences return name.hashCode() + code.hashCode(); } } + + private class UrlListSelectionHandler implements ListSelectionListener + { + + @Override + public void valueChanged(ListSelectionEvent e) + { + ListSelectionModel lsm = (ListSelectionModel) e.getSource(); + + int index = lsm.getMinSelectionIndex(); + if (index == -1) + { + // no selection, so disable delete/edit buttons + editLink.setEnabled(false); + deleteLink.setEnabled(false); + return; + } + int modelIndex = linkUrlTable.convertRowIndexToModel(index); + + // determine if the new selection is a custom url or not + if (!sequenceUrlLinks.isUserEntry((String) linkUrlTable +.getModel() + .getValueAt(modelIndex, 4))) // KM TODO do this better + { + // entry is not a user-defined url and so should not be edited + // disable edit and delete buttons + deleteLink.setEnabled(false); + editLink.setEnabled(false); + } + else + { + deleteLink.setEnabled(true); + editLink.setEnabled(true); + } + + // BUT it's the default url, don't allow deletion + if ((boolean) linkUrlTable.getValueAt(index, 3)) + { + deleteLink.setEnabled(false); + } + } +} } diff --git a/src/jalview/jbgui/GPreferences.java b/src/jalview/jbgui/GPreferences.java index 90053f5..3fe1939 100755 --- a/src/jalview/jbgui/GPreferences.java +++ b/src/jalview/jbgui/GPreferences.java @@ -45,6 +45,7 @@ import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import javax.swing.AbstractCellEditor; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.DefaultListCellRenderer; @@ -53,11 +54,11 @@ import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JFileChooser; import javax.swing.JLabel; -import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JTabbedPane; +import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.ListSelectionModel; import javax.swing.SwingConstants; @@ -67,8 +68,8 @@ import javax.swing.border.EtchedBorder; import javax.swing.border.TitledBorder; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; /** * Base class for the Preferences panel. @@ -180,7 +181,21 @@ public class GPreferences extends JPanel /* * Connections tab components */ - protected JList linkURLList = new JList(); + protected JTable linkUrlTable = new JTable(); + + protected JButton editLink = new JButton(); + + protected JButton deleteLink = new JButton(); + + protected JTextField filterTB = new JTextField(); + + protected JButton doReset = new JButton(); + + protected JButton userOnly = new JButton(); + + protected JLabel portLabel = new JLabel(); + + protected JLabel serverLabel = new JLabel(); protected JTextField proxyServerTB = new JTextField(); @@ -188,8 +203,6 @@ public class GPreferences extends JPanel protected JTextField defaultBrowser = new JTextField(); - protected JList linkNameList = new JList(); - protected JCheckBox useProxy = new JCheckBox(); protected JCheckBox usagestats = new JCheckBox(); @@ -483,38 +496,255 @@ public class GPreferences extends JPanel { JPanel connectTab = new JPanel(); connectTab.setLayout(new GridBagLayout()); - JLabel serverLabel = new JLabel(); + + // Label for browser text box + JLabel browserLabel = new JLabel(); + browserLabel.setFont(LABEL_FONT); + browserLabel.setHorizontalAlignment(SwingConstants.TRAILING); + browserLabel.setText(MessageManager + .getString("label.default_browser_unix")); + defaultBrowser.setFont(LABEL_FONT); + defaultBrowser.setText(""); + + defaultBrowser.addMouseListener(new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent e) + { + if (e.getClickCount() > 1) + { + defaultBrowser_mouseClicked(e); + } + } + }); + + JPanel proxyPanel = initConnTabProxyPanel(); + JPanel linkPanel = initConnTabUrlLinks(); + initConnTabCheckboxes(); + + // Add URL link panel + connectTab.add(linkPanel, new GridBagConstraints(0, 0, 2, 1, 2.0, 2.0, + GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets( + 16, 0, 0, 12), 359, 32)); + + // Add default Browser text box + connectTab.add(browserLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, + 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, + new Insets(10, 0, 0, 0), 5, 1)); + + connectTab.add(defaultBrowser, new GridBagConstraints(1, 1, 1, 1, 1.0, + 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, + new Insets(10, 0, 0, 10), 307, 1)); + + // Add proxy server panel + connectTab.add(proxyPanel, new GridBagConstraints(0, 2, 2, 1, 1.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, + new Insets(10, 0, 0, 12), 4, 10)); + + // Add usage stats, version check and questionnaire checkboxes + connectTab.add(usagestats, new GridBagConstraints(0, 3, 1, 1, 1.0, 0.0, + GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, + new Insets(0, 2, 4, 2), 70, 1)); + connectTab.add(questionnaire, new GridBagConstraints(1, 3, 1, 1, 1.0, + 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, + new Insets(0, 2, 4, 10), 70, 1)); + connectTab.add(versioncheck, new GridBagConstraints(0, 4, 1, 1, 1.0, + 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, + new Insets(0, 2, 4, 2), 70, 1)); + return connectTab; + } + + /** + * Initialises the proxy server panel in the Connections tab + * + * @return the proxy server panel + */ + private JPanel initConnTabProxyPanel() + { + // Label for server text box serverLabel.setText(MessageManager.getString("label.address")); serverLabel.setHorizontalAlignment(SwingConstants.RIGHT); serverLabel.setFont(LABEL_FONT); + + // Proxy server and port text boxes proxyServerTB.setFont(LABEL_FONT); proxyPortTB.setFont(LABEL_FONT); - JLabel portLabel = new JLabel(); + + // Label for Port text box portLabel.setFont(LABEL_FONT); portLabel.setHorizontalAlignment(SwingConstants.RIGHT); portLabel.setText(MessageManager.getString("label.port")); - JLabel browserLabel = new JLabel(); - browserLabel.setFont(new java.awt.Font("SansSerif", 0, 11)); - browserLabel.setHorizontalAlignment(SwingConstants.TRAILING); - browserLabel.setText(MessageManager - .getString("label.default_browser_unix")); - defaultBrowser.setFont(LABEL_FONT); - defaultBrowser.setText(""); + + // Use proxy server checkbox + useProxy.setFont(LABEL_FONT); + useProxy.setHorizontalAlignment(SwingConstants.RIGHT); + useProxy.setHorizontalTextPosition(SwingConstants.LEADING); + useProxy.setText(MessageManager.getString("label.use_proxy_server")); + useProxy.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + useProxy_actionPerformed(); + } + }); + + // Make proxy server panel + JPanel proxyPanel = new JPanel(); + TitledBorder titledBorder1 = new TitledBorder( + MessageManager.getString("label.proxy_server")); + proxyPanel.setBorder(titledBorder1); + proxyPanel.setLayout(new GridBagLayout()); + proxyPanel.add(serverLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, + 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, + new Insets(0, 2, 2, 0), 5, 0)); + proxyPanel.add(portLabel, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0, + GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, + 0, 2, 0), 11, 0)); + proxyPanel.add(useProxy, new GridBagConstraints(0, 0, 2, 1, 0.0, 0.0, + GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, + 2, 5, 185), 2, -4)); + proxyPanel.add(proxyPortTB, new GridBagConstraints(3, 1, 1, 1, 1.0, + 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, + new Insets(0, 2, 2, 2), 54, 1)); + proxyPanel.add(proxyServerTB, new GridBagConstraints(1, 1, 1, 1, 1.0, + 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, + new Insets(0, 2, 2, 0), 263, 1)); + + return proxyPanel; + } + + /** + * Initialises the checkboxes in the Connections tab + */ + private void initConnTabCheckboxes() + { + // Usage stats checkbox label usagestats.setText(MessageManager .getString("label.send_usage_statistics")); usagestats.setFont(LABEL_FONT); usagestats.setHorizontalAlignment(SwingConstants.RIGHT); usagestats.setHorizontalTextPosition(SwingConstants.LEADING); + + // Questionnaire checkbox label questionnaire.setText(MessageManager .getString("label.check_for_questionnaires")); questionnaire.setFont(LABEL_FONT); questionnaire.setHorizontalAlignment(SwingConstants.RIGHT); questionnaire.setHorizontalTextPosition(SwingConstants.LEADING); + + // Check for latest version checkbox label versioncheck.setText(MessageManager .getString("label.check_for_latest_version")); versioncheck.setFont(LABEL_FONT); versioncheck.setHorizontalAlignment(SwingConstants.RIGHT); versioncheck.setHorizontalTextPosition(SwingConstants.LEADING); + } + + /** + * Initialises the URL links panel in the Connection tab + * + * @return the URL links panel + */ + private JPanel initConnTabUrlLinks() + { + // Set up table for Url links + linkUrlTable.setFillsViewportHeight(true); + linkUrlTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); + linkUrlTable.setAutoCreateRowSorter(true); + linkUrlTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + + // Table in scrollpane so that the table is given a scrollbar + JScrollPane linkScrollPane = new JScrollPane(linkUrlTable); + linkScrollPane.setBorder(null); + + // Panel for links functionality + JPanel linkPanel = new JPanel(new GridBagLayout()); + linkPanel.setBorder(new TitledBorder(MessageManager + .getString("label.url_linkfrom_sequence_id"))); + + // Put the Url links panel together + + // Buttons go at top right, resizing only resizes the blank space vertically + JPanel buttonPanel = initConnTabUrlButtons(); + GridBagConstraints linkConstraints1 = new GridBagConstraints(); + linkConstraints1.gridx = 1; + linkConstraints1.gridy = 0; + linkConstraints1.fill = GridBagConstraints.VERTICAL; + linkPanel.add(buttonPanel, linkConstraints1); + + // Links table goes at top left, resizing resizes the table + GridBagConstraints linkConstraints2 = new GridBagConstraints(); + linkConstraints2.gridx = 0; + linkConstraints2.gridy = 0; + linkConstraints2.weightx = 1.0; + linkConstraints2.weighty = 1.0; + linkConstraints2.fill = GridBagConstraints.BOTH; + linkPanel.add(linkScrollPane, linkConstraints2); + + // Filter box and buttons goes at bottom left, resizing resizes the text box + JPanel filterPanel = initConnTabFilterPanel(); + GridBagConstraints linkConstraints3 = new GridBagConstraints(); + linkConstraints3.gridx = 0; + linkConstraints3.gridy = 1; + linkConstraints3.weightx = 1.0; + linkConstraints3.fill = GridBagConstraints.HORIZONTAL; + linkPanel.add(filterPanel, linkConstraints3); + + return linkPanel; + } + + private JPanel initConnTabFilterPanel() + { + // Filter textbox and reset button + JLabel filterLabel = new JLabel( + MessageManager.getString("label.filter")); + filterLabel.setFont(LABEL_FONT); + filterLabel.setHorizontalAlignment(SwingConstants.RIGHT); + filterLabel.setHorizontalTextPosition(SwingConstants.LEADING); + + filterTB.setFont(LABEL_FONT); + filterTB.setText(""); + + doReset.setText(MessageManager.getString("action.reset")); + userOnly.setText(MessageManager.getString("action.customfilter")); + + // Panel for filter functionality + JPanel filterPanel = new JPanel(new GridBagLayout()); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.fill = GridBagConstraints.NONE; + gbc.anchor = GridBagConstraints.WEST; + + filterPanel.add(filterLabel, gbc); + + GridBagConstraints gbc1 = new GridBagConstraints(); + gbc1.gridx = 0; + gbc1.gridx = 1; + gbc1.fill = GridBagConstraints.HORIZONTAL; + gbc1.anchor = GridBagConstraints.WEST; + gbc1.weightx = 1.0; + filterPanel.add(filterTB, gbc1); + + GridBagConstraints gbc2 = new GridBagConstraints(); + gbc2.gridx = 2; + gbc2.fill = GridBagConstraints.NONE; + gbc2.anchor = GridBagConstraints.WEST; + filterPanel.add(doReset, gbc2); + + GridBagConstraints gbc3 = new GridBagConstraints(); + gbc3.gridx = 3; + gbc3.fill = GridBagConstraints.NONE; + gbc3.anchor = GridBagConstraints.WEST; + filterPanel.add(userOnly, gbc3); + + return filterPanel; + } + + private JPanel initConnTabUrlButtons() + { + // Buttons for new / edit / delete Url links JButton newLink = new JButton(); newLink.setText(MessageManager.getString("action.new")); newLink.addActionListener(new java.awt.event.ActionListener() @@ -525,7 +755,7 @@ public class GPreferences extends JPanel newLink_actionPerformed(e); } }); - JButton editLink = new JButton(); + editLink.setText(MessageManager.getString("action.edit")); editLink.addActionListener(new java.awt.event.ActionListener() { @@ -535,7 +765,7 @@ public class GPreferences extends JPanel editLink_actionPerformed(e); } }); - JButton deleteLink = new JButton(); + deleteLink.setText(MessageManager.getString("action.delete")); deleteLink.addActionListener(new java.awt.event.ActionListener() { @@ -546,117 +776,21 @@ public class GPreferences extends JPanel } }); - linkURLList.addListSelectionListener(new ListSelectionListener() - { - @Override - public void valueChanged(ListSelectionEvent e) - { - int index = linkURLList.getSelectedIndex(); - linkNameList.setSelectedIndex(index); - } - }); + // no current selection, so initially disable delete/edit buttons + editLink.setEnabled(false); + deleteLink.setEnabled(false); - linkNameList.addListSelectionListener(new ListSelectionListener() - { - @Override - public void valueChanged(ListSelectionEvent e) - { - int index = linkNameList.getSelectedIndex(); - linkURLList.setSelectedIndex(index); - } - }); + // Panels for new/edit/delete link buttons + // buttonContent prevents the buttons from being resized when the window is + JPanel buttonContent = new JPanel(new GridLayout(0, 1, 0, 0)); + JPanel buttonPanel = new JPanel(new BorderLayout()); - JScrollPane linkScrollPane = new JScrollPane(); - linkScrollPane.setBorder(null); - JPanel linkPanel = new JPanel(); - linkPanel.setBorder(new TitledBorder(MessageManager - .getString("label.url_linkfrom_sequence_id"))); - linkPanel.setLayout(new BorderLayout()); - GridLayout gridLayout1 = new GridLayout(); - JPanel editLinkButtons = new JPanel(); - editLinkButtons.setLayout(gridLayout1); - gridLayout1.setRows(3); - linkNameList.setFont(LABEL_FONT); - linkNameList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - BorderLayout borderLayout3 = new BorderLayout(); - JPanel linkPanel2 = new JPanel(); - linkPanel2.setLayout(borderLayout3); - linkURLList.setFont(LABEL_FONT); - linkURLList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + buttonContent.add(newLink, null); + buttonContent.add(editLink, null); + buttonContent.add(deleteLink, null); + buttonPanel.add(buttonContent, BorderLayout.NORTH); - defaultBrowser.addMouseListener(new MouseAdapter() - { - @Override - public void mouseClicked(MouseEvent e) - { - if (e.getClickCount() > 1) - { - defaultBrowser_mouseClicked(e); - } - } - }); - useProxy.setFont(LABEL_FONT); - useProxy.setHorizontalAlignment(SwingConstants.RIGHT); - useProxy.setHorizontalTextPosition(SwingConstants.LEADING); - useProxy.setText(MessageManager.getString("label.use_proxy_server")); - useProxy.addActionListener(new ActionListener() - { - @Override - public void actionPerformed(ActionEvent e) - { - useProxy_actionPerformed(); - } - }); - linkPanel.add(editLinkButtons, BorderLayout.EAST); - editLinkButtons.add(newLink, null); - editLinkButtons.add(editLink, null); - editLinkButtons.add(deleteLink, null); - linkPanel.add(linkScrollPane, BorderLayout.CENTER); - linkScrollPane.getViewport().add(linkPanel2, null); - linkPanel2.add(linkURLList, BorderLayout.CENTER); - linkPanel2.add(linkNameList, BorderLayout.WEST); - JPanel jPanel1 = new JPanel(); - TitledBorder titledBorder1 = new TitledBorder( - MessageManager.getString("label.proxy_server")); - jPanel1.setBorder(titledBorder1); - jPanel1.setLayout(new GridBagLayout()); - jPanel1.add(serverLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, - 2, 4, 0), 5, 0)); - jPanel1.add(portLabel, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, - 0, 4, 0), 11, 6)); - connectTab.add(linkPanel, new GridBagConstraints(0, 0, 2, 1, 1.0, 1.0, - GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets( - 16, 0, 0, 12), 359, -17)); - connectTab.add(jPanel1, new GridBagConstraints(0, 2, 2, 1, 1.0, 1.0, - GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets( - 21, 0, 35, 12), 4, 6)); - connectTab.add(browserLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, - 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, - new Insets(16, 0, 0, 0), 5, 1)); - jPanel1.add(useProxy, new GridBagConstraints(0, 0, 2, 1, 0.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, - 2, 5, 185), 2, -4)); - jPanel1.add(proxyPortTB, new GridBagConstraints(3, 1, 1, 1, 1.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(0, 2, 4, 2), 54, 1)); - jPanel1.add(proxyServerTB, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(0, 2, 4, 0), 263, 1)); - connectTab.add(defaultBrowser, new GridBagConstraints(1, 1, 1, 1, 1.0, - 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(15, 0, 0, 15), 307, 1)); - connectTab.add(usagestats, new GridBagConstraints(0, 4, 1, 1, 1.0, 0.0, - GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(0, 2, 4, 2), 70, 1)); - connectTab.add(questionnaire, new GridBagConstraints(1, 4, 1, 1, 1.0, - 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(0, 2, 4, 2), 70, 1)); - connectTab.add(versioncheck, new GridBagConstraints(0, 5, 1, 1, 1.0, - 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, - new Insets(0, 2, 4, 2), 70, 1)); - return connectTab; + return buttonPanel; } /** @@ -1357,8 +1491,78 @@ public class GPreferences extends JPanel public void useProxy_actionPerformed() { - proxyServerTB.setEnabled(useProxy.isSelected()); - proxyPortTB.setEnabled(useProxy.isSelected()); + boolean enabled = useProxy.isSelected(); + portLabel.setEnabled(enabled); + serverLabel.setEnabled(enabled); + proxyServerTB.setEnabled(enabled); + proxyPortTB.setEnabled(enabled); } + public class RadioButtonRenderer extends JRadioButton implements + TableCellRenderer + { + public RadioButtonRenderer() + { + setHorizontalAlignment(CENTER); + } + + @Override + public Component getTableCellRendererComponent(JTable table, + Object value, boolean isSelected, boolean hasFocus, int row, + int column) + { + setSelected((boolean) value); + + // set colours to match rest of table + if (isSelected) + { + setBackground(table.getSelectionBackground()); + setForeground(table.getSelectionForeground()); + } + else + { + setBackground(table.getBackground()); + setForeground(table.getForeground()); + } + + // adjust row height so radio buttons actually fit + table.setRowHeight(row, getMinimumSize().height); + + return this; + } + } + + public class RadioButtonEditor extends AbstractCellEditor implements + TableCellEditor + { + private JRadioButton button = new JRadioButton(); + + public RadioButtonEditor() + { + this.button.setHorizontalAlignment(SwingConstants.CENTER); + this.button.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + fireEditingStopped(); + } + }); + } + + @Override + public Component getTableCellEditorComponent(JTable table, + Object value, boolean isSelected, int row, int column) + { + button.setSelected((boolean) value); + return button; + } + + @Override + public Object getCellEditorValue() + { + return button.isSelected(); + } + + } } diff --git a/src/jalview/jbgui/GSequenceLink.java b/src/jalview/jbgui/GSequenceLink.java index 2689946..f7914bf 100755 --- a/src/jalview/jbgui/GSequenceLink.java +++ b/src/jalview/jbgui/GSequenceLink.java @@ -28,7 +28,6 @@ import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; -import java.awt.Panel; import java.awt.Rectangle; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; @@ -40,7 +39,7 @@ import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.SwingConstants; -public class GSequenceLink extends Panel +public class GSequenceLink extends JPanel { public GSequenceLink() { diff --git a/src/jalview/urls/CustomUrlProvider.java b/src/jalview/urls/CustomUrlProvider.java index d88c571..fb0d676 100644 --- a/src/jalview/urls/CustomUrlProvider.java +++ b/src/jalview/urls/CustomUrlProvider.java @@ -29,9 +29,12 @@ import static jalview.util.UrlConstants.SEQUENCE_ID; import jalview.util.MessageManager; import jalview.util.UrlLink; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.StringTokenizer; import java.util.Vector; @@ -73,19 +76,24 @@ public class CustomUrlProvider extends UrlProviderImpl while (st.hasMoreElements()) { String name = st.nextToken(); - String url = st.nextToken(); - // check for '|' within a regex - int rxstart = url.indexOf(DELIM + DB_ACCESSION + DELIM); - if (rxstart == -1) - { - rxstart = url.indexOf(DELIM + SEQUENCE_ID + DELIM); - } - while (rxstart == -1 && url.indexOf("/=" + DELIM) == -1 - && st.hasMoreTokens()) + + if (!isMiriamId(name)) { - url = url + SEP + st.nextToken(); + // this one of our custom urls + String url = st.nextToken(); + // check for '|' within a regex + int rxstart = url.indexOf(DELIM + DB_ACCESSION + DELIM); + if (rxstart == -1) + { + rxstart = url.indexOf(DELIM + SEQUENCE_ID + DELIM); + } + while (rxstart == -1 && url.indexOf("/=" + DELIM) == -1 + && st.hasMoreTokens()) + { + url = url + SEP + st.nextToken(); + } + urls.put(name, new UrlLink(name + SEP + url)); } - urls.put(name, new UrlLink(name + SEP + url)); } } catch (Exception ex) { @@ -148,6 +156,27 @@ public class CustomUrlProvider extends UrlProviderImpl } @Override + public List getLinksForTable() + { + ArrayList displayLinks = new ArrayList(); + for (Entry entry : urls.entrySet()) + { + String key = entry.getKey(); + boolean isDefault = (key.equals(defaultUrl)); + boolean isSelected = true; // custom urls always selected + String displayLink = entry.getValue().toString().split("\\|")[1]; // TODO + // sort + // this + // out + // properly! + displayLinks.add(new UrlLinkDisplay(key, key, displayLink, + isSelected, + isDefault)); + } + return displayLinks; + } + + @Override public boolean setDefaultUrl(String id) { if (urls.containsKey(id)) @@ -248,6 +277,45 @@ public class CustomUrlProvider extends UrlProviderImpl } @Override + public void setUrlData(List links) + { + HashMap newurls = new HashMap(); + + Iterator it = links.iterator(); + while (it.hasNext()) + { + UrlLinkDisplay link = it.next(); + + // MIRIAM ids will be handled by a different UrlProvider class + if (!isMiriamId(link.getId())) + { + + // don't allow duplicate key names as entries will be overwritten + if (newurls.containsKey(link.getId())) + { + throw new IllegalArgumentException(MessageManager.formatMessage( + "exception.url_cannot_have_duplicate_id", link.getId())); + } + if (link.getIsSelected()) + { + newurls.put(link.getId(), + new UrlLink(link.getId() + SEP + link.getUrl())); + + // sort out default and selected ids + if (link.getIsDefault()) + { + setDefaultUrl(link.getId()); + } + } + // TODO KM make it possible to set and save selected custom urls + + } + + } + urls = newurls; + } + + @Override public String chooseDefaultUrl() { // unilaterally set the default id to the EMBL_EBI link diff --git a/src/jalview/urls/IdentifiersUrlProvider.java b/src/jalview/urls/IdentifiersUrlProvider.java index 7819136..a74ad07 100644 --- a/src/jalview/urls/IdentifiersUrlProvider.java +++ b/src/jalview/urls/IdentifiersUrlProvider.java @@ -35,6 +35,9 @@ import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map.Entry; import java.util.Vector; import org.json.simple.JSONArray; @@ -65,11 +68,13 @@ public class IdentifiersUrlProvider extends UrlProviderImpl { // File idFile = getIdentifiers(); urls = readIdentifiers(new FileReader(idFileName)); + selectedUrls = new ArrayList(); checkSelectionMatchesUrls(cachedUrlList); } catch (IOException e) { - + System.out.println("Exception reading URLs from identifiers.org"); + System.out.println(e.getMessage()); } } @@ -129,7 +134,7 @@ public class IdentifiersUrlProvider extends UrlProviderImpl private void checkSelectionMatchesUrls(String cachedUrlList) { - selectedUrls = new ArrayList(); + String[] prevSelected = cachedUrlList.split("\\" + SEP); for (String id : prevSelected) { @@ -145,7 +150,6 @@ public class IdentifiersUrlProvider extends UrlProviderImpl private void checkSelectionMatchesUrls(Vector idList) { - selectedUrls = new ArrayList(); String[] prevSelected = new String[idList.size()]; idList.toArray(prevSelected); for (String id : prevSelected) @@ -183,12 +187,19 @@ public class IdentifiersUrlProvider extends UrlProviderImpl @Override public String writeUrlsAsString() { - StringBuffer links = new StringBuffer(); - for (String k : selectedUrls) + if (!selectedUrls.isEmpty()) { - links.append(k); + StringBuffer links = new StringBuffer(); + for (String k : selectedUrls) + { + links.append(k); + links.append(SEP); + } + // remove last SEP + links.setLength(links.length() - 1); + return links.toString(); } - return links.toString(); + return ""; } @Override @@ -197,13 +208,63 @@ public class IdentifiersUrlProvider extends UrlProviderImpl Vector links = new Vector(); for (String key : selectedUrls) { - links.add(key + SEP + urls.get(key).get("url") + "/" + DELIM + links.add(urls.get(key).get("name") + SEP + urls.get(key).get("url") + + "/" + DELIM + DB_ACCESSION + DELIM); } return links; } @Override + public List getLinksForTable() + { + ArrayList displayLinks = new ArrayList(); + for (Entry> entry : urls.entrySet()) + { + String key = entry.getKey(); + boolean isDefault = (key == defaultUrl); + boolean isSelected = (selectedUrls.contains(key)); + displayLinks.add(new UrlLinkDisplay(key, + entry.getValue().get("name"), + entry.getValue().get("url") + + "/" + DELIM + DB_ACCESSION + DELIM, isSelected, isDefault)); + } + return displayLinks; + } + + @Override + public void setUrlData(List links) + { + selectedUrls = new ArrayList(); + + Iterator it = links.iterator(); + while (it.hasNext()) + { + UrlLinkDisplay link = it.next(); + + // Handle links with MIRIAM ids only + if (isMiriamId(link.getId())) // TODO separate use of name and id + { + // select/deselect links accordingly and set default url + + if (link.getIsSelected()) + { + if (urls.containsKey(link.getId())) + { + selectedUrls.add(link.getId()); + } + if (link.getIsDefault()) + { + setDefaultUrl(link.getId()); + } + + } + } + + } + } + + @Override public String getDefaultUrl(String seqid) { return urls.get(defaultUrl).get("url") + "/" + seqid; diff --git a/src/jalview/urls/UrlLinkDisplay.java b/src/jalview/urls/UrlLinkDisplay.java new file mode 100644 index 0000000..9afe6d3 --- /dev/null +++ b/src/jalview/urls/UrlLinkDisplay.java @@ -0,0 +1,152 @@ +/* + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ + +package jalview.urls; + + +/** + * UrlLink table row definition + * + * @author $author$ + * @version $Revision$ + */ + +public class UrlLinkDisplay +{ + private String id; // id is not supplied to display, but used to identify + // entries when saved + + private String name; + + private String url; + + private boolean isDefault; + + private boolean isSelected; + + public final static int ID = 4; + + public final static int URL = 1; + + public final static int SELECTED = 2; + + public final static int DEFAULT = 3; + + public final static int NAME = 0; + + public UrlLinkDisplay(String rowId, String rowName, String rowUrl, + boolean rowSelected, boolean rowDefault) + { + id = rowId; + name = rowName; + url = rowUrl; + isDefault = rowDefault; + isSelected = rowSelected; + } + + public String getId() + { + return id; + } + + public String getName() + { + return name; + } + + public String getUrl() + { + return url; + } + + public boolean getIsDefault() + { + return isDefault; + } + + public boolean getIsSelected() + { + return isSelected; + } + + public void setUrl(String rowUrl) + { + url = rowUrl; + } + + public void setIsDefault(boolean rowDefault) + { + isDefault = rowDefault; + } + + public void setIsSelected(boolean rowSelected) + { + isSelected = rowSelected; + } + + public Object getValue(int index) + { + switch (index) + { + case ID: + return id; + case URL: + return url; + case DEFAULT: + return isDefault; + case SELECTED: + return isSelected; + case NAME: + return name; + default: + return null; // TODO + } + } + + public void setValue(int index, Object value) + { + switch (index) + { + case ID: + id = (String) value; + break; + case URL: + url = (String) value; + break; + case DEFAULT: + isDefault = (boolean) value; + break; + case SELECTED: + isSelected = (boolean) value; + break; + case NAME: + name = (String) value; + break; + default: + // TODO + } + } + + public boolean isEditable(int index) + { + return ((index == DEFAULT) || (index == SELECTED)); + } +} diff --git a/src/jalview/urls/UrlLinkTableModel.java b/src/jalview/urls/UrlLinkTableModel.java new file mode 100644 index 0000000..103454b --- /dev/null +++ b/src/jalview/urls/UrlLinkTableModel.java @@ -0,0 +1,204 @@ +/* + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ + +package jalview.urls; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.swing.table.AbstractTableModel; + +/** + * TableModel for UrlLinks table + * + * @author $author$ + * @version $Revision$ + */ + +public class UrlLinkTableModel extends AbstractTableModel +{ + // local storage of data + // use LinkedHashMap to guarantee ordering remains the same, as + // we need to maintain a row/col mapping into the HashMap + private List data; + + private UrlProviderI dataProvider; + + private List displayColumns; + + // row in table which is currently the default + private int defaultRow; + + /** + * UrlLinkTableModel constructor + * + * @param baseData + * base data set to be presented in table + * @param entryNames + * keys of entries in baseData's nested hashmap. Should match order + * in displayColNames + * @param displayColNames + * names of columns to display in order. + * @param keyColName + * name of column corresponding to keys in baseData + */ + public UrlLinkTableModel(UrlProviderI baseData, + List displayColNames, + String keyColName) + { + dataProvider = baseData; + data = baseData.getLinksForTable(); + displayColumns = new ArrayList(); + displayColumns.add(keyColName); + displayColumns.addAll(displayColNames); + + // find the default row + defaultRow = 0; + Iterator it = data.iterator(); + while (it.hasNext()) + { + if (it.next().getIsDefault()) + { + break; + } + else + { + defaultRow++; + } + } + } + + @Override + public int getRowCount() + { + if (data == null) + { + return 0; + } + else + { + return data.size(); + } + } + + @Override + public int getColumnCount() + { + return displayColumns.size(); + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) + { + return data.get(rowIndex).getValue(columnIndex); + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) + { + return data.get(rowIndex).isEditable(columnIndex); + } + + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) + { + if ((columnIndex == UrlLinkDisplay.SELECTED) + && (rowIndex == defaultRow)) + { + // Selected urls column: can't deselect default URL + // refuse to edit: TODO show message box here + + } + else if (columnIndex == UrlLinkDisplay.DEFAULT) + { + // Default url column: exactly one row must always be true + if (rowIndex != defaultRow) + { + // selected row is not currently the default + // set the current default to false + data.get(defaultRow).setValue(columnIndex, false); + fireTableRowsUpdated(defaultRow, defaultRow); + + // set the default to be the selected row + defaultRow = rowIndex; + data.get(rowIndex).setValue(columnIndex, aValue); + + // default row must also be selected + if (!data.get(rowIndex).getIsSelected()) + { + data.get(rowIndex).setValue(UrlLinkDisplay.SELECTED, true); + } + fireTableRowsUpdated(rowIndex, rowIndex); + } + } + else + { + data.get(rowIndex).setValue(columnIndex, aValue); + fireTableRowsUpdated(rowIndex, rowIndex); + } + } + + @Override + public Class getColumnClass(int columnIndex) + { + return getValueAt(0, columnIndex).getClass(); + } + + @Override + public String getColumnName(int columnIndex) + { + return displayColumns.get(columnIndex); + } + + @Override + public String toString() + { + // update the UrlProvider from data list + dataProvider.setUrlData(data); + + return dataProvider.writeUrlsAsString(); + } + + public void removeRow(int rowIndex) + { + // remove the row from data + data.remove(rowIndex); + + // update default row + if (defaultRow > rowIndex) + { + defaultRow--; + } + + fireTableRowsDeleted(rowIndex, rowIndex); + } + + public int insertRow(String name, String url) + { + // add a row to the data + UrlLinkDisplay u = new UrlLinkDisplay(name, name, url, true, false); + int index = data.size(); + data.add(u); + fireTableRowsInserted(index, index); + return index; + } +} diff --git a/src/jalview/urls/UrlProvider.java b/src/jalview/urls/UrlProvider.java index af618f0..37e95e2 100644 --- a/src/jalview/urls/UrlProvider.java +++ b/src/jalview/urls/UrlProvider.java @@ -20,6 +20,8 @@ */ package jalview.urls; +import static jalview.util.UrlConstants.SEP; + import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -57,7 +59,7 @@ public class UrlProvider implements UrlProviderI UrlProviderI idProvider = new IdentifiersUrlProvider(cachedUrlList, ID_ORG_FILE); customProvider = new CustomUrlProvider(cachedUrlList); - // providers.add(idProvider); + providers.add(idProvider); providers.add(customProvider); // check that the defaultUrl still exists @@ -134,7 +136,10 @@ public class UrlProvider implements UrlProviderI for (UrlProviderI p : providers) { result += p.writeUrlsAsString(); + result += SEP; } + // remove last sep + result = result.substring(0, result.length() - 1); return result; } @@ -156,6 +161,26 @@ public class UrlProvider implements UrlProviderI } @Override + public List getLinksForTable() + { + ArrayList displayLinks = new ArrayList(); + for (UrlProviderI p : providers) + { + displayLinks.addAll(p.getLinksForTable()); + } + return displayLinks; + } + + @Override + public void setUrlData(List links) + { + for (UrlProviderI p : providers) + { + p.setUrlData(links); + } + } + + @Override public String getDefaultUrl(String seqid) { String link = null; @@ -207,4 +232,9 @@ public class UrlProvider implements UrlProviderI return customProvider.chooseDefaultUrl(); } + @Override + public boolean isUserEntry(String id) + { + return customProvider.isUserEntry(id); + } } diff --git a/src/jalview/urls/UrlProviderI.java b/src/jalview/urls/UrlProviderI.java index 4ade3bb..3841a50 100644 --- a/src/jalview/urls/UrlProviderI.java +++ b/src/jalview/urls/UrlProviderI.java @@ -21,6 +21,7 @@ package jalview.urls; import java.io.File; +import java.util.List; import java.util.Vector; /** @@ -56,6 +57,17 @@ public interface UrlProviderI Vector getLinksForDisplay(); /** + * Get names and urls as strings for display + * + */ + List getLinksForTable(); + + /** + * Set names and urls from display settings + */ + void setUrlData(List links); + + /** * Get the id of the default URL * * @return id of the default URL @@ -110,4 +122,9 @@ public interface UrlProviderI * @return id of chosen default url */ String chooseDefaultUrl(); + + /** + * Determine if id is for a user-defined URL + */ + boolean isUserEntry(String id); } diff --git a/src/jalview/urls/UrlProviderImpl.java b/src/jalview/urls/UrlProviderImpl.java index 554145d..4511919 100644 --- a/src/jalview/urls/UrlProviderImpl.java +++ b/src/jalview/urls/UrlProviderImpl.java @@ -20,9 +20,17 @@ */ package jalview.urls; +import java.util.List; import java.util.Vector; import java.util.regex.Pattern; +/** + * Leaf node of UrlProvider composite + * + * @author $author$ + * @version $Revision$ + */ + public class UrlProviderImpl implements UrlProviderI { private static final Pattern MIRIAM_PATTERN = Pattern @@ -84,11 +92,27 @@ public class UrlProviderImpl implements UrlProviderI return null; } + @Override + public List getLinksForTable() + { + return null; + } + + @Override + public void setUrlData(List links) + { + // deliberately left empty + } + protected boolean isMiriamId(String id) { return MIRIAM_PATTERN.matcher(id).matches(); } - + @Override + public boolean isUserEntry(String id) + { + return !isMiriamId(id); + } } -- 1.7.10.2