Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
AppVarnaBinding | 67 | 124 | 55 | ||
AppVarnaBinding.BackupHolder | 316 | 13 | 7 |
1 | /* | |
2 | * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) | |
3 | * Copyright (C) $$Year-Rel$$ The Jalview Authors | |
4 | * | |
5 | * This file is part of Jalview. | |
6 | * | |
7 | * Jalview is free software: you can redistribute it and/or | |
8 | * modify it under the terms of the GNU General Public License | |
9 | * as published by the Free Software Foundation, either version 3 | |
10 | * of the License, or (at your option) any later version. | |
11 | * | |
12 | * Jalview is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty | |
14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |
15 | * PURPOSE. See the GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with Jalview. If not, see <http://www.gnu.org/licenses/>. | |
19 | * The Jalview Authors are detailed in the 'AUTHORS' file. | |
20 | */ | |
21 | package jalview.gui; | |
22 | ||
23 | import jalview.datamodel.SequenceI; | |
24 | import jalview.ext.varna.JalviewVarnaBinding; | |
25 | import jalview.structure.AtomSpec; | |
26 | import jalview.util.MessageManager; | |
27 | ||
28 | import java.awt.BorderLayout; | |
29 | import java.awt.Color; | |
30 | import java.awt.Component; | |
31 | import java.awt.Dimension; | |
32 | import java.awt.datatransfer.DataFlavor; | |
33 | import java.awt.datatransfer.Transferable; | |
34 | import java.awt.dnd.DnDConstants; | |
35 | import java.awt.dnd.DropTarget; | |
36 | import java.awt.dnd.DropTargetAdapter; | |
37 | import java.awt.dnd.DropTargetDropEvent; | |
38 | import java.awt.event.ComponentEvent; | |
39 | import java.awt.event.MouseAdapter; | |
40 | import java.awt.event.MouseEvent; | |
41 | import java.io.File; | |
42 | import java.io.IOException; | |
43 | import java.util.ArrayList; | |
44 | import java.util.Collection; | |
45 | import java.util.List; | |
46 | ||
47 | import javax.swing.DefaultListModel; | |
48 | import javax.swing.DefaultListSelectionModel; | |
49 | import javax.swing.JLabel; | |
50 | import javax.swing.JList; | |
51 | import javax.swing.JPanel; | |
52 | import javax.swing.JScrollPane; | |
53 | import javax.swing.ListModel; | |
54 | import javax.swing.ListSelectionModel; | |
55 | import javax.swing.event.ListSelectionEvent; | |
56 | import javax.swing.event.ListSelectionListener; | |
57 | ||
58 | import fr.orsay.lri.varna.VARNAPanel; | |
59 | import fr.orsay.lri.varna.components.ReorderableJList; | |
60 | import fr.orsay.lri.varna.exceptions.ExceptionLoadingFailed; | |
61 | import fr.orsay.lri.varna.exceptions.ExceptionNAViewAlgorithm; | |
62 | import fr.orsay.lri.varna.exceptions.ExceptionNonEqualLength; | |
63 | import fr.orsay.lri.varna.models.FullBackup; | |
64 | import fr.orsay.lri.varna.models.VARNAConfig; | |
65 | import fr.orsay.lri.varna.models.rna.RNA; | |
66 | ||
67 | public class AppVarnaBinding extends JalviewVarnaBinding | |
68 | { | |
69 | public VARNAPanel vp; | |
70 | ||
71 | protected JPanel _listPanel = new JPanel(); | |
72 | ||
73 | private ReorderableJList _sideList = null; | |
74 | ||
75 | private static String errorOpt = "error"; | |
76 | ||
77 | @SuppressWarnings("unused") | |
78 | private boolean _error; | |
79 | ||
80 | private Color _backgroundColor = Color.white; | |
81 | ||
82 | private static int _nextID = 1; | |
83 | ||
84 | @SuppressWarnings("unused") | |
85 | private int _algoCode; | |
86 | ||
87 | private BackupHolder _rnaList; | |
88 | ||
89 | /** | |
90 | * Constructor | |
91 | */ | |
92 | 0 | public AppVarnaBinding() |
93 | { | |
94 | 0 | init(); |
95 | } | |
96 | ||
97 | /** | |
98 | * Constructs the VARNAPanel and an (empty) selection list of structures to | |
99 | * show in it | |
100 | */ | |
101 | 0 | private void init() |
102 | { | |
103 | 0 | DefaultListModel<FullBackup> dlm = new DefaultListModel<FullBackup>(); |
104 | ||
105 | 0 | int marginTools = 40; |
106 | ||
107 | 0 | DefaultListSelectionModel m = new DefaultListSelectionModel(); |
108 | 0 | m.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); |
109 | 0 | m.setLeadAnchorNotificationEnabled(false); |
110 | ||
111 | 0 | _sideList = new ReorderableJList(); |
112 | 0 | _sideList.setModel(dlm); |
113 | 0 | _sideList.addMouseListener(new MouseAdapter() |
114 | { | |
115 | 0 | @Override |
116 | public void mouseClicked(MouseEvent e) | |
117 | { | |
118 | 0 | AppVarnaBinding.this.mouseClicked(e); |
119 | } | |
120 | }); | |
121 | 0 | _sideList.setSelectionModel(m); |
122 | 0 | _sideList.setPreferredSize(new Dimension(100, 0)); |
123 | 0 | _sideList.addListSelectionListener(new ListSelectionListener() |
124 | { | |
125 | 0 | public void valueChanged(ListSelectionEvent evt) |
126 | { | |
127 | 0 | changeSelectedStructure_actionPerformed(evt); |
128 | } | |
129 | }); | |
130 | 0 | _rnaList = new BackupHolder(dlm, _sideList); |
131 | ||
132 | 0 | try |
133 | { | |
134 | 0 | vp = new VARNAPanel("0", "."); |
135 | } catch (ExceptionNonEqualLength e) | |
136 | { | |
137 | 0 | vp.errorDialog(e); |
138 | } | |
139 | 0 | vp.setPreferredSize(new Dimension(400, 400)); |
140 | ||
141 | 0 | JScrollPane listScroller = new JScrollPane(_sideList); |
142 | 0 | listScroller.setPreferredSize(new Dimension(150, 0)); |
143 | ||
144 | 0 | vp.setBackground(_backgroundColor); |
145 | ||
146 | 0 | JLabel j = new JLabel( |
147 | MessageManager.getString("label.structures_manager"), | |
148 | JLabel.CENTER); | |
149 | 0 | _listPanel.setLayout(new BorderLayout()); |
150 | ||
151 | 0 | _listPanel.add(j, BorderLayout.NORTH); |
152 | 0 | _listPanel.add(listScroller, BorderLayout.CENTER); |
153 | ||
154 | 0 | new DropTarget(vp, new DropTargetAdapter() |
155 | { | |
156 | 0 | @Override |
157 | public void drop(DropTargetDropEvent dtde) | |
158 | { | |
159 | 0 | AppVarnaBinding.this.drop(dtde); |
160 | } | |
161 | }); | |
162 | } | |
163 | ||
164 | 0 | public JPanel getListPanel() |
165 | { | |
166 | 0 | return _listPanel; |
167 | } | |
168 | ||
169 | /** | |
170 | * Returns the currently selected RNA, or null if none selected | |
171 | * | |
172 | * @return | |
173 | */ | |
174 | 0 | public RNA getSelectedRNA() |
175 | { | |
176 | 0 | int selectedIndex = _sideList.getSelectedIndex(); |
177 | 0 | if (selectedIndex < 0) |
178 | { | |
179 | 0 | return null; |
180 | } | |
181 | 0 | FullBackup selected = _rnaList.getElementAt(selectedIndex); |
182 | 0 | return selected.rna; |
183 | } | |
184 | ||
185 | /** | |
186 | * Substitute currently selected RNA with the edited one | |
187 | * | |
188 | * @param rnaEdit | |
189 | */ | |
190 | 0 | public void updateSelectedRNA(RNA rnaEdit) |
191 | { | |
192 | 0 | vp.repaint(); |
193 | 0 | vp.showRNA(rnaEdit); |
194 | } | |
195 | ||
196 | 0 | public static String generateDefaultName() |
197 | { | |
198 | 0 | return "User file #" + _nextID++; |
199 | } | |
200 | ||
201 | 0 | public String[][] getParameterInfo() |
202 | { | |
203 | 0 | String[][] info = { |
204 | // Parameter Name Kind of Value Description, | |
205 | { "sequenceDBN", "String", "A raw RNA sequence" }, | |
206 | { "structureDBN", "String", | |
207 | "An RNA structure in dot bracket notation (DBN)" }, | |
208 | { errorOpt, "boolean", "To show errors" }, }; | |
209 | 0 | return info; |
210 | } | |
211 | ||
212 | 0 | @SuppressWarnings("unused") |
213 | private Color getSafeColor(String col, Color def) | |
214 | { | |
215 | 0 | Color result; |
216 | 0 | try |
217 | { | |
218 | 0 | result = Color.decode(col); |
219 | } catch (Exception e) | |
220 | { | |
221 | 0 | try |
222 | { | |
223 | 0 | result = Color.getColor(col, def); |
224 | } catch (Exception e2) | |
225 | { | |
226 | 0 | return def; |
227 | } | |
228 | } | |
229 | 0 | return result; |
230 | } | |
231 | ||
232 | 0 | public VARNAPanel get_varnaPanel() |
233 | { | |
234 | 0 | return vp; |
235 | } | |
236 | ||
237 | 0 | public void set_varnaPanel(VARNAPanel surface) |
238 | { | |
239 | 0 | vp = surface; |
240 | } | |
241 | ||
242 | 0 | public void drop(DropTargetDropEvent dtde) |
243 | { | |
244 | 0 | try |
245 | { | |
246 | 0 | Transferable tr = dtde.getTransferable(); |
247 | 0 | DataFlavor[] flavors = tr.getTransferDataFlavors(); |
248 | 0 | for (int i = 0; i < flavors.length; i++) |
249 | { | |
250 | 0 | if (flavors[i].isFlavorJavaFileListType()) |
251 | { | |
252 | 0 | dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); |
253 | 0 | Object ob = tr.getTransferData(flavors[i]); |
254 | 0 | if (ob instanceof List) |
255 | { | |
256 | 0 | List list = (List) ob; |
257 | 0 | for (int j = 0; j < list.size(); j++) |
258 | { | |
259 | 0 | Object o = list.get(j); |
260 | ||
261 | 0 | if (dtde.getSource() instanceof DropTarget) |
262 | { | |
263 | 0 | DropTarget dt = (DropTarget) dtde.getSource(); |
264 | 0 | Component c = dt.getComponent(); |
265 | 0 | if (c instanceof VARNAPanel) |
266 | { | |
267 | 0 | String path = o.toString(); |
268 | 0 | VARNAPanel varnaPanel = (VARNAPanel) c; |
269 | 0 | try |
270 | { | |
271 | 0 | FullBackup bck = VARNAPanel.importSession(path); |
272 | 0 | _rnaList.add(bck.config, bck.rna, bck.name, true); |
273 | } catch (ExceptionLoadingFailed e3) | |
274 | { | |
275 | 0 | int mn = 1; |
276 | 0 | Collection<RNA> mdls = fr.orsay.lri.varna.factories.RNAFactory |
277 | .loadSecStr(path); | |
278 | 0 | for (RNA r : mdls) |
279 | { | |
280 | 0 | r.drawRNA(varnaPanel.getConfig()); |
281 | 0 | String name = r.getName(); |
282 | 0 | if (name.equals("")) |
283 | { | |
284 | 0 | name = path.substring( |
285 | path.lastIndexOf(File.separatorChar) + 1); | |
286 | } | |
287 | 0 | if (mdls.size() > 1) |
288 | { | |
289 | 0 | name += " (Model " + mn++ + ")"; |
290 | } | |
291 | 0 | _rnaList.add(varnaPanel.getConfig().clone(), r, name, |
292 | true); | |
293 | // BH 2018 SwingJS clone of varnaPanel or its config will | |
294 | // be the object itself, not a clone | |
295 | } | |
296 | } | |
297 | } | |
298 | } | |
299 | } | |
300 | } | |
301 | // If we made it this far, everything worked. | |
302 | 0 | dtde.dropComplete(true); |
303 | 0 | return; |
304 | } | |
305 | } | |
306 | // Hmm, the user must not have dropped a file list | |
307 | 0 | dtde.rejectDrop(); |
308 | } catch (Exception e) | |
309 | { | |
310 | 0 | e.printStackTrace(); |
311 | 0 | dtde.rejectDrop(); |
312 | } | |
313 | ||
314 | } | |
315 | ||
316 | private class BackupHolder | |
317 | { | |
318 | private DefaultListModel<FullBackup> _rnalist; | |
319 | ||
320 | private List<RNA> _rnas = new ArrayList<RNA>(); | |
321 | ||
322 | JList _l; | |
323 | ||
324 | 0 | public BackupHolder(DefaultListModel<FullBackup> rnaList, JList l) |
325 | { | |
326 | 0 | _rnalist = rnaList; |
327 | 0 | _l = l; |
328 | } | |
329 | ||
330 | 0 | public void add(VARNAConfig c, RNA r, String name) |
331 | { | |
332 | 0 | add(c, r, name, false); |
333 | } | |
334 | ||
335 | /** | |
336 | * Adds an entry to the end of the selection list and (optionally) sets it | |
337 | * as selected | |
338 | * | |
339 | * @param c | |
340 | * @param r | |
341 | * @param name | |
342 | * @param select | |
343 | */ | |
344 | 0 | public void add(VARNAConfig c, RNA r, String name, boolean select) |
345 | { | |
346 | 0 | if (select) |
347 | { | |
348 | 0 | _l.removeSelectionInterval(0, _rnalist.size()); |
349 | } | |
350 | 0 | if (name.equals("")) |
351 | { | |
352 | 0 | name = generateDefaultName(); |
353 | } | |
354 | 0 | FullBackup bck = new FullBackup(c, r, name); |
355 | 0 | _rnas.add(r); |
356 | 0 | _rnalist.addElement(bck); |
357 | 0 | if (select) |
358 | { | |
359 | 0 | _l.setSelectedIndex(0); |
360 | } | |
361 | } | |
362 | ||
363 | 0 | public FullBackup getElementAt(int i) |
364 | { | |
365 | 0 | return _rnalist.getElementAt(i); |
366 | } | |
367 | } | |
368 | ||
369 | 0 | public void mouseClicked(MouseEvent e) |
370 | { | |
371 | 0 | if (e.getClickCount() == 2) |
372 | { | |
373 | 0 | int index = _sideList.locationToIndex(e.getPoint()); |
374 | 0 | ListModel<FullBackup> dlm = _sideList.getModel(); |
375 | // FullBackup item = dlm.getElementAt(index); | |
376 | ||
377 | 0 | _sideList.ensureIndexIsVisible(index); |
378 | /* | |
379 | * TODO Object newName = JvOptionPane.showInputDialog( this, | |
380 | * "Specify a new name for this RNA", "Rename RNA", | |
381 | * JvOptionPane.QUESTION_MESSAGE, (Icon)null, null, item.toString()); if | |
382 | * (newName!=null) { item.name = newName.toString(); | |
383 | * this._sideList.repaint(); } | |
384 | */ | |
385 | } | |
386 | } | |
387 | ||
388 | 0 | @Override |
389 | public String[] getStructureFiles() | |
390 | { | |
391 | 0 | return null; |
392 | } | |
393 | ||
394 | 0 | @Override |
395 | public void releaseReferences(Object svl) | |
396 | { | |
397 | } | |
398 | ||
399 | 0 | @Override |
400 | public void updateColours(Object source) | |
401 | { | |
402 | } | |
403 | ||
404 | 0 | @Override |
405 | public void componentHidden(ComponentEvent e) | |
406 | { | |
407 | } | |
408 | ||
409 | 0 | @Override |
410 | public void componentMoved(ComponentEvent e) | |
411 | { | |
412 | } | |
413 | ||
414 | 0 | @Override |
415 | public void componentResized(ComponentEvent e) | |
416 | { | |
417 | } | |
418 | ||
419 | 0 | @Override |
420 | public void componentShown(ComponentEvent e) | |
421 | { | |
422 | } | |
423 | ||
424 | 0 | @Override |
425 | public void highlightAtoms(List<AtomSpec> atoms) | |
426 | { | |
427 | } | |
428 | ||
429 | 0 | @Override |
430 | public boolean isListeningFor(SequenceI seq) | |
431 | { | |
432 | 0 | return true; |
433 | } | |
434 | ||
435 | /** | |
436 | * Returns the path to a temporary file containing a representation of the | |
437 | * state of the Varna display, or null on any error | |
438 | * | |
439 | * @param rna | |
440 | * @param jds | |
441 | * | |
442 | * @return | |
443 | */ | |
444 | 0 | public String getStateInfo(RNA rna) |
445 | { | |
446 | 0 | if (vp == null) |
447 | { | |
448 | 0 | return null; |
449 | } | |
450 | ||
451 | /* | |
452 | * we have to show the RNA we want to save in the viewer; get the currently | |
453 | * displayed model first so we can restore it | |
454 | */ | |
455 | 0 | FullBackup sel = (FullBackup) _sideList.getSelectedValue(); |
456 | ||
457 | 0 | FullBackup model = null; |
458 | 0 | ListModel models = _sideList.getModel(); |
459 | 0 | for (int i = 0; i < models.getSize(); i++) |
460 | { | |
461 | 0 | model = (FullBackup) models.getElementAt(i); |
462 | 0 | if (model.rna == rna) |
463 | { | |
464 | 0 | break; |
465 | } | |
466 | } | |
467 | 0 | if (model == null) |
468 | { | |
469 | 0 | return null; |
470 | } | |
471 | ||
472 | /* | |
473 | * switch display | |
474 | */ | |
475 | 0 | vp.showRNA(model.rna, model.config); |
476 | ||
477 | 0 | try |
478 | { | |
479 | 0 | File temp; |
480 | 0 | temp = File.createTempFile("varna", null); |
481 | 0 | temp.deleteOnExit(); |
482 | 0 | String filePath = temp.getAbsolutePath(); |
483 | 0 | vp.toXML(filePath); |
484 | ||
485 | /* | |
486 | * restore the previous display | |
487 | */ | |
488 | 0 | vp.showRNA(sel.rna, sel.config); |
489 | ||
490 | 0 | return filePath; |
491 | } catch (IOException e) | |
492 | { | |
493 | 0 | return null; |
494 | } | |
495 | } | |
496 | ||
497 | 0 | public int getSelectedIndex() |
498 | { | |
499 | 0 | return _sideList.getSelectedIndex(); |
500 | } | |
501 | ||
502 | /** | |
503 | * Switch the Varna display to the structure selected in the left hand panel | |
504 | * | |
505 | * @param evt | |
506 | */ | |
507 | 0 | protected void changeSelectedStructure_actionPerformed( |
508 | ListSelectionEvent evt) | |
509 | { | |
510 | 0 | if (!evt.getValueIsAdjusting()) |
511 | { | |
512 | 0 | showSelectedStructure(); |
513 | } | |
514 | } | |
515 | ||
516 | /** | |
517 | * | |
518 | */ | |
519 | 0 | protected void showSelectedStructure() |
520 | { | |
521 | 0 | FullBackup sel = (FullBackup) _sideList.getSelectedValue(); |
522 | 0 | if (sel != null) |
523 | { | |
524 | 0 | vp.showRNA(sel.rna, sel.config); |
525 | } | |
526 | } | |
527 | ||
528 | /** | |
529 | * Set and display the selected item in the list of structures | |
530 | * | |
531 | * @param selectedRna | |
532 | */ | |
533 | 0 | public void setSelectedIndex(final int selectedRna) |
534 | { | |
535 | /* | |
536 | * note this does nothing if, say, selecting item 3 when only 1 has been | |
537 | * added on load | |
538 | */ | |
539 | 0 | _sideList.setSelectedIndex(selectedRna); |
540 | // TODO ? need a worker thread to get this to happen properly | |
541 | } | |
542 | ||
543 | /** | |
544 | * Add an RNA structure to the selection list | |
545 | * | |
546 | * @param rna | |
547 | */ | |
548 | 0 | public void addStructure(RNA rna) |
549 | { | |
550 | 0 | VARNAConfig config = vp.getConfig().clone(); // BH 2018 this will NOT be a |
551 | // clone in SwingJS | |
552 | 0 | addStructure(rna, config); |
553 | } | |
554 | ||
555 | /** | |
556 | * @param rna | |
557 | * @param config | |
558 | */ | |
559 | 0 | protected void addStructure(final RNA rna, final VARNAConfig config) |
560 | { | |
561 | 0 | drawRna(rna, config); |
562 | 0 | _rnaList.add(config, rna, rna.getName()); |
563 | } | |
564 | ||
565 | /** | |
566 | * @param rna | |
567 | * @param config | |
568 | */ | |
569 | 0 | protected void drawRna(final RNA rna, final VARNAConfig config) |
570 | { | |
571 | 0 | try |
572 | { | |
573 | 0 | rna.drawRNA(rna.getDrawMode(), config); |
574 | } catch (ExceptionNAViewAlgorithm e) | |
575 | { | |
576 | // only throwable for draw mode = 3 NAView | |
577 | 0 | jalview.bin.Console |
578 | .errPrintln("Error drawing RNA: " + e.getMessage()); | |
579 | } | |
580 | } | |
581 | } |