3 import jalview.bin.Cache;
4 import jalview.util.MessageManager;
5 import jalview.ws.WSDiscovererI;
6 import jalview.ws.slivkaws.SlivkaWSDiscoverer;
8 import java.awt.BorderLayout;
10 import java.awt.Component;
11 import java.awt.Dimension;
13 import java.awt.event.ActionEvent;
14 import java.awt.event.ActionListener;
15 import java.awt.event.MouseAdapter;
16 import java.awt.event.MouseEvent;
17 import java.awt.event.MouseListener;
18 import java.net.MalformedURLException;
20 import java.util.ArrayList;
21 import java.util.HashMap;
23 import java.util.NoSuchElementException;
24 import java.util.concurrent.CompletableFuture;
26 import javax.swing.BorderFactory;
27 import javax.swing.Box;
28 import javax.swing.BoxLayout;
29 import javax.swing.JButton;
30 import javax.swing.JOptionPane;
31 import javax.swing.JPanel;
32 import javax.swing.JProgressBar;
33 import javax.swing.JScrollPane;
34 import javax.swing.JTable;
35 import javax.swing.SwingUtilities;
36 import javax.swing.UIManager;
37 import javax.swing.table.AbstractTableModel;
38 import javax.swing.table.DefaultTableCellRenderer;
40 @SuppressWarnings("serial")
41 public class SlivkaPreferences extends JPanel
44 setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
45 setPreferredSize(new Dimension(500, 450));
48 WSDiscovererI discoverer;
50 private final ArrayList<String> urls = new ArrayList<>();
52 private final Map<String, Integer> statuses = new HashMap<>();
54 private final AbstractTableModel urlTableModel = new AbstractTableModel()
56 final String[] columnNames = { "Service URL", "Status" };
59 public String getColumnName(int col)
61 return columnNames[col];
65 public Object getValueAt(int rowIndex, int columnIndex)
70 return urls.get(rowIndex);
72 return statuses.getOrDefault(urls.get(rowIndex), WSDiscovererI.STATUS_UNKNOWN);
74 throw new NoSuchElementException();
79 public int getRowCount()
85 public int getColumnCount()
91 private class WSStatusCellRenderer extends DefaultTableCellRenderer
94 public Component getTableCellRendererComponent(JTable table,
95 Object value, boolean isSelected, boolean hasFocus, int row,
98 setHorizontalAlignment(CENTER);
99 super.getTableCellRendererComponent(table, "\u25CF", isSelected,
100 hasFocus, row, column);
101 switch ((Integer) value)
103 case WSDiscovererI.STATUS_NO_SERVICES:
104 setForeground(Color.ORANGE);
106 case WSDiscovererI.STATUS_OK:
107 setForeground(Color.GREEN);
109 case WSDiscovererI.STATUS_INVALID:
110 setForeground(Color.RED);
112 case WSDiscovererI.STATUS_UNKNOWN:
114 setForeground(Color.LIGHT_GRAY);
120 private JTable urlListTable = new JTable(urlTableModel);
122 urlListTable.getColumnModel().getColumn(1).setMaxWidth(60);
123 urlListTable.getColumnModel().getColumn(1)
124 .setCellRenderer(new WSStatusCellRenderer());
127 // URL control panel buttons
128 JButton newWsUrl = new JButton(
129 MessageManager.getString("label.new_service_url"));
131 JButton editWsUrl = new JButton(
132 MessageManager.getString("label.edit_service_url"));
134 JButton deleteWsUrl = new JButton(
135 MessageManager.getString("label.delete_service_url"));
137 JButton moveUrlUp = new JButton(
138 MessageManager.getString("action.move_up"));
140 JButton moveUrlDown = new JButton(
141 MessageManager.getString("action.move_down"));
143 private String showEditUrlDialog(String oldUrl)
145 String input = (String) JvOptionPane
146 .showInternalInputDialog(
148 MessageManager.getString("label.url:"),
149 UIManager.getString("OptionPane.inputDialogTitle", MessageManager.getLocale()),
150 JOptionPane.QUESTION_MESSAGE,
161 } catch (MalformedURLException ex)
163 JvOptionPane.showInternalMessageDialog(this,
164 MessageManager.getString("label.invalid_url"),
165 UIManager.getString("OptionPane.messageDialogTitle",
166 MessageManager.getLocale()),
167 JOptionPane.WARNING_MESSAGE);
173 // Button Action Listeners
174 private ActionListener newUrlAction = (ActionEvent e) -> {
175 final String input = showEditUrlDialog("");
179 reloadStatusForUrl(input);
180 urlTableModel.fireTableRowsInserted(urls.size(), urls.size());
181 discoverer.setServiceUrls(urls);
185 private ActionListener editUrlAction = (ActionEvent e) -> {
186 final int i = urlListTable.getSelectedRow();
189 final String input = showEditUrlDialog(urls.get(i));
193 statuses.remove(input);
194 reloadStatusForUrl(input);
195 urlTableModel.fireTableRowsUpdated(i, i);
196 discoverer.setServiceUrls(urls);
201 private ActionListener deleteUrlAction = (ActionEvent e) -> {
202 final int i = urlListTable.getSelectedRow();
207 urlTableModel.fireTableRowsDeleted(i, i);
208 discoverer.setServiceUrls(urls);
212 private ActionListener moveUrlUpAction = (ActionEvent e) -> {
213 final int i = urlListTable.getSelectedRow();
216 moveTableRow(i, i - 1);
217 discoverer.setServiceUrls(urls);
221 private ActionListener moveUrlDownAction = (ActionEvent e) -> {
222 final int i = urlListTable.getSelectedRow();
223 if (i >= 0 && i < urls.size() - 1)
225 moveTableRow(i, i + 1);
226 discoverer.setServiceUrls(urls);
230 private MouseListener tableClickListener = new MouseAdapter()
232 final ActionEvent actionEvent = new ActionEvent(urlListTable,
233 ActionEvent.ACTION_PERFORMED, "edit");
236 public void mouseClicked(MouseEvent e)
238 if (e.getClickCount() > 1)
240 editUrlAction.actionPerformed(actionEvent);
245 // Setting up URL list Pane
247 Font font = new Font("Verdana", Font.PLAIN, 10);
248 JPanel urlPaneContainer = new JPanel(new BorderLayout(5, 5));
249 urlPaneContainer.setBorder(BorderFactory.createCompoundBorder(
250 BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),
251 "Slivka Web Services"),
252 BorderFactory.createEmptyBorder(10, 5, 5, 5)));
254 newWsUrl.setFont(font);
255 editWsUrl.setFont(font);
256 deleteWsUrl.setFont(font);
257 moveUrlUp.setFont(font);
258 moveUrlDown.setFont(font);
259 JPanel editContainer = new JPanel();
260 editContainer.add(newWsUrl);
261 editContainer.add(editWsUrl);
262 editContainer.add(deleteWsUrl);
263 urlPaneContainer.add(editContainer, BorderLayout.PAGE_END);
265 JPanel moveContainer = new JPanel();
267 .setLayout(new BoxLayout(moveContainer, BoxLayout.PAGE_AXIS));
268 moveContainer.add(moveUrlUp);
269 moveContainer.add(Box.createRigidArea(new Dimension(0, 5)));
270 moveContainer.add(moveUrlDown);
271 urlPaneContainer.add(moveContainer, BorderLayout.LINE_START);
273 urlPaneContainer.add(new JScrollPane(urlListTable),
274 BorderLayout.CENTER);
275 this.add(urlPaneContainer);
277 // Connecting action listeners
278 urlListTable.addMouseListener(tableClickListener);
279 newWsUrl.addActionListener(newUrlAction);
280 editWsUrl.addActionListener(editUrlAction);
281 deleteWsUrl.addActionListener(deleteUrlAction);
282 moveUrlUp.addActionListener(moveUrlUpAction);
283 moveUrlDown.addActionListener(moveUrlDownAction);
286 private void moveTableRow(int fromIndex, int toIndex)
288 String url = urls.get(fromIndex);
289 int status = statuses.get(fromIndex);
290 urls.set(fromIndex, urls.get(toIndex));
291 urls.set(toIndex, url);
292 if (urlListTable.getSelectedRow() == fromIndex)
294 urlListTable.setRowSelectionInterval(toIndex, toIndex);
296 int firstRow = Math.min(toIndex, fromIndex);
297 int lastRow = Math.max(fromIndex, toIndex);
298 urlTableModel.fireTableRowsUpdated(firstRow, lastRow);
301 // Discoverer reloading buttons
302 JButton refreshServices = new JButton(
303 MessageManager.getString("action.refresh_services"));
305 JButton resetServices = new JButton(
306 MessageManager.getString("action.reset_services"));
308 JProgressBar progressBar = new JProgressBar();
310 // Discoverer buttons action listeners
311 private ActionListener refreshServicesAction = (ActionEvent e) -> {
312 progressBar.setVisible(true);
313 Cache.log.info("Requesting service reload");
314 discoverer.startDiscoverer().handle((_discoverer, exception) -> {
315 if (exception == null)
317 Cache.log.info("Reloading done");
321 Cache.log.error("Reloading failed", exception);
323 SwingUtilities.invokeLater(() -> progressBar.setVisible(false));
328 private ActionListener resetServicesAction = (ActionEvent e) -> {
329 discoverer.setServiceUrls(null);
332 urls.addAll(discoverer.getServiceUrls());
333 for (String url : urls)
335 reloadStatusForUrl(url);
337 urlTableModel.fireTableDataChanged();
341 Font font = new Font("Verdana", Font.PLAIN, 11);
342 refreshServices.setFont(font);
343 resetServices.setFont(font);
344 JPanel container = new JPanel();
345 container.add(refreshServices);
346 container.add(resetServices);
349 // Connecting action listeners
350 refreshServices.addActionListener(refreshServicesAction);
351 resetServices.addActionListener(resetServicesAction);
355 progressBar.setVisible(false);
356 progressBar.setIndeterminate(true);
362 // Initial URLs loading
363 discoverer = SlivkaWSDiscoverer.getInstance();
364 urls.addAll(discoverer.getServiceUrls());
365 for (String url : urls)
367 reloadStatusForUrl(url);
371 private void reloadStatusForUrl(String url)
373 CompletableFuture.supplyAsync(() -> discoverer.getServerStatusFor(url))
374 .thenAccept((status) -> {
375 statuses.put(url, status);
376 int row = urls.indexOf(url);
378 urlTableModel.fireTableCellUpdated(row, 1);