Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
AnnotationLabels | 56 | 307 | 111 |
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.appletgui; | |
22 | ||
23 | import jalview.analysis.AlignmentUtils; | |
24 | import jalview.datamodel.AlignmentAnnotation; | |
25 | import jalview.datamodel.Annotation; | |
26 | import jalview.datamodel.HiddenColumns; | |
27 | import jalview.datamodel.SequenceGroup; | |
28 | import jalview.datamodel.SequenceI; | |
29 | import jalview.util.MessageManager; | |
30 | import jalview.util.ParseHtmlBodyAndLinks; | |
31 | ||
32 | import java.awt.Checkbox; | |
33 | import java.awt.CheckboxMenuItem; | |
34 | import java.awt.Color; | |
35 | import java.awt.Cursor; | |
36 | import java.awt.Dimension; | |
37 | import java.awt.FlowLayout; | |
38 | import java.awt.FontMetrics; | |
39 | import java.awt.Frame; | |
40 | import java.awt.Graphics; | |
41 | import java.awt.Image; | |
42 | import java.awt.MenuItem; | |
43 | import java.awt.Panel; | |
44 | import java.awt.PopupMenu; | |
45 | import java.awt.event.ActionEvent; | |
46 | import java.awt.event.ActionListener; | |
47 | import java.awt.event.InputEvent; | |
48 | import java.awt.event.ItemEvent; | |
49 | import java.awt.event.ItemListener; | |
50 | import java.awt.event.MouseEvent; | |
51 | import java.awt.event.MouseListener; | |
52 | import java.awt.event.MouseMotionListener; | |
53 | import java.util.Arrays; | |
54 | import java.util.Collections; | |
55 | ||
56 | public class AnnotationLabels extends Panel | |
57 | implements ActionListener, MouseListener, MouseMotionListener | |
58 | { | |
59 | Image image; | |
60 | ||
61 | /** | |
62 | * width in pixels within which height adjuster arrows are shown and active | |
63 | */ | |
64 | private static final int HEIGHT_ADJUSTER_WIDTH = 50; | |
65 | ||
66 | /** | |
67 | * height in pixels for allowing height adjuster to be active | |
68 | */ | |
69 | private static int HEIGHT_ADJUSTER_HEIGHT = 10; | |
70 | ||
71 | boolean active = false; | |
72 | ||
73 | AlignmentPanel ap; | |
74 | ||
75 | AlignViewport av; | |
76 | ||
77 | boolean resizing = false; | |
78 | ||
79 | int oldY, mouseX; | |
80 | ||
81 | static String ADDNEW = "Add New Row"; | |
82 | ||
83 | static String EDITNAME = "Edit Label/Description"; | |
84 | ||
85 | static String HIDE = "Hide This Row"; | |
86 | ||
87 | static String SHOWALL = "Show All Hidden Rows"; | |
88 | ||
89 | static String OUTPUT_TEXT = "Show Values In Textbox"; | |
90 | ||
91 | static String COPYCONS_SEQ = "Copy Consensus Sequence"; | |
92 | ||
93 | int scrollOffset = 0; | |
94 | ||
95 | int selectedRow = -1; | |
96 | ||
97 | Tooltip tooltip; | |
98 | ||
99 | private boolean hasHiddenRows; | |
100 | ||
101 | 0 | public AnnotationLabels(AlignmentPanel ap) |
102 | { | |
103 | 0 | this.ap = ap; |
104 | 0 | this.av = ap.av; |
105 | 0 | setLayout(null); |
106 | 0 | addMouseListener(this); |
107 | 0 | addMouseMotionListener(this); |
108 | } | |
109 | ||
110 | 0 | public AnnotationLabels(AlignViewport av) |
111 | { | |
112 | 0 | this.av = av; |
113 | } | |
114 | ||
115 | 0 | public void setScrollOffset(int y, boolean repaint) |
116 | { | |
117 | 0 | scrollOffset = y; |
118 | 0 | if (repaint) |
119 | { | |
120 | 0 | repaint(); |
121 | } | |
122 | } | |
123 | ||
124 | /** | |
125 | * | |
126 | * @param y | |
127 | * @return -2 if no rows are visible at all, -1 if no visible rows were | |
128 | * selected | |
129 | */ | |
130 | 0 | int getSelectedRow(int y) |
131 | { | |
132 | 0 | int row = -2; |
133 | 0 | AlignmentAnnotation[] aa = ap.av.getAlignment() |
134 | .getAlignmentAnnotation(); | |
135 | ||
136 | 0 | if (aa == null) |
137 | { | |
138 | 0 | return row; |
139 | } | |
140 | 0 | int height = 0; |
141 | 0 | for (int i = 0; i < aa.length; i++) |
142 | { | |
143 | 0 | row = -1; |
144 | 0 | if (!aa[i].visible) |
145 | { | |
146 | 0 | continue; |
147 | } | |
148 | 0 | height += aa[i].height; |
149 | 0 | if (y < height) |
150 | { | |
151 | 0 | row = i; |
152 | 0 | break; |
153 | } | |
154 | } | |
155 | ||
156 | 0 | return row; |
157 | } | |
158 | ||
159 | 0 | @Override |
160 | public void actionPerformed(ActionEvent evt) | |
161 | { | |
162 | 0 | AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation(); |
163 | ||
164 | 0 | if (evt.getActionCommand().equals(ADDNEW)) |
165 | { | |
166 | 0 | AlignmentAnnotation newAnnotation = new AlignmentAnnotation("", null, |
167 | new Annotation[ap.av.getAlignment().getWidth()]); | |
168 | ||
169 | 0 | if (!editLabelDescription(newAnnotation)) |
170 | { | |
171 | 0 | return; |
172 | } | |
173 | ||
174 | 0 | ap.av.getAlignment().addAnnotation(newAnnotation); |
175 | 0 | ap.av.getAlignment().setAnnotationIndex(newAnnotation, 0); |
176 | } | |
177 | 0 | else if (evt.getActionCommand().equals(EDITNAME)) |
178 | { | |
179 | 0 | editLabelDescription(aa[selectedRow]); |
180 | } | |
181 | 0 | else if (evt.getActionCommand().equals(HIDE)) |
182 | { | |
183 | 0 | aa[selectedRow].visible = false; |
184 | } | |
185 | 0 | else if (evt.getActionCommand().equals(SHOWALL)) |
186 | { | |
187 | 0 | for (int i = 0; i < aa.length; i++) |
188 | { | |
189 | 0 | aa[i].visible = (aa[i].annotations == null) ? false : true; |
190 | } | |
191 | } | |
192 | 0 | else if (evt.getActionCommand().equals(OUTPUT_TEXT)) |
193 | { | |
194 | 0 | CutAndPasteTransfer cap = new CutAndPasteTransfer(false, |
195 | ap.alignFrame); | |
196 | 0 | Frame frame = new Frame(); |
197 | 0 | frame.add(cap); |
198 | 0 | jalview.bin.JalviewLite.addFrame(frame, |
199 | ap.alignFrame.getTitle() + " - " + aa[selectedRow].label, 500, | |
200 | 100); | |
201 | 0 | cap.setText(aa[selectedRow].toString()); |
202 | } | |
203 | 0 | else if (evt.getActionCommand().equals(COPYCONS_SEQ)) |
204 | { | |
205 | 0 | SequenceGroup group = aa[selectedRow].groupRef; |
206 | 0 | SequenceI cons = group == null ? av.getConsensusSeq() |
207 | : group.getConsensusSeq(); | |
208 | 0 | if (cons != null) |
209 | { | |
210 | 0 | copy_annotseqtoclipboard(cons); |
211 | } | |
212 | ||
213 | } | |
214 | 0 | refresh(); |
215 | } | |
216 | ||
217 | /** | |
218 | * Adjust size and repaint | |
219 | */ | |
220 | 0 | protected void refresh() |
221 | { | |
222 | 0 | ap.annotationPanel.adjustPanelHeight(); |
223 | 0 | setSize(getSize().width, ap.annotationPanel.getSize().height); |
224 | 0 | ap.validate(); |
225 | // TODO: only paint if we needed to | |
226 | 0 | ap.paintAlignment(true, true); |
227 | } | |
228 | ||
229 | 0 | boolean editLabelDescription(AlignmentAnnotation annotation) |
230 | { | |
231 | 0 | Checkbox padGaps = new Checkbox( |
232 | "Fill Empty Gaps With \"" + ap.av.getGapCharacter() + "\"", | |
233 | annotation.padGaps); | |
234 | ||
235 | 0 | EditNameDialog dialog = new EditNameDialog(annotation.label, |
236 | annotation.description, " Annotation Label", | |
237 | "Annotation Description", ap.alignFrame, | |
238 | "Edit Annotation Name / Description", 500, 180, false); | |
239 | ||
240 | 0 | Panel empty = new Panel(new FlowLayout()); |
241 | 0 | empty.add(padGaps); |
242 | 0 | dialog.add(empty); |
243 | 0 | dialog.pack(); |
244 | ||
245 | 0 | dialog.setVisible(true); |
246 | ||
247 | 0 | if (dialog.accept) |
248 | { | |
249 | 0 | annotation.label = dialog.getName(); |
250 | 0 | annotation.description = dialog.getDescription(); |
251 | 0 | annotation.setPadGaps(padGaps.getState(), av.getGapCharacter()); |
252 | 0 | repaint(); |
253 | 0 | return true; |
254 | } | |
255 | else | |
256 | { | |
257 | 0 | return false; |
258 | } | |
259 | ||
260 | } | |
261 | ||
262 | boolean resizePanel = false; | |
263 | ||
264 | 0 | @Override |
265 | public void mouseMoved(MouseEvent evt) | |
266 | { | |
267 | 0 | resizePanel = evt.getY() < HEIGHT_ADJUSTER_HEIGHT |
268 | && evt.getX() < HEIGHT_ADJUSTER_WIDTH; | |
269 | 0 | setCursor(Cursor.getPredefinedCursor( |
270 | 0 | resizePanel ? Cursor.S_RESIZE_CURSOR : Cursor.DEFAULT_CURSOR)); |
271 | 0 | int row = getSelectedRow(evt.getY() + scrollOffset); |
272 | ||
273 | 0 | if (row > -1) |
274 | { | |
275 | 0 | ParseHtmlBodyAndLinks phb = new ParseHtmlBodyAndLinks( |
276 | av.getAlignment().getAlignmentAnnotation()[row] | |
277 | .getDescription(true), | |
278 | true, "\n"); | |
279 | 0 | if (tooltip == null) |
280 | { | |
281 | 0 | tooltip = new Tooltip(phb.getNonHtmlContent(), this); |
282 | } | |
283 | else | |
284 | { | |
285 | 0 | tooltip.setTip(phb.getNonHtmlContent()); |
286 | } | |
287 | } | |
288 | 0 | else if (tooltip != null) |
289 | { | |
290 | 0 | tooltip.setTip(""); |
291 | } | |
292 | } | |
293 | ||
294 | /** | |
295 | * curent drag position | |
296 | */ | |
297 | MouseEvent dragEvent = null; | |
298 | ||
299 | /** | |
300 | * flag to indicate drag events should be ignored | |
301 | */ | |
302 | private boolean dragCancelled = false; | |
303 | ||
304 | /** | |
305 | * clear any drag events in progress | |
306 | */ | |
307 | 0 | public void cancelDrag() |
308 | { | |
309 | 0 | dragEvent = null; |
310 | 0 | dragCancelled = true; |
311 | } | |
312 | ||
313 | 0 | @Override |
314 | public void mouseDragged(MouseEvent evt) | |
315 | { | |
316 | 0 | if (dragCancelled) |
317 | { | |
318 | 0 | return; |
319 | } | |
320 | 0 | ; |
321 | 0 | dragEvent = evt; |
322 | ||
323 | 0 | if (resizePanel) |
324 | { | |
325 | 0 | Dimension d = ap.annotationPanelHolder.getSize(), |
326 | e = ap.annotationSpaceFillerHolder.getSize(), | |
327 | f = ap.seqPanelHolder.getSize(); | |
328 | 0 | int dif = evt.getY() - oldY; |
329 | ||
330 | 0 | dif /= ap.av.getCharHeight(); |
331 | 0 | dif *= ap.av.getCharHeight(); |
332 | ||
333 | 0 | if ((d.height - dif) > 20 && (f.height + dif) > 20) |
334 | { | |
335 | 0 | ap.annotationPanel.setSize(d.width, d.height - dif); |
336 | 0 | setSize(new Dimension(e.width, d.height - dif)); |
337 | 0 | ap.annotationSpaceFillerHolder |
338 | .setSize(new Dimension(e.width, d.height - dif)); | |
339 | 0 | ap.annotationPanelHolder |
340 | .setSize(new Dimension(d.width, d.height - dif)); | |
341 | 0 | ap.apvscroll.setValues(ap.apvscroll.getValue(), d.height - dif, 0, |
342 | av.calcPanelHeight()); | |
343 | 0 | f.height += dif; |
344 | 0 | ap.seqPanelHolder.setPreferredSize(f); |
345 | 0 | ap.setScrollValues(av.getRanges().getStartRes(), |
346 | av.getRanges().getStartSeq()); | |
347 | 0 | ap.validate(); |
348 | // ap.paintAlignment(true); | |
349 | 0 | ap.addNotify(); |
350 | } | |
351 | ||
352 | } | |
353 | else | |
354 | { | |
355 | 0 | int diff; |
356 | 0 | if ((diff = 6 - evt.getY()) > 0) |
357 | { | |
358 | // nudge scroll up | |
359 | 0 | ap.apvscroll.setValue(ap.apvscroll.getValue() - diff); |
360 | 0 | ap.adjustmentValueChanged(null); |
361 | ||
362 | } | |
363 | 0 | else if ((0 < (diff = 6 |
364 | - ap.annotationSpaceFillerHolder.getSize().height | |
365 | + evt.getY()))) | |
366 | { | |
367 | // nudge scroll down | |
368 | 0 | ap.apvscroll.setValue(ap.apvscroll.getValue() + diff); |
369 | 0 | ap.adjustmentValueChanged(null); |
370 | } | |
371 | 0 | repaint(); |
372 | } | |
373 | } | |
374 | ||
375 | 0 | @Override |
376 | public void mouseClicked(MouseEvent evt) | |
377 | { | |
378 | } | |
379 | ||
380 | 0 | @Override |
381 | public void mouseReleased(MouseEvent evt) | |
382 | { | |
383 | 0 | if (!resizePanel && !dragCancelled) |
384 | { | |
385 | 0 | int start = selectedRow; |
386 | ||
387 | 0 | int end = getSelectedRow(evt.getY() + scrollOffset); |
388 | ||
389 | 0 | if (start > -1 && start != end) |
390 | { | |
391 | // Swap these annotations | |
392 | 0 | AlignmentAnnotation startAA = ap.av.getAlignment() |
393 | .getAlignmentAnnotation()[start]; | |
394 | 0 | if (end == -1) |
395 | { | |
396 | 0 | end = ap.av.getAlignment().getAlignmentAnnotation().length - 1; |
397 | } | |
398 | 0 | AlignmentAnnotation endAA = ap.av.getAlignment() |
399 | .getAlignmentAnnotation()[end]; | |
400 | ||
401 | 0 | ap.av.getAlignment().getAlignmentAnnotation()[end] = startAA; |
402 | 0 | ap.av.getAlignment().getAlignmentAnnotation()[start] = endAA; |
403 | } | |
404 | } | |
405 | 0 | resizePanel = false; |
406 | 0 | dragEvent = null; |
407 | 0 | dragCancelled = false; |
408 | 0 | setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); |
409 | 0 | repaint(); |
410 | 0 | ap.annotationPanel.repaint(); |
411 | } | |
412 | ||
413 | 0 | @Override |
414 | public void mouseEntered(MouseEvent evt) | |
415 | { | |
416 | 0 | if (evt.getY() < 10 && evt.getX() < 14) |
417 | { | |
418 | 0 | resizePanel = true; |
419 | 0 | repaint(); |
420 | } | |
421 | 0 | setCursor(Cursor.getPredefinedCursor( |
422 | 0 | resizePanel ? Cursor.S_RESIZE_CURSOR : Cursor.DEFAULT_CURSOR)); |
423 | } | |
424 | ||
425 | 0 | @Override |
426 | public void mouseExited(MouseEvent evt) | |
427 | { | |
428 | 0 | dragCancelled = false; |
429 | ||
430 | 0 | if (dragEvent == null) |
431 | { | |
432 | 0 | resizePanel = false; |
433 | } | |
434 | else | |
435 | { | |
436 | 0 | if (!resizePanel) |
437 | { | |
438 | 0 | dragEvent = null; |
439 | } | |
440 | } | |
441 | 0 | repaint(); |
442 | } | |
443 | ||
444 | 0 | @Override |
445 | public void mousePressed(MouseEvent evt) | |
446 | { | |
447 | 0 | oldY = evt.getY(); |
448 | 0 | if (resizePanel) |
449 | { | |
450 | 0 | return; |
451 | } | |
452 | 0 | dragCancelled = false; |
453 | // todo: move below to mouseClicked ? | |
454 | 0 | selectedRow = getSelectedRow(evt.getY() + scrollOffset); |
455 | ||
456 | 0 | AlignmentAnnotation[] aa = ap.av.getAlignment() |
457 | .getAlignmentAnnotation(); | |
458 | ||
459 | // DETECT RIGHT MOUSE BUTTON IN AWT | |
460 | 0 | if ((evt.getModifiersEx() |
461 | & InputEvent.BUTTON3_DOWN_MASK) == InputEvent.BUTTON3_DOWN_MASK) | |
462 | { | |
463 | ||
464 | 0 | PopupMenu popup = new PopupMenu( |
465 | MessageManager.getString("label.annotations")); | |
466 | ||
467 | 0 | MenuItem item = new MenuItem(ADDNEW); |
468 | 0 | item.addActionListener(this); |
469 | 0 | popup.add(item); |
470 | 0 | if (selectedRow < 0) |
471 | { | |
472 | // this never happens at moment: - see comment on JAL-563 | |
473 | 0 | if (hasHiddenRows) |
474 | { | |
475 | 0 | item = new MenuItem(SHOWALL); |
476 | 0 | item.addActionListener(this); |
477 | 0 | popup.add(item); |
478 | } | |
479 | 0 | this.add(popup); |
480 | 0 | popup.show(this, evt.getX(), evt.getY()); |
481 | 0 | return; |
482 | } | |
483 | // add the rest if there are actually rows to show | |
484 | 0 | item = new MenuItem(EDITNAME); |
485 | 0 | item.addActionListener(this); |
486 | 0 | popup.add(item); |
487 | 0 | item = new MenuItem(HIDE); |
488 | 0 | item.addActionListener(this); |
489 | 0 | popup.add(item); |
490 | ||
491 | /* | |
492 | * Hide all <label>: | |
493 | */ | |
494 | 0 | if (selectedRow < aa.length) |
495 | { | |
496 | 0 | if (aa[selectedRow].sequenceRef != null) |
497 | { | |
498 | 0 | final String label = aa[selectedRow].label; |
499 | 0 | MenuItem hideType = new MenuItem( |
500 | MessageManager.getString("label.hide_all") + " " + label); | |
501 | 0 | hideType.addActionListener(new ActionListener() |
502 | { | |
503 | 0 | @Override |
504 | public void actionPerformed(ActionEvent e) | |
505 | { | |
506 | 0 | AlignmentUtils.showOrHideSequenceAnnotations( |
507 | ap.av.getAlignment(), Collections.singleton(label), | |
508 | null, false, false); | |
509 | 0 | refresh(); |
510 | } | |
511 | }); | |
512 | 0 | popup.add(hideType); |
513 | } | |
514 | } | |
515 | ||
516 | 0 | if (hasHiddenRows) |
517 | { | |
518 | 0 | item = new MenuItem(SHOWALL); |
519 | 0 | item.addActionListener(this); |
520 | 0 | popup.add(item); |
521 | } | |
522 | 0 | this.add(popup); |
523 | 0 | item = new MenuItem(OUTPUT_TEXT); |
524 | 0 | item.addActionListener(this); |
525 | 0 | popup.add(item); |
526 | 0 | if (selectedRow < aa.length) |
527 | { | |
528 | 0 | if (aa[selectedRow].autoCalculated) |
529 | { | |
530 | 0 | if (aa[selectedRow].label.indexOf("Consensus") > -1) |
531 | { | |
532 | 0 | popup.addSeparator(); |
533 | 0 | final CheckboxMenuItem cbmi = new CheckboxMenuItem( |
534 | MessageManager.getString("label.ignore_gaps_consensus"), | |
535 | 0 | (aa[selectedRow].groupRef != null) |
536 | ? aa[selectedRow].groupRef | |
537 | .getIgnoreGapsConsensus() | |
538 | : ap.av.isIgnoreGapsConsensus()); | |
539 | 0 | final AlignmentAnnotation aaa = aa[selectedRow]; |
540 | 0 | cbmi.addItemListener(new ItemListener() |
541 | { | |
542 | 0 | @Override |
543 | public void itemStateChanged(ItemEvent e) | |
544 | { | |
545 | 0 | if (aaa.groupRef != null) |
546 | { | |
547 | // TODO: pass on reference to ap so the view can be updated. | |
548 | 0 | aaa.groupRef.setIgnoreGapsConsensus(cbmi.getState()); |
549 | } | |
550 | else | |
551 | { | |
552 | 0 | ap.av.setIgnoreGapsConsensus(cbmi.getState(), ap); |
553 | } | |
554 | 0 | ap.paintAlignment(true, true); |
555 | } | |
556 | }); | |
557 | 0 | popup.add(cbmi); |
558 | 0 | if (aaa.groupRef != null) |
559 | { | |
560 | 0 | final CheckboxMenuItem chist = new CheckboxMenuItem( |
561 | MessageManager | |
562 | .getString("label.show_group_histogram"), | |
563 | aa[selectedRow].groupRef.isShowConsensusHistogram()); | |
564 | 0 | chist.addItemListener(new ItemListener() |
565 | { | |
566 | 0 | @Override |
567 | public void itemStateChanged(ItemEvent e) | |
568 | { | |
569 | // TODO: pass on reference | |
570 | // to ap | |
571 | // so the | |
572 | // view | |
573 | // can be | |
574 | // updated. | |
575 | 0 | aaa.groupRef.setShowConsensusHistogram(chist.getState()); |
576 | 0 | ap.repaint(); |
577 | // ap.annotationPanel.paint(ap.annotationPanel.getGraphics()); | |
578 | } | |
579 | }); | |
580 | 0 | popup.add(chist); |
581 | 0 | final CheckboxMenuItem cprofl = new CheckboxMenuItem( |
582 | MessageManager.getString("label.show_group_logo"), | |
583 | aa[selectedRow].groupRef.isShowSequenceLogo()); | |
584 | 0 | cprofl.addItemListener(new ItemListener() |
585 | { | |
586 | 0 | @Override |
587 | public void itemStateChanged(ItemEvent e) | |
588 | { | |
589 | // TODO: pass on reference | |
590 | // to ap | |
591 | // so the | |
592 | // view | |
593 | // can be | |
594 | // updated. | |
595 | 0 | aaa.groupRef.setshowSequenceLogo(cprofl.getState()); |
596 | 0 | ap.repaint(); |
597 | // ap.annotationPanel.paint(ap.annotationPanel.getGraphics()); | |
598 | } | |
599 | }); | |
600 | ||
601 | 0 | popup.add(cprofl); |
602 | 0 | final CheckboxMenuItem cprofn = new CheckboxMenuItem( |
603 | MessageManager | |
604 | .getString("label.normalise_group_logo"), | |
605 | aa[selectedRow].groupRef.isNormaliseSequenceLogo()); | |
606 | 0 | cprofn.addItemListener(new ItemListener() |
607 | { | |
608 | 0 | @Override |
609 | public void itemStateChanged(ItemEvent e) | |
610 | { | |
611 | // TODO: pass on reference | |
612 | // to ap | |
613 | // so the | |
614 | // view | |
615 | // can be | |
616 | // updated. | |
617 | 0 | aaa.groupRef.setshowSequenceLogo(true); |
618 | 0 | aaa.groupRef.setNormaliseSequenceLogo(cprofn.getState()); |
619 | 0 | ap.repaint(); |
620 | // ap.annotationPanel.paint(ap.annotationPanel.getGraphics()); | |
621 | } | |
622 | }); | |
623 | 0 | popup.add(cprofn); |
624 | } | |
625 | else | |
626 | { | |
627 | 0 | final CheckboxMenuItem chist = new CheckboxMenuItem( |
628 | MessageManager.getString("label.show_histogram"), | |
629 | av.isShowConsensusHistogram()); | |
630 | 0 | chist.addItemListener(new ItemListener() |
631 | { | |
632 | 0 | @Override |
633 | public void itemStateChanged(ItemEvent e) | |
634 | { | |
635 | // TODO: pass on reference | |
636 | // to ap | |
637 | // so the | |
638 | // view | |
639 | // can be | |
640 | // updated. | |
641 | 0 | av.setShowConsensusHistogram(chist.getState()); |
642 | 0 | ap.alignFrame.showConsensusHistogram |
643 | .setState(chist.getState()); // TODO: implement | |
644 | // ap.updateGUI()/alignFrame.updateGUI | |
645 | // for applet | |
646 | 0 | ap.repaint(); |
647 | // ap.annotationPanel.paint(ap.annotationPanel.getGraphics()); | |
648 | } | |
649 | }); | |
650 | 0 | popup.add(chist); |
651 | 0 | final CheckboxMenuItem cprof = new CheckboxMenuItem( |
652 | MessageManager.getString("label.show_logo"), | |
653 | av.isShowSequenceLogo()); | |
654 | 0 | cprof.addItemListener(new ItemListener() |
655 | { | |
656 | 0 | @Override |
657 | public void itemStateChanged(ItemEvent e) | |
658 | { | |
659 | // TODO: pass on reference | |
660 | // to ap | |
661 | // so the | |
662 | // view | |
663 | // can be | |
664 | // updated. | |
665 | 0 | av.setShowSequenceLogo(cprof.getState()); |
666 | 0 | ap.alignFrame.showSequenceLogo.setState(cprof.getState()); // TODO: |
667 | // implement | |
668 | // ap.updateGUI()/alignFrame.updateGUI | |
669 | // for | |
670 | // applet | |
671 | 0 | ap.repaint(); |
672 | // ap.annotationPanel.paint(ap.annotationPanel.getGraphics()); | |
673 | } | |
674 | }); | |
675 | 0 | popup.add(cprof); |
676 | 0 | final CheckboxMenuItem cprofn = new CheckboxMenuItem( |
677 | MessageManager.getString("label.normalise_logo"), | |
678 | av.isNormaliseSequenceLogo()); | |
679 | 0 | cprofn.addItemListener(new ItemListener() |
680 | { | |
681 | 0 | @Override |
682 | public void itemStateChanged(ItemEvent e) | |
683 | { | |
684 | // TODO: pass on reference | |
685 | // to ap | |
686 | // so the | |
687 | // view | |
688 | // can be | |
689 | // updated. | |
690 | 0 | av.setShowSequenceLogo(true); |
691 | 0 | ap.alignFrame.normSequenceLogo |
692 | .setState(cprofn.getState()); // TODO: | |
693 | // implement | |
694 | // ap.updateGUI()/alignFrame.updateGUI | |
695 | // for | |
696 | // applet | |
697 | 0 | av.setNormaliseSequenceLogo(cprofn.getState()); |
698 | 0 | ap.repaint(); |
699 | // ap.annotationPanel.paint(ap.annotationPanel.getGraphics()); | |
700 | } | |
701 | }); | |
702 | 0 | popup.add(cprofn); |
703 | } | |
704 | ||
705 | 0 | item = new MenuItem(COPYCONS_SEQ); |
706 | 0 | item.addActionListener(this); |
707 | 0 | popup.add(item); |
708 | } | |
709 | } | |
710 | } | |
711 | 0 | popup.show(this, evt.getX(), evt.getY()); |
712 | } | |
713 | else | |
714 | { | |
715 | // selection action. | |
716 | 0 | if (selectedRow > -1 && selectedRow < aa.length) |
717 | { | |
718 | 0 | if (aa[selectedRow].groupRef != null) |
719 | { | |
720 | 0 | if (evt.getClickCount() >= 2) |
721 | { | |
722 | // todo: make the ap scroll to the selection - not necessary, first | |
723 | // click highlights/scrolls, second selects | |
724 | 0 | ap.seqPanel.ap.idPanel.highlightSearchResults(null); |
725 | // process modifiers | |
726 | 0 | SequenceGroup sg = ap.av.getSelectionGroup(); |
727 | 0 | if (sg == null || sg == aa[selectedRow].groupRef |
728 | || !(jalview.util.Platform.isControlDown(evt) | |
729 | || evt.isShiftDown())) | |
730 | { | |
731 | 0 | if (jalview.util.Platform.isControlDown(evt) |
732 | || evt.isShiftDown()) | |
733 | { | |
734 | // clone a new selection group from the associated group | |
735 | 0 | ap.av.setSelectionGroup( |
736 | new SequenceGroup(aa[selectedRow].groupRef)); | |
737 | } | |
738 | else | |
739 | { | |
740 | // set selection to the associated group so it can be edited | |
741 | 0 | ap.av.setSelectionGroup(aa[selectedRow].groupRef); |
742 | } | |
743 | } | |
744 | else | |
745 | { | |
746 | // modify current selection with associated group | |
747 | 0 | int remainToAdd = aa[selectedRow].groupRef.getSize(); |
748 | 0 | for (SequenceI sgs : aa[selectedRow].groupRef.getSequences()) |
749 | { | |
750 | 0 | if (jalview.util.Platform.isControlDown(evt)) |
751 | { | |
752 | 0 | sg.addOrRemove(sgs, --remainToAdd == 0); |
753 | } | |
754 | else | |
755 | { | |
756 | // notionally, we should also add intermediate sequences from | |
757 | // last added sequence ? | |
758 | 0 | sg.addSequence(sgs, --remainToAdd == 0); |
759 | } | |
760 | } | |
761 | } | |
762 | 0 | ap.paintAlignment(false, false); |
763 | 0 | PaintRefresher.Refresh(ap, ap.av.getSequenceSetId()); |
764 | 0 | ap.av.sendSelection(); |
765 | } | |
766 | else | |
767 | { | |
768 | 0 | ap.seqPanel.ap.idPanel.highlightSearchResults( |
769 | aa[selectedRow].groupRef.getSequences(null)); | |
770 | } | |
771 | 0 | return; |
772 | } | |
773 | 0 | else if (aa[selectedRow].sequenceRef != null) |
774 | { | |
775 | 0 | if (evt.getClickCount() == 1) |
776 | { | |
777 | 0 | ap.seqPanel.ap.idPanel |
778 | .highlightSearchResults(Arrays.asList(new SequenceI[] | |
779 | { aa[selectedRow].sequenceRef })); | |
780 | } | |
781 | 0 | else if (evt.getClickCount() >= 2) |
782 | { | |
783 | 0 | ap.seqPanel.ap.idPanel.highlightSearchResults(null); |
784 | 0 | SequenceGroup sg = ap.av.getSelectionGroup(); |
785 | 0 | if (sg != null) |
786 | { | |
787 | // we make a copy rather than edit the current selection if no | |
788 | // modifiers pressed | |
789 | // see Enhancement JAL-1557 | |
790 | 0 | if (!(jalview.util.Platform.isControlDown(evt) |
791 | || evt.isShiftDown())) | |
792 | { | |
793 | 0 | sg = new SequenceGroup(sg); |
794 | 0 | sg.clear(); |
795 | 0 | sg.addSequence(aa[selectedRow].sequenceRef, false); |
796 | } | |
797 | else | |
798 | { | |
799 | 0 | if (jalview.util.Platform.isControlDown(evt)) |
800 | { | |
801 | 0 | sg.addOrRemove(aa[selectedRow].sequenceRef, true); |
802 | } | |
803 | else | |
804 | { | |
805 | // notionally, we should also add intermediate sequences from | |
806 | // last added sequence ? | |
807 | 0 | sg.addSequence(aa[selectedRow].sequenceRef, true); |
808 | } | |
809 | } | |
810 | } | |
811 | else | |
812 | { | |
813 | 0 | sg = new SequenceGroup(); |
814 | 0 | sg.setStartRes(0); |
815 | 0 | sg.setEndRes(ap.av.getAlignment().getWidth() - 1); |
816 | 0 | sg.addSequence(aa[selectedRow].sequenceRef, false); |
817 | } | |
818 | 0 | ap.av.setSelectionGroup(sg); |
819 | 0 | ap.paintAlignment(false, false); |
820 | 0 | PaintRefresher.Refresh(ap, ap.av.getSequenceSetId()); |
821 | 0 | ap.av.sendSelection(); |
822 | } | |
823 | ||
824 | } | |
825 | } | |
826 | ||
827 | } | |
828 | } | |
829 | ||
830 | /** | |
831 | * DOCUMENT ME! | |
832 | * | |
833 | * @param e | |
834 | * DOCUMENT ME! | |
835 | */ | |
836 | 0 | protected void copy_annotseqtoclipboard(SequenceI sq) |
837 | { | |
838 | 0 | if (sq == null || sq.getLength() < 1) |
839 | { | |
840 | 0 | return; |
841 | } | |
842 | 0 | jalview.appletgui.AlignFrame.copiedSequences = new StringBuffer(); |
843 | 0 | jalview.appletgui.AlignFrame.copiedSequences |
844 | .append(sq.getName() + "\t" + sq.getStart() + "\t" + sq.getEnd() | |
845 | + "\t" + sq.getSequenceAsString() + "\n"); | |
846 | 0 | if (av.hasHiddenColumns()) |
847 | { | |
848 | 0 | jalview.appletgui.AlignFrame.copiedHiddenColumns = new HiddenColumns( |
849 | av.getAlignment().getHiddenColumns()); | |
850 | } | |
851 | } | |
852 | ||
853 | 0 | @Override |
854 | public void update(Graphics g) | |
855 | { | |
856 | 0 | paint(g); |
857 | } | |
858 | ||
859 | 0 | @Override |
860 | public void paint(Graphics g) | |
861 | { | |
862 | 0 | int w = getSize().width; |
863 | 0 | int h = getSize().height; |
864 | 0 | if (image == null || w != image.getWidth(this) |
865 | || h != image.getHeight(this)) | |
866 | { | |
867 | 0 | image = createImage(w, ap.annotationPanel.getSize().height); |
868 | } | |
869 | ||
870 | 0 | drawComponent(image.getGraphics(), w); |
871 | 0 | g.drawImage(image, 0, 0, this); |
872 | } | |
873 | ||
874 | 0 | public void drawComponent(Graphics g, int width) |
875 | { | |
876 | 0 | g.setFont(av.getFont()); |
877 | 0 | FontMetrics fm = g.getFontMetrics(av.getFont()); |
878 | 0 | g.setColor(Color.white); |
879 | 0 | g.fillRect(0, 0, getSize().width, getSize().height); |
880 | ||
881 | 0 | g.translate(0, -scrollOffset); |
882 | 0 | g.setColor(Color.black); |
883 | ||
884 | 0 | AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation(); |
885 | 0 | int y = 0, fy = g.getFont().getSize(); |
886 | 0 | int x = 0, offset; |
887 | ||
888 | 0 | if (aa != null) |
889 | { | |
890 | 0 | hasHiddenRows = false; |
891 | 0 | for (int i = 0; i < aa.length; i++) |
892 | { | |
893 | 0 | if (!aa[i].visible) |
894 | { | |
895 | 0 | hasHiddenRows = true; |
896 | 0 | continue; |
897 | } | |
898 | ||
899 | 0 | x = width - fm.stringWidth(aa[i].label) - 3; |
900 | ||
901 | 0 | y += aa[i].height; |
902 | 0 | offset = -(aa[i].height - fy) / 2; |
903 | ||
904 | 0 | g.drawString(aa[i].label, x, y + offset); |
905 | } | |
906 | } | |
907 | 0 | g.translate(0, +scrollOffset); |
908 | ||
909 | 0 | if (!resizePanel && !dragCancelled && dragEvent != null && aa != null) |
910 | { | |
911 | 0 | g.setColor(Color.lightGray); |
912 | 0 | g.drawString(aa[selectedRow].label, dragEvent.getX(), |
913 | dragEvent.getY()); | |
914 | } | |
915 | ||
916 | 0 | if (!av.getWrapAlignment() && ((aa == null) || (aa.length < 1))) |
917 | { | |
918 | 0 | g.setColor(Color.black); |
919 | 0 | g.drawString(MessageManager.getString("label.right_click"), 2, 8); |
920 | 0 | g.drawString(MessageManager.getString("label.to_add_annotation"), 2, |
921 | 18); | |
922 | } | |
923 | } | |
924 | } |