From 57447cbc359ed9a0c8826540079898677ef86660 Mon Sep 17 00:00:00 2001 From: MMWarowny Date: Tue, 4 Feb 2020 11:28:42 +0000 Subject: [PATCH] JAL-3515 Build a WSPreferences page for Slivka services. --- src/jalview/gui/Preferences.java | 6 +- src/jalview/gui/SlivkaPreferences.java | 358 ++++++++++++++++++++++++++++++++ src/jalview/jbgui/GPreferences.java | 4 + 3 files changed, 367 insertions(+), 1 deletion(-) create mode 100644 src/jalview/gui/SlivkaPreferences.java diff --git a/src/jalview/gui/Preferences.java b/src/jalview/gui/Preferences.java index a0a7511..c921331 100755 --- a/src/jalview/gui/Preferences.java +++ b/src/jalview/gui/Preferences.java @@ -192,6 +192,8 @@ public class Preferences extends GPreferences private WsPreferences wsPrefs; + private SlivkaPreferences slivkaPrefs; + private OptionsParam promptEachTimeOpt = new OptionsParam( MessageManager.getString("label.prompt_each_time"), "Prompt each time"); @@ -212,6 +214,8 @@ public class Preferences extends GPreferences frame.setContentPane(this); wsPrefs = new WsPreferences(); wsTab.add(wsPrefs, BorderLayout.CENTER); + slivkaTab.add(slivkaPrefs = new SlivkaPreferences(), + BorderLayout.CENTER); int width = 500, height = 450; new jalview.util.Platform(); if (Platform.isAMac()) @@ -481,7 +485,7 @@ public class Preferences extends GPreferences doReset.addActionListener(onReset); // filter to display only custom urls - final RowFilter customUrlFilter = new RowFilter() + final RowFilter customUrlFilter = new RowFilter<>() { @Override public boolean include( diff --git a/src/jalview/gui/SlivkaPreferences.java b/src/jalview/gui/SlivkaPreferences.java new file mode 100644 index 0000000..4df4bf6 --- /dev/null +++ b/src/jalview/gui/SlivkaPreferences.java @@ -0,0 +1,358 @@ +package jalview.gui; + +import jalview.bin.Cache; +import jalview.util.MessageManager; +import jalview.ws.WSDiscovererI; +import jalview.ws.slivkaws.SlivkaWSDiscoverer; + +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; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.NoSuchElementException; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.UIManager; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableCellRenderer; + +@SuppressWarnings("serial") +public class SlivkaPreferences extends JPanel +{ + { + setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); + setPreferredSize(new Dimension(500, 450)); + } + + WSDiscovererI discoverer; + + private final ArrayList urls = new ArrayList<>(); + + private final ArrayList statuses = new ArrayList<>(); + + private final AbstractTableModel urlTableModel = new AbstractTableModel() + { + final String[] columnNames = { "Service URL", "Status" }; + + @Override + public String getColumnName(int col) + { + return columnNames[col]; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) + { + switch (columnIndex) + { + case 0: + return urls.get(rowIndex); + case 1: + return statuses.get(rowIndex); + default: + throw new NoSuchElementException(); + } + } + + @Override + public int getRowCount() + { + return urls.size(); + } + + @Override + public int getColumnCount() + { + return 2; + } + }; + + private class WSStatusCellRenderer extends DefaultTableCellRenderer + { + @Override + public Component getTableCellRendererComponent(JTable table, + Object value, boolean isSelected, boolean hasFocus, int row, + int column) + { + setHorizontalAlignment(CENTER); + super.getTableCellRendererComponent(table, "\u25CF", isSelected, + hasFocus, row, column); + switch ((Integer) value) + { + case WSDiscovererI.STATUS_NO_SERVICES: + setForeground(Color.ORANGE); + break; + case WSDiscovererI.STATUS_OK: + setForeground(Color.GREEN); + break; + case WSDiscovererI.STATUS_INVALID: + setForeground(Color.RED); + break; + case WSDiscovererI.STATUS_UNKNOWN: + default: + setForeground(Color.LIGHT_GRAY); + } + return this; + } + } + + private JTable urlListTable = new JTable(urlTableModel); + { + urlListTable.getColumnModel().getColumn(1).setMaxWidth(60); + urlListTable.getColumnModel().getColumn(1) + .setCellRenderer(new WSStatusCellRenderer()); + } + + // URL control panel buttons + JButton newWsUrl = new JButton( + MessageManager.getString("label.new_service_url")); + + JButton editWsUrl = new JButton( + MessageManager.getString("label.edit_service_url")); + + JButton deleteWsUrl = new JButton( + MessageManager.getString("label.delete_service_url")); + + JButton moveUrlUp = new JButton( + MessageManager.getString("action.move_up")); + + JButton moveUrlDown = new JButton( + MessageManager.getString("action.move_down")); + + private String showEditUrlDialog(String oldUrl) + { + String input = (String) JOptionPane + .showInternalInputDialog( + this, + MessageManager.getString("label.url:"), + UIManager.getString("OptionPane.inputDialogTitle", MessageManager.getLocale()), + JOptionPane.QUESTION_MESSAGE, + null, + null, + oldUrl); + if (input == null) + { + return null; + } + try + { + new URL(input); + } catch (MalformedURLException ex) + { + JOptionPane.showMessageDialog(this, + MessageManager.getString("label.invalid_url"), "Warning", + JOptionPane.WARNING_MESSAGE); + return null; + } + return input; + } + + // Button Action Listeners + private ActionListener newUrlAction = (ActionEvent e) -> { + final String input = showEditUrlDialog(""); + if (input != null) + { + urls.add(input); + statuses.add(discoverer.getServerStatusFor(input)); + urlTableModel.fireTableRowsInserted(urls.size(), urls.size()); + discoverer.setServiceUrls(urls); + } + }; + + private ActionListener editUrlAction = (ActionEvent e) -> { + final int i = urlListTable.getSelectedRow(); + if (i >= 0) + { + final String input = showEditUrlDialog(urls.get(i)); + if (input != null) + { + urls.set(i, input); + statuses.set(i, discoverer.getServerStatusFor(input)); + urlTableModel.fireTableRowsUpdated(i, i); + discoverer.setServiceUrls(urls); + } + } + }; + + private ActionListener deleteUrlAction = (ActionEvent e) -> { + final int i = urlListTable.getSelectedRow(); + if (i >= 0) + { + urls.remove(i); + statuses.remove(i); + urlTableModel.fireTableRowsDeleted(i, i); + discoverer.setServiceUrls(urls); + } + }; + + private ActionListener moveUrlUpAction = (ActionEvent e) -> { + int i = urlListTable.getSelectedRow(); + if (i > 0) + { + moveTableRow(i, i - 1); + discoverer.setServiceUrls(urls); + } + }; + + private ActionListener moveUrlDownAction = (ActionEvent e) -> { + int i = urlListTable.getSelectedRow(); + if (i >= 0 && i < urls.size() - 1) + { + moveTableRow(i, i + 1); + discoverer.setServiceUrls(urls); + } + }; + + private MouseListener tableClickListener = new MouseAdapter() + { + final ActionEvent actionEvent = new ActionEvent(urlListTable, + ActionEvent.ACTION_PERFORMED, "edit"); + + @Override + public void mouseClicked(MouseEvent e) + { + if (e.getClickCount() > 1) + { + editUrlAction.actionPerformed(actionEvent); + } + } + }; + + // Setting up URL list Pane + { + Font font = new Font("Verdana", Font.PLAIN, 10); + JPanel urlPaneContainer = new JPanel(new BorderLayout(5, 5)); + urlPaneContainer.setBorder(BorderFactory.createCompoundBorder( + BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), + "Slivka Web Services"), + BorderFactory.createEmptyBorder(10, 5, 5, 5))); + + newWsUrl.setFont(font); + editWsUrl.setFont(font); + deleteWsUrl.setFont(font); + moveUrlUp.setFont(font); + moveUrlDown.setFont(font); + JPanel editContainer = new JPanel(); + editContainer.add(newWsUrl); + editContainer.add(editWsUrl); + editContainer.add(deleteWsUrl); + urlPaneContainer.add(editContainer, BorderLayout.PAGE_END); + + JPanel moveContainer = new JPanel(); + moveContainer + .setLayout(new BoxLayout(moveContainer, BoxLayout.PAGE_AXIS)); + moveContainer.add(moveUrlUp); + moveContainer.add(Box.createRigidArea(new Dimension(0, 5))); + moveContainer.add(moveUrlDown); + urlPaneContainer.add(moveContainer, BorderLayout.LINE_START); + + urlPaneContainer.add(new JScrollPane(urlListTable), + BorderLayout.CENTER); + this.add(urlPaneContainer); + + // Connecting action listeners + urlListTable.addMouseListener(tableClickListener); + newWsUrl.addActionListener(newUrlAction); + editWsUrl.addActionListener(editUrlAction); + deleteWsUrl.addActionListener(deleteUrlAction); + moveUrlUp.addActionListener(moveUrlUpAction); + moveUrlDown.addActionListener(moveUrlDownAction); + } + + private void moveTableRow(int fromIndex, int toIndex) + { + String url = urls.get(fromIndex); + int status = statuses.get(fromIndex); + urls.set(fromIndex, urls.get(toIndex)); + statuses.set(fromIndex, statuses.get(toIndex)); + urls.set(toIndex, url); + statuses.set(toIndex, status); + if (urlListTable.getSelectedRow() == fromIndex) + { + urlListTable.setRowSelectionInterval(toIndex, toIndex); + } + int firstRow = Math.min(toIndex, fromIndex); + int lastRow = Math.max(fromIndex, toIndex); + urlTableModel.fireTableRowsUpdated(firstRow, lastRow); + } + + // Discoverer reloading buttons + JButton refreshServices = new JButton( + MessageManager.getString("action.refresh_services")); + + JButton resetServices = new JButton( + MessageManager.getString("action.reset_services")); + + JProgressBar progressBar = new JProgressBar(); + + // Discoverer buttons action listeners + private ActionListener refreshServicesAction = (ActionEvent e) -> { + new Thread(() -> { + progressBar.setVisible(true); + Cache.log.info("Requesting service reload"); + Desktop.instance.startServiceDiscovery(discoverer, true); + Cache.log.info("Reloading done"); + progressBar.setVisible(false); + }).start(); + }; + + private ActionListener resetServicesAction = (ActionEvent e) -> { + discoverer.setServiceUrls(null); + urls.clear(); + statuses.clear(); + urls.addAll(discoverer.getServiceUrls()); + for (String url : urls) + { + statuses.add(discoverer.getServerStatusFor(url)); + } + urlTableModel.fireTableDataChanged(); + }; + + { + Font font = new Font("Verdana", Font.PLAIN, 11); + refreshServices.setFont(font); + resetServices.setFont(font); + JPanel container = new JPanel(); + container.add(refreshServices); + container.add(resetServices); + this.add(container); + + // Connecting action listeners + refreshServices.addActionListener(refreshServicesAction); + resetServices.addActionListener(resetServicesAction); + } + + { + progressBar.setVisible(false); + progressBar.setIndeterminate(true); + add(progressBar); + } + + SlivkaPreferences() + { + // Initial URLs loading + discoverer = SlivkaWSDiscoverer.getInstance(); + urls.addAll(discoverer.getServiceUrls()); + for (String url : urls) + { + statuses.add(discoverer.getServerStatusFor(url)); + } + } +} diff --git a/src/jalview/jbgui/GPreferences.java b/src/jalview/jbgui/GPreferences.java index ca11541..34a7c75 100755 --- a/src/jalview/jbgui/GPreferences.java +++ b/src/jalview/jbgui/GPreferences.java @@ -314,6 +314,8 @@ public class GPreferences extends JPanel */ protected JPanel wsTab = new JPanel(); + protected JPanel slivkaTab = new JPanel(); + /* * Backups tab components * a lot of these are member variables instead of local variables only so that they @@ -421,6 +423,8 @@ public class GPreferences extends JPanel */ wsTab.setLayout(new BorderLayout()); tabbedPane.add(wsTab, MessageManager.getString("label.web_services")); + slivkaTab.setLayout(new BorderLayout()); + tabbedPane.add(slivkaTab, "Slivka Services"); /* * Handler to validate a tab before leaving it - currently only for -- 1.7.10.2