f4f6a9a4b724497bcf67c50e5034ce66c3c35ebb
[jalview.git] / src / jalview / gui / SlivkaPreferences.java
1 package jalview.gui;
2
3 import jalview.bin.Cache;
4 import jalview.util.MessageManager;
5 import jalview.ws.WSDiscovererI;
6 import jalview.ws.slivkaws.SlivkaWSDiscoverer;
7
8 import java.awt.BorderLayout;
9 import java.awt.Color;
10 import java.awt.Component;
11 import java.awt.Dimension;
12 import java.awt.Font;
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;
19 import java.net.URL;
20 import java.util.ArrayList;
21 import java.util.NoSuchElementException;
22
23 import javax.swing.BorderFactory;
24 import javax.swing.Box;
25 import javax.swing.BoxLayout;
26 import javax.swing.JButton;
27 import javax.swing.JOptionPane;
28 import javax.swing.JPanel;
29 import javax.swing.JProgressBar;
30 import javax.swing.JScrollPane;
31 import javax.swing.JTable;
32 import javax.swing.UIManager;
33 import javax.swing.table.AbstractTableModel;
34 import javax.swing.table.DefaultTableCellRenderer;
35
36 @SuppressWarnings("serial")
37 public class SlivkaPreferences extends JPanel
38 {
39   {
40     setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
41     setPreferredSize(new Dimension(500, 450));
42   }
43
44   WSDiscovererI discoverer;
45
46   private final ArrayList<String> urls = new ArrayList<>();
47
48   private final ArrayList<Integer> statuses = new ArrayList<>();
49
50   private final AbstractTableModel urlTableModel = new AbstractTableModel()
51   {
52     final String[] columnNames = { "Service URL", "Status" };
53
54     @Override
55     public String getColumnName(int col)
56     {
57       return columnNames[col];
58     }
59
60     @Override
61     public Object getValueAt(int rowIndex, int columnIndex)
62     {
63       switch (columnIndex)
64       {
65       case 0:
66         return urls.get(rowIndex);
67       case 1:
68         return statuses.get(rowIndex);
69       default:
70         throw new NoSuchElementException();
71       }
72     }
73
74     @Override
75     public int getRowCount()
76     {
77       return urls.size();
78     }
79
80     @Override
81     public int getColumnCount()
82     {
83       return 2;
84     }
85   };
86
87   private class WSStatusCellRenderer extends DefaultTableCellRenderer
88   {
89     @Override
90     public Component getTableCellRendererComponent(JTable table,
91         Object value, boolean isSelected, boolean hasFocus, int row,
92         int column)
93     {
94       setHorizontalAlignment(CENTER);
95       super.getTableCellRendererComponent(table, "\u25CF", isSelected,
96           hasFocus, row, column);
97       switch ((Integer) value)
98       {
99       case WSDiscovererI.STATUS_NO_SERVICES:
100         setForeground(Color.ORANGE);
101         break;
102       case WSDiscovererI.STATUS_OK:
103         setForeground(Color.GREEN);
104         break;
105       case WSDiscovererI.STATUS_INVALID:
106         setForeground(Color.RED);
107         break;
108       case WSDiscovererI.STATUS_UNKNOWN:
109       default:
110         setForeground(Color.LIGHT_GRAY);
111       }
112       return this;
113     }
114   }
115
116   private JTable urlListTable = new JTable(urlTableModel);
117   {
118     urlListTable.getColumnModel().getColumn(1).setMaxWidth(60);
119     urlListTable.getColumnModel().getColumn(1)
120         .setCellRenderer(new WSStatusCellRenderer());
121   }
122
123   // URL control panel buttons
124   JButton newWsUrl = new JButton(
125       MessageManager.getString("label.new_service_url"));
126
127   JButton editWsUrl = new JButton(
128       MessageManager.getString("label.edit_service_url"));
129
130   JButton deleteWsUrl = new JButton(
131       MessageManager.getString("label.delete_service_url"));
132
133   JButton moveUrlUp = new JButton(
134       MessageManager.getString("action.move_up"));
135
136   JButton moveUrlDown = new JButton(
137       MessageManager.getString("action.move_down"));
138
139   private String showEditUrlDialog(String oldUrl)
140   {
141     String input = (String) JvOptionPane
142         .showInternalInputDialog(
143             this, 
144             MessageManager.getString("label.url:"),
145             UIManager.getString("OptionPane.inputDialogTitle", MessageManager.getLocale()),
146             JOptionPane.QUESTION_MESSAGE,
147             null,
148             null,
149             oldUrl);
150     if (input == null)
151     {
152       return null;
153     }
154     try
155     {
156       new URL(input);
157     } catch (MalformedURLException ex)
158     {
159       JvOptionPane.showInternalMessageDialog(this,
160           MessageManager.getString("label.invalid_url"),
161           UIManager.getString("OptionPane.messageDialogTitle",
162               MessageManager.getLocale()),
163           JOptionPane.WARNING_MESSAGE);
164       return null;
165     }
166     return input;
167   }
168
169   // Button Action Listeners
170   private ActionListener newUrlAction = (ActionEvent e) -> {
171     final String input = showEditUrlDialog("");
172     if (input != null)
173     {
174       urls.add(input);
175       statuses.add(discoverer.getServerStatusFor(input));
176       urlTableModel.fireTableRowsInserted(urls.size(), urls.size());
177       discoverer.setServiceUrls(urls);
178     }
179   };
180
181   private ActionListener editUrlAction = (ActionEvent e) -> {
182     final int i = urlListTable.getSelectedRow();
183     if (i >= 0)
184     {
185       final String input = showEditUrlDialog(urls.get(i));
186       if (input != null)
187       {
188         urls.set(i, input);
189         statuses.set(i, discoverer.getServerStatusFor(input));
190         urlTableModel.fireTableRowsUpdated(i, i);
191         discoverer.setServiceUrls(urls);
192       }
193     }
194   };
195
196   private ActionListener deleteUrlAction = (ActionEvent e) -> {
197     final int i = urlListTable.getSelectedRow();
198     if (i >= 0)
199     {
200       urls.remove(i);
201       statuses.remove(i);
202       urlTableModel.fireTableRowsDeleted(i, i);
203       discoverer.setServiceUrls(urls);
204     }
205   };
206
207   private ActionListener moveUrlUpAction = (ActionEvent e) -> {
208     final int i = urlListTable.getSelectedRow();
209     if (i > 0)
210     {
211       moveTableRow(i, i - 1);
212       discoverer.setServiceUrls(urls);
213     }
214   };
215
216   private ActionListener moveUrlDownAction = (ActionEvent e) -> {
217     final int i = urlListTable.getSelectedRow();
218     if (i >= 0 && i < urls.size() - 1)
219     {
220       moveTableRow(i, i + 1);
221       discoverer.setServiceUrls(urls);
222     }
223   };
224
225   private MouseListener tableClickListener = new MouseAdapter()
226   {
227     final ActionEvent actionEvent = new ActionEvent(urlListTable,
228         ActionEvent.ACTION_PERFORMED, "edit");
229
230     @Override
231     public void mouseClicked(MouseEvent e)
232     {
233       if (e.getClickCount() > 1)
234       {
235         editUrlAction.actionPerformed(actionEvent);
236       }
237     }
238   };
239
240   // Setting up URL list Pane
241   {
242     Font font = new Font("Verdana", Font.PLAIN, 10);
243     JPanel urlPaneContainer = new JPanel(new BorderLayout(5, 5));
244     urlPaneContainer.setBorder(BorderFactory.createCompoundBorder(
245         BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),
246             "Slivka Web Services"),
247         BorderFactory.createEmptyBorder(10, 5, 5, 5)));
248
249     newWsUrl.setFont(font);
250     editWsUrl.setFont(font);
251     deleteWsUrl.setFont(font);
252     moveUrlUp.setFont(font);
253     moveUrlDown.setFont(font);
254     JPanel editContainer = new JPanel();
255     editContainer.add(newWsUrl);
256     editContainer.add(editWsUrl);
257     editContainer.add(deleteWsUrl);
258     urlPaneContainer.add(editContainer, BorderLayout.PAGE_END);
259
260     JPanel moveContainer = new JPanel();
261     moveContainer
262         .setLayout(new BoxLayout(moveContainer, BoxLayout.PAGE_AXIS));
263     moveContainer.add(moveUrlUp);
264     moveContainer.add(Box.createRigidArea(new Dimension(0, 5)));
265     moveContainer.add(moveUrlDown);
266     urlPaneContainer.add(moveContainer, BorderLayout.LINE_START);
267
268     urlPaneContainer.add(new JScrollPane(urlListTable),
269         BorderLayout.CENTER);
270     this.add(urlPaneContainer);
271
272     // Connecting action listeners
273     urlListTable.addMouseListener(tableClickListener);
274     newWsUrl.addActionListener(newUrlAction);
275     editWsUrl.addActionListener(editUrlAction);
276     deleteWsUrl.addActionListener(deleteUrlAction);
277     moveUrlUp.addActionListener(moveUrlUpAction);
278     moveUrlDown.addActionListener(moveUrlDownAction);
279   }
280
281   private void moveTableRow(int fromIndex, int toIndex)
282   {
283     String url = urls.get(fromIndex);
284     int status = statuses.get(fromIndex);
285     urls.set(fromIndex, urls.get(toIndex));
286     statuses.set(fromIndex, statuses.get(toIndex));
287     urls.set(toIndex, url);
288     statuses.set(toIndex, status);
289     if (urlListTable.getSelectedRow() == fromIndex)
290     {
291       urlListTable.setRowSelectionInterval(toIndex, toIndex);
292     }
293     int firstRow = Math.min(toIndex, fromIndex);
294     int lastRow = Math.max(fromIndex, toIndex);
295     urlTableModel.fireTableRowsUpdated(firstRow, lastRow);
296   }
297
298   // Discoverer reloading buttons
299   JButton refreshServices = new JButton(
300       MessageManager.getString("action.refresh_services"));
301
302   JButton resetServices = new JButton(
303       MessageManager.getString("action.reset_services"));
304
305   JProgressBar progressBar = new JProgressBar();
306
307   // Discoverer buttons action listeners
308   private ActionListener refreshServicesAction = (ActionEvent e) -> {
309     new Thread(() -> {
310       progressBar.setVisible(true);
311       Cache.log.info("Requesting service reload");
312       Desktop.instance.startServiceDiscovery(discoverer, true);
313       Cache.log.info("Reloading done");
314       progressBar.setVisible(false);
315     }).start();
316   };
317
318   private ActionListener resetServicesAction = (ActionEvent e) -> {
319     discoverer.setServiceUrls(null);
320     urls.clear();
321     statuses.clear();
322     urls.addAll(discoverer.getServiceUrls());
323     for (String url : urls)
324     {
325       statuses.add(discoverer.getServerStatusFor(url));
326     }
327     urlTableModel.fireTableDataChanged();
328   };
329
330   {
331     Font font = new Font("Verdana", Font.PLAIN, 11);
332     refreshServices.setFont(font);
333     resetServices.setFont(font);
334     JPanel container = new JPanel();
335     container.add(refreshServices);
336     container.add(resetServices);
337     this.add(container);
338
339     // Connecting action listeners
340     refreshServices.addActionListener(refreshServicesAction);
341     resetServices.addActionListener(resetServicesAction);
342   }
343
344   {
345     progressBar.setVisible(false);
346     progressBar.setIndeterminate(true);
347     add(progressBar);
348   }
349
350   SlivkaPreferences()
351   {
352     // Initial URLs loading
353     discoverer = SlivkaWSDiscoverer.getInstance();
354     urls.addAll(discoverer.getServiceUrls());
355     for (String url : urls)
356     {
357       statuses.add(discoverer.getServerStatusFor(url));
358     }
359   }
360 }