Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
FeatureSettings | 67 | 234 | 83 | ||
FeatureSettings.MyCheckbox | 744 | 32 | 12 |
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.api.FeatureColourI; | |
24 | import jalview.api.FeatureSettingsControllerI; | |
25 | import jalview.datamodel.AlignmentI; | |
26 | import jalview.datamodel.SequenceI; | |
27 | import jalview.util.MessageManager; | |
28 | import jalview.viewmodel.seqfeatures.FeatureRendererModel.FeatureSettingsBean; | |
29 | ||
30 | import java.awt.BorderLayout; | |
31 | import java.awt.Button; | |
32 | import java.awt.Checkbox; | |
33 | import java.awt.Color; | |
34 | import java.awt.Component; | |
35 | import java.awt.Dimension; | |
36 | import java.awt.Font; | |
37 | import java.awt.FontMetrics; | |
38 | import java.awt.Frame; | |
39 | import java.awt.Graphics; | |
40 | import java.awt.GridLayout; | |
41 | import java.awt.Image; | |
42 | import java.awt.Label; | |
43 | import java.awt.MenuItem; | |
44 | import java.awt.Panel; | |
45 | import java.awt.PopupMenu; | |
46 | import java.awt.ScrollPane; | |
47 | import java.awt.Scrollbar; | |
48 | import java.awt.event.ActionEvent; | |
49 | import java.awt.event.ActionListener; | |
50 | import java.awt.event.AdjustmentEvent; | |
51 | import java.awt.event.AdjustmentListener; | |
52 | import java.awt.event.InputEvent; | |
53 | import java.awt.event.ItemEvent; | |
54 | import java.awt.event.ItemListener; | |
55 | import java.awt.event.MouseEvent; | |
56 | import java.awt.event.MouseListener; | |
57 | import java.awt.event.MouseMotionListener; | |
58 | import java.awt.event.WindowAdapter; | |
59 | import java.awt.event.WindowEvent; | |
60 | import java.util.ArrayList; | |
61 | import java.util.Arrays; | |
62 | import java.util.HashSet; | |
63 | import java.util.List; | |
64 | import java.util.Map; | |
65 | import java.util.Set; | |
66 | ||
67 | public class FeatureSettings extends Panel | |
68 | implements ItemListener, MouseListener, MouseMotionListener, | |
69 | AdjustmentListener, FeatureSettingsControllerI | |
70 | { | |
71 | FeatureRenderer fr; | |
72 | ||
73 | AlignmentPanel ap; | |
74 | ||
75 | AlignViewport av; | |
76 | ||
77 | Frame frame; | |
78 | ||
79 | Panel groupPanel; | |
80 | ||
81 | Panel featurePanel = new Panel(); | |
82 | ||
83 | ScrollPane scrollPane; | |
84 | ||
85 | Image linkImage; | |
86 | ||
87 | Scrollbar transparency; | |
88 | ||
89 | 0 | public FeatureSettings(final AlignmentPanel ap) |
90 | { | |
91 | 0 | this.ap = ap; |
92 | 0 | this.av = ap.av; |
93 | 0 | ap.av.featureSettings = this; |
94 | 0 | fr = ap.seqPanel.seqCanvas.getFeatureRenderer(); |
95 | ||
96 | 0 | transparency = new Scrollbar(Scrollbar.HORIZONTAL, |
97 | 100 - (int) (fr.getTransparency() * 100), 1, 1, 100); | |
98 | ||
99 | 0 | transparency.addAdjustmentListener(this); |
100 | ||
101 | 0 | java.net.URL url = getClass().getResource("/images/link.gif"); |
102 | 0 | if (url != null) |
103 | { | |
104 | 0 | linkImage = java.awt.Toolkit.getDefaultToolkit().getImage(url); |
105 | } | |
106 | ||
107 | 0 | if (av.isShowSequenceFeatures() || !fr.hasRenderOrder()) |
108 | { | |
109 | 0 | fr.findAllFeatures(true); // was default - now true to make all visible |
110 | } | |
111 | 0 | groupPanel = new Panel(); |
112 | ||
113 | 0 | discoverAllFeatureData(); |
114 | ||
115 | 0 | this.setLayout(new BorderLayout()); |
116 | 0 | scrollPane = new ScrollPane(); |
117 | 0 | scrollPane.add(featurePanel); |
118 | 0 | if (fr.getAllFeatureColours() != null |
119 | && fr.getAllFeatureColours().size() > 0) | |
120 | { | |
121 | 0 | add(scrollPane, BorderLayout.CENTER); |
122 | } | |
123 | ||
124 | 0 | Button invert = new Button( |
125 | MessageManager.getString("label.invert_selection")); | |
126 | 0 | invert.addActionListener(new ActionListener() |
127 | { | |
128 | ||
129 | 0 | @Override |
130 | public void actionPerformed(ActionEvent e) | |
131 | { | |
132 | 0 | invertSelection(); |
133 | } | |
134 | }); | |
135 | ||
136 | 0 | Panel lowerPanel = new Panel(new GridLayout(2, 1, 5, 10)); |
137 | 0 | lowerPanel.add(invert); |
138 | ||
139 | 0 | Panel tPanel = new Panel(new BorderLayout()); |
140 | ||
141 | 0 | tPanel.add(transparency, BorderLayout.CENTER); |
142 | 0 | tPanel.add(new Label("Transparency"), BorderLayout.EAST); |
143 | ||
144 | 0 | lowerPanel.add(tPanel, BorderLayout.SOUTH); |
145 | ||
146 | 0 | add(lowerPanel, BorderLayout.SOUTH); |
147 | ||
148 | 0 | groupPanel.setLayout( |
149 | new GridLayout((fr.getFeatureGroupsSize()) / 4 + 1, 4)); // JBPNote | |
150 | // - this | |
151 | // was | |
152 | // scaled | |
153 | // on | |
154 | // number | |
155 | // of | |
156 | // visible | |
157 | // groups. | |
158 | // seems | |
159 | // broken | |
160 | 0 | groupPanel.validate(); |
161 | ||
162 | 0 | add(groupPanel, BorderLayout.NORTH); |
163 | ||
164 | 0 | frame = new Frame(); |
165 | 0 | frame.add(this); |
166 | 0 | final FeatureSettings me = this; |
167 | 0 | frame.addWindowListener(new WindowAdapter() |
168 | { | |
169 | 0 | @Override |
170 | public void windowClosing(WindowEvent e) | |
171 | { | |
172 | 0 | if (me.av.featureSettings == me) |
173 | { | |
174 | 0 | me.av.featureSettings = null; |
175 | 0 | me.ap = null; |
176 | 0 | me.av = null; |
177 | } | |
178 | } | |
179 | }); | |
180 | 0 | int height = featurePanel.getComponentCount() * 50 + 60; |
181 | ||
182 | 0 | height = Math.max(200, height); |
183 | 0 | height = Math.min(400, height); |
184 | 0 | int width = 300; |
185 | 0 | jalview.bin.JalviewLite.addFrame(frame, |
186 | MessageManager.getString("label.sequence_feature_settings"), | |
187 | width, height); | |
188 | } | |
189 | ||
190 | 0 | @Override |
191 | public void paint(Graphics g) | |
192 | { | |
193 | 0 | g.setColor(Color.black); |
194 | 0 | g.drawString(MessageManager.getString( |
195 | "label.no_features_added_to_this_alignment"), 10, 20); | |
196 | 0 | g.drawString(MessageManager.getString( |
197 | "label.features_can_be_added_from_searches_1"), 10, 40); | |
198 | 0 | g.drawString(MessageManager.getString( |
199 | "label.features_can_be_added_from_searches_2"), 10, 60); | |
200 | } | |
201 | ||
202 | 0 | protected void popupSort(final MyCheckbox check, |
203 | final Map<String, float[][]> minmax, int x, int y) | |
204 | { | |
205 | 0 | final String type = check.type; |
206 | 0 | final FeatureColourI typeCol = fr.getFeatureStyle(type); |
207 | 0 | PopupMenu men = new PopupMenu(MessageManager |
208 | .formatMessage("label.settings_for_type", new String[] | |
209 | { type })); | |
210 | 0 | java.awt.MenuItem scr = new MenuItem( |
211 | MessageManager.getString("label.sort_by_score")); | |
212 | 0 | men.add(scr); |
213 | 0 | final FeatureSettings me = this; |
214 | 0 | scr.addActionListener(new ActionListener() |
215 | { | |
216 | ||
217 | 0 | @Override |
218 | public void actionPerformed(ActionEvent e) | |
219 | { | |
220 | 0 | me.ap.alignFrame.avc |
221 | .sortAlignmentByFeatureScore(Arrays.asList(new String[] | |
222 | { type })); | |
223 | } | |
224 | ||
225 | }); | |
226 | 0 | MenuItem dens = new MenuItem( |
227 | MessageManager.getString("label.sort_by_density")); | |
228 | 0 | dens.addActionListener(new ActionListener() |
229 | { | |
230 | ||
231 | 0 | @Override |
232 | public void actionPerformed(ActionEvent e) | |
233 | { | |
234 | 0 | me.ap.alignFrame.avc |
235 | .sortAlignmentByFeatureDensity(Arrays.asList(new String[] | |
236 | { type })); | |
237 | } | |
238 | ||
239 | }); | |
240 | 0 | men.add(dens); |
241 | ||
242 | 0 | if (minmax != null) |
243 | { | |
244 | 0 | final float[][] typeMinMax = minmax.get(type); |
245 | /* | |
246 | * final java.awt.CheckboxMenuItem chb = new | |
247 | * java.awt.CheckboxMenuItem("Vary Height"); // this is broken at the | |
248 | * moment chb.setState(minmax.get(type) != null); | |
249 | * chb.addActionListener(new ActionListener() { | |
250 | * | |
251 | * public void actionPerformed(ActionEvent e) { | |
252 | * chb.setState(chb.getState()); if (chb.getState()) { minmax.put(type, | |
253 | * null); } else { minmax.put(type, typeMinMax); } } | |
254 | * | |
255 | * }); men.add(chb); | |
256 | */ | |
257 | 0 | if (typeMinMax != null && typeMinMax[0] != null) |
258 | { | |
259 | // graduated colourschemes for those where minmax exists for the | |
260 | // positional features | |
261 | 0 | MenuItem mxcol = new MenuItem( |
262 | 0 | (typeCol.isSimpleColour()) ? "Graduated Colour" |
263 | : "Single Colour"); | |
264 | 0 | men.add(mxcol); |
265 | 0 | mxcol.addActionListener(new ActionListener() |
266 | { | |
267 | ||
268 | 0 | @Override |
269 | public void actionPerformed(ActionEvent e) | |
270 | { | |
271 | 0 | if (typeCol.isSimpleColour()) |
272 | { | |
273 | 0 | new FeatureColourChooser(me, type); |
274 | // write back the current colour object to update the table | |
275 | 0 | check.updateColor(fr.getFeatureStyle(type)); |
276 | } | |
277 | else | |
278 | { | |
279 | 0 | new UserDefinedColours(me, check.type, typeCol); |
280 | } | |
281 | } | |
282 | ||
283 | }); | |
284 | } | |
285 | } | |
286 | ||
287 | 0 | MenuItem selectContaining = new MenuItem( |
288 | MessageManager.getString("label.select_columns_containing")); | |
289 | 0 | selectContaining.addActionListener(new ActionListener() |
290 | { | |
291 | 0 | @Override |
292 | public void actionPerformed(ActionEvent e) | |
293 | { | |
294 | 0 | me.ap.alignFrame.avc.markColumnsContainingFeatures(false, false, |
295 | false, type); | |
296 | } | |
297 | }); | |
298 | 0 | men.add(selectContaining); |
299 | ||
300 | 0 | MenuItem selectNotContaining = new MenuItem(MessageManager |
301 | .getString("label.select_columns_not_containing")); | |
302 | 0 | selectNotContaining.addActionListener(new ActionListener() |
303 | { | |
304 | 0 | @Override |
305 | public void actionPerformed(ActionEvent e) | |
306 | { | |
307 | 0 | me.ap.alignFrame.avc.markColumnsContainingFeatures(true, false, |
308 | false, type); | |
309 | } | |
310 | }); | |
311 | 0 | men.add(selectNotContaining); |
312 | ||
313 | 0 | MenuItem hideContaining = new MenuItem( |
314 | MessageManager.getString("label.hide_columns_containing")); | |
315 | 0 | hideContaining.addActionListener(new ActionListener() |
316 | { | |
317 | 0 | @Override |
318 | public void actionPerformed(ActionEvent e) | |
319 | { | |
320 | 0 | hideFeatureColumns(type, true); |
321 | } | |
322 | }); | |
323 | 0 | men.add(hideContaining); |
324 | ||
325 | 0 | MenuItem hideNotContaining = new MenuItem( |
326 | MessageManager.getString("label.hide_columns_not_containing")); | |
327 | 0 | hideNotContaining.addActionListener(new ActionListener() |
328 | { | |
329 | 0 | @Override |
330 | public void actionPerformed(ActionEvent e) | |
331 | { | |
332 | 0 | hideFeatureColumns(type, false); |
333 | } | |
334 | }); | |
335 | 0 | men.add(hideNotContaining); |
336 | ||
337 | 0 | this.featurePanel.add(men); |
338 | 0 | men.show(this.featurePanel, x, y); |
339 | } | |
340 | ||
341 | 0 | @Override |
342 | public void discoverAllFeatureData() | |
343 | { | |
344 | 0 | if (fr.getAllFeatureColours() != null |
345 | && fr.getAllFeatureColours().size() > 0) | |
346 | { | |
347 | // rebuildGroups(); | |
348 | ||
349 | } | |
350 | 0 | resetTable(false); |
351 | } | |
352 | ||
353 | /** | |
354 | * Answers the visibility of the given group, and adds a checkbox for it if | |
355 | * there is not one already | |
356 | */ | |
357 | 0 | public boolean checkGroupState(String group) |
358 | { | |
359 | 0 | boolean visible = fr.checkGroupVisibility(group, true); |
360 | ||
361 | /* | |
362 | * is there already a checkbox for this group? | |
363 | */ | |
364 | 0 | for (int g = 0; g < groupPanel.getComponentCount(); g++) |
365 | { | |
366 | 0 | if (((Checkbox) groupPanel.getComponent(g)).getLabel().equals(group)) |
367 | { | |
368 | 0 | ((Checkbox) groupPanel.getComponent(g)).setState(visible); |
369 | 0 | return visible; |
370 | } | |
371 | } | |
372 | ||
373 | /* | |
374 | * add a new checkbox | |
375 | */ | |
376 | 0 | Checkbox check = new MyCheckbox(group, visible, false); |
377 | 0 | check.addMouseListener(this); |
378 | 0 | check.setFont(new Font("Serif", Font.BOLD, 12)); |
379 | 0 | check.addItemListener(groupItemListener); |
380 | 0 | groupPanel.add(check); |
381 | ||
382 | 0 | groupPanel.validate(); |
383 | 0 | return visible; |
384 | } | |
385 | ||
386 | // This routine adds and removes checkboxes depending on | |
387 | // Group selection states | |
388 | 0 | void resetTable(boolean groupsChanged) |
389 | { | |
390 | 0 | List<String> displayableTypes = new ArrayList<>(); |
391 | 0 | Set<String> foundGroups = new HashSet<>(); |
392 | ||
393 | 0 | AlignmentI alignment = av.getAlignment(); |
394 | ||
395 | 0 | for (int i = 0; i < alignment.getHeight(); i++) |
396 | { | |
397 | 0 | SequenceI seq = alignment.getSequenceAt(i); |
398 | ||
399 | /* | |
400 | * get the sequence's groups for positional features | |
401 | * and keep track of which groups are visible | |
402 | */ | |
403 | 0 | Set<String> groups = seq.getFeatures().getFeatureGroups(true); |
404 | 0 | Set<String> visibleGroups = new HashSet<>(); |
405 | 0 | for (String group : groups) |
406 | { | |
407 | // if (group == null || fr.checkGroupVisibility(group, true)) | |
408 | 0 | if (group == null || checkGroupState(group)) |
409 | { | |
410 | 0 | visibleGroups.add(group); |
411 | } | |
412 | } | |
413 | 0 | foundGroups.addAll(groups); |
414 | ||
415 | /* | |
416 | * get distinct feature types for visible groups | |
417 | * record distinct visible types | |
418 | */ | |
419 | 0 | Set<String> types = seq.getFeatures().getFeatureTypesForGroups(true, |
420 | visibleGroups.toArray(new String[visibleGroups.size()])); | |
421 | 0 | displayableTypes.addAll(types); |
422 | } | |
423 | ||
424 | /* | |
425 | * remove any checkboxes for groups not present | |
426 | */ | |
427 | 0 | pruneGroups(foundGroups); |
428 | ||
429 | 0 | Component[] comps; |
430 | 0 | int cSize = featurePanel.getComponentCount(); |
431 | 0 | MyCheckbox check; |
432 | // This will remove any checkboxes which shouldn't be | |
433 | // visible | |
434 | 0 | for (int i = 0; i < cSize; i++) |
435 | { | |
436 | 0 | comps = featurePanel.getComponents(); |
437 | 0 | check = (MyCheckbox) comps[i]; |
438 | 0 | if (!displayableTypes.contains(check.type)) |
439 | { | |
440 | 0 | featurePanel.remove(i); |
441 | 0 | cSize--; |
442 | 0 | i--; |
443 | } | |
444 | } | |
445 | ||
446 | 0 | if (fr.getRenderOrder() != null) |
447 | { | |
448 | // First add the checks in the previous render order, | |
449 | // in case the window has been closed and reopened | |
450 | 0 | List<String> rol = fr.getRenderOrder(); |
451 | 0 | for (int ro = rol.size() - 1; ro > -1; ro--) |
452 | { | |
453 | 0 | String item = rol.get(ro); |
454 | ||
455 | 0 | if (!displayableTypes.contains(item)) |
456 | { | |
457 | 0 | continue; |
458 | } | |
459 | ||
460 | 0 | displayableTypes.remove(item); |
461 | ||
462 | 0 | addCheck(false, item); |
463 | } | |
464 | } | |
465 | ||
466 | /* | |
467 | * now add checkboxes which should be visible, | |
468 | * if they have not already been added | |
469 | */ | |
470 | 0 | for (String type : displayableTypes) |
471 | { | |
472 | 0 | addCheck(groupsChanged, type); |
473 | } | |
474 | ||
475 | 0 | featurePanel.setLayout( |
476 | new GridLayout(featurePanel.getComponentCount(), 1, 10, 5)); | |
477 | 0 | featurePanel.validate(); |
478 | ||
479 | 0 | if (scrollPane != null) |
480 | { | |
481 | 0 | scrollPane.validate(); |
482 | } | |
483 | ||
484 | 0 | itemStateChanged(null); |
485 | } | |
486 | ||
487 | /** | |
488 | * Remove from the groups panel any checkboxes for groups that are not in the | |
489 | * foundGroups set. This enables removing a group from the display when the | |
490 | * last feature in that group is deleted. | |
491 | * | |
492 | * @param foundGroups | |
493 | */ | |
494 | 0 | protected void pruneGroups(Set<String> foundGroups) |
495 | { | |
496 | 0 | for (int g = 0; g < groupPanel.getComponentCount(); g++) |
497 | { | |
498 | 0 | Checkbox checkbox = (Checkbox) groupPanel.getComponent(g); |
499 | 0 | if (!foundGroups.contains(checkbox.getLabel())) |
500 | { | |
501 | 0 | groupPanel.remove(checkbox); |
502 | } | |
503 | } | |
504 | } | |
505 | ||
506 | /** | |
507 | * update the checklist of feature types with the given type | |
508 | * | |
509 | * @param groupsChanged | |
510 | * true means if the type is not in the display list then it will be | |
511 | * added and displayed | |
512 | * @param type | |
513 | * feature type to be checked for in the list. | |
514 | */ | |
515 | 0 | void addCheck(boolean groupsChanged, String type) |
516 | { | |
517 | 0 | boolean addCheck; |
518 | 0 | Component[] comps = featurePanel.getComponents(); |
519 | 0 | MyCheckbox check; |
520 | 0 | addCheck = true; |
521 | 0 | for (int i = 0; i < featurePanel.getComponentCount(); i++) |
522 | { | |
523 | 0 | check = (MyCheckbox) comps[i]; |
524 | 0 | if (check.type.equals(type)) |
525 | { | |
526 | 0 | addCheck = false; |
527 | 0 | break; |
528 | } | |
529 | } | |
530 | ||
531 | 0 | if (addCheck) |
532 | { | |
533 | 0 | boolean selected = false; |
534 | 0 | if (groupsChanged || av.getFeaturesDisplayed().isVisible(type)) |
535 | { | |
536 | 0 | selected = true; |
537 | } | |
538 | ||
539 | 0 | check = new MyCheckbox(type, selected, false, |
540 | fr.getFeatureStyle(type)); | |
541 | ||
542 | 0 | check.addMouseListener(this); |
543 | 0 | check.addMouseMotionListener(this); |
544 | 0 | check.addItemListener(this); |
545 | 0 | if (groupsChanged) |
546 | { | |
547 | // add at beginning of stack. | |
548 | 0 | featurePanel.add(check, 0); |
549 | } | |
550 | else | |
551 | { | |
552 | // add at end of stack. | |
553 | 0 | featurePanel.add(check); |
554 | } | |
555 | } | |
556 | } | |
557 | ||
558 | 0 | protected void invertSelection() |
559 | { | |
560 | 0 | for (int i = 0; i < featurePanel.getComponentCount(); i++) |
561 | { | |
562 | 0 | Checkbox check = (Checkbox) featurePanel.getComponent(i); |
563 | 0 | check.setState(!check.getState()); |
564 | } | |
565 | 0 | selectionChanged(true); |
566 | } | |
567 | ||
568 | private ItemListener groupItemListener = new ItemListener() | |
569 | { | |
570 | 0 | @Override |
571 | public void itemStateChanged(ItemEvent evt) | |
572 | { | |
573 | 0 | Checkbox source = (Checkbox) evt.getSource(); |
574 | 0 | fr.setGroupVisibility(source.getLabel(), source.getState()); |
575 | 0 | ap.seqPanel.seqCanvas.repaint(); |
576 | 0 | if (ap.overviewPanel != null) |
577 | { | |
578 | 0 | ap.overviewPanel.updateOverviewImage(); |
579 | } | |
580 | 0 | resetTable(true); |
581 | 0 | return; |
582 | }; | |
583 | }; | |
584 | ||
585 | 0 | @Override |
586 | public void itemStateChanged(ItemEvent evt) | |
587 | { | |
588 | 0 | selectionChanged(true); |
589 | } | |
590 | ||
591 | 0 | void selectionChanged(boolean updateOverview) |
592 | { | |
593 | 0 | Component[] comps = featurePanel.getComponents(); |
594 | 0 | int cSize = comps.length; |
595 | 0 | FeatureSettingsBean[] rowData = new FeatureSettingsBean[cSize]; |
596 | 0 | int i = 0; |
597 | 0 | for (Component comp : comps) |
598 | { | |
599 | 0 | MyCheckbox check = (MyCheckbox) comp; |
600 | // feature filter set to null as not (yet) offered in applet | |
601 | 0 | FeatureColourI colour = fr.getFeatureStyle(check.type); |
602 | 0 | rowData[i] = new FeatureSettingsBean(check.type, colour, null, |
603 | check.getState()); | |
604 | 0 | i++; |
605 | } | |
606 | ||
607 | 0 | fr.setFeaturePriority(rowData); |
608 | ||
609 | 0 | ap.paintAlignment(updateOverview, updateOverview); |
610 | } | |
611 | ||
612 | MyCheckbox selectedCheck; | |
613 | ||
614 | boolean dragging = false; | |
615 | ||
616 | 0 | @Override |
617 | public void mouseDragged(MouseEvent evt) | |
618 | { | |
619 | 0 | if (((Component) evt.getSource()).getParent() != featurePanel) |
620 | { | |
621 | 0 | return; |
622 | } | |
623 | 0 | dragging = true; |
624 | } | |
625 | ||
626 | 0 | @Override |
627 | public void mouseReleased(MouseEvent evt) | |
628 | { | |
629 | 0 | if (((Component) evt.getSource()).getParent() != featurePanel) |
630 | { | |
631 | 0 | return; |
632 | } | |
633 | ||
634 | 0 | Component comp = null; |
635 | 0 | Checkbox target = null; |
636 | ||
637 | 0 | int height = evt.getY() + evt.getComponent().getLocation().y; |
638 | ||
639 | 0 | if (height > featurePanel.getSize().height) |
640 | { | |
641 | ||
642 | 0 | comp = featurePanel |
643 | .getComponent(featurePanel.getComponentCount() - 1); | |
644 | } | |
645 | 0 | else if (height < 0) |
646 | { | |
647 | 0 | comp = featurePanel.getComponent(0); |
648 | } | |
649 | else | |
650 | { | |
651 | 0 | comp = featurePanel.getComponentAt(evt.getX(), |
652 | evt.getY() + evt.getComponent().getLocation().y); | |
653 | } | |
654 | ||
655 | 0 | if (comp != null && comp instanceof Checkbox) |
656 | { | |
657 | 0 | target = (Checkbox) comp; |
658 | } | |
659 | ||
660 | 0 | if (selectedCheck != null && target != null && selectedCheck != target) |
661 | { | |
662 | 0 | int targetIndex = -1; |
663 | 0 | for (int i = 0; i < featurePanel.getComponentCount(); i++) |
664 | { | |
665 | 0 | if (target == featurePanel.getComponent(i)) |
666 | { | |
667 | 0 | targetIndex = i; |
668 | 0 | break; |
669 | } | |
670 | } | |
671 | ||
672 | 0 | featurePanel.remove(selectedCheck); |
673 | 0 | featurePanel.add(selectedCheck, targetIndex); |
674 | 0 | featurePanel.validate(); |
675 | 0 | itemStateChanged(null); |
676 | } | |
677 | } | |
678 | ||
679 | 0 | public void setUserColour(String feature, FeatureColourI originalColour) |
680 | { | |
681 | 0 | fr.setColour(feature, originalColour); |
682 | 0 | refreshTable(); |
683 | } | |
684 | ||
685 | 0 | public void refreshTable() |
686 | { | |
687 | 0 | featurePanel.removeAll(); |
688 | 0 | resetTable(false); |
689 | 0 | ap.paintAlignment(true, true); |
690 | } | |
691 | ||
692 | 0 | @Override |
693 | public void mouseEntered(MouseEvent evt) | |
694 | { | |
695 | } | |
696 | ||
697 | 0 | @Override |
698 | public void mouseExited(MouseEvent evt) | |
699 | { | |
700 | } | |
701 | ||
702 | 0 | @Override |
703 | public void mouseClicked(MouseEvent evt) | |
704 | { | |
705 | 0 | MyCheckbox check = (MyCheckbox) evt.getSource(); |
706 | 0 | if ((evt.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) != 0) |
707 | { | |
708 | 0 | this.popupSort(check, fr.getMinMax(), evt.getX(), evt.getY()); |
709 | } | |
710 | ||
711 | 0 | if (check.getParent() != featurePanel) |
712 | { | |
713 | 0 | return; |
714 | } | |
715 | ||
716 | 0 | if (evt.getClickCount() > 1) |
717 | { | |
718 | 0 | FeatureColourI fcol = fr.getFeatureStyle(check.type); |
719 | 0 | if (fcol.isSimpleColour()) |
720 | { | |
721 | 0 | new UserDefinedColours(this, check.type, fcol.getColour()); |
722 | } | |
723 | else | |
724 | { | |
725 | 0 | new FeatureColourChooser(this, check.type); |
726 | // write back the current colour object to update the table | |
727 | 0 | check.updateColor(fr.getFeatureStyle(check.type)); |
728 | } | |
729 | } | |
730 | } | |
731 | ||
732 | 0 | @Override |
733 | public void mouseMoved(MouseEvent evt) | |
734 | { | |
735 | } | |
736 | ||
737 | 0 | @Override |
738 | public void adjustmentValueChanged(AdjustmentEvent evt) | |
739 | { | |
740 | 0 | fr.setTransparency((100 - transparency.getValue()) / 100f); |
741 | 0 | ap.paintAlignment(true, true); |
742 | } | |
743 | ||
744 | class MyCheckbox extends Checkbox | |
745 | { | |
746 | public String type; | |
747 | ||
748 | public int stringWidth; | |
749 | ||
750 | boolean hasLink; | |
751 | ||
752 | FeatureColourI col; | |
753 | ||
754 | 0 | public void updateColor(FeatureColourI newcol) |
755 | { | |
756 | 0 | col = newcol; |
757 | 0 | if (col.isSimpleColour()) |
758 | { | |
759 | 0 | setBackground(col.getColour()); |
760 | } | |
761 | else | |
762 | { | |
763 | 0 | String vlabel = type; |
764 | 0 | if (col.isAboveThreshold()) |
765 | { | |
766 | 0 | vlabel += " (>)"; |
767 | } | |
768 | 0 | else if (col.isBelowThreshold()) |
769 | { | |
770 | 0 | vlabel += " (<)"; |
771 | } | |
772 | 0 | if (col.isColourByLabel()) |
773 | { | |
774 | 0 | setBackground(Color.white); |
775 | 0 | vlabel += " (by Label)"; |
776 | } | |
777 | else | |
778 | { | |
779 | 0 | setBackground(col.getMinColour()); |
780 | } | |
781 | 0 | this.setLabel(vlabel); |
782 | } | |
783 | 0 | repaint(); |
784 | } | |
785 | ||
786 | 0 | public MyCheckbox(String label, boolean checked, boolean haslink) |
787 | { | |
788 | 0 | super(label, checked); |
789 | 0 | type = label; |
790 | 0 | FontMetrics fm = av.nullFrame.getFontMetrics(av.nullFrame.getFont()); |
791 | 0 | stringWidth = fm.stringWidth(label); |
792 | 0 | this.hasLink = haslink; |
793 | } | |
794 | ||
795 | 0 | public MyCheckbox(String type, boolean selected, boolean b, |
796 | FeatureColourI featureStyle) | |
797 | { | |
798 | 0 | this(type, selected, b); |
799 | 0 | updateColor(featureStyle); |
800 | } | |
801 | ||
802 | 0 | @Override |
803 | public void paint(Graphics g) | |
804 | { | |
805 | 0 | Dimension d = getSize(); |
806 | 0 | if (col != null) |
807 | { | |
808 | 0 | if (col.isColourByLabel()) |
809 | { | |
810 | 0 | g.setColor(Color.white); |
811 | 0 | g.fillRect(d.width / 2, 0, d.width / 2, d.height); |
812 | /* | |
813 | * g.setColor(Color.black); Font f=g.getFont().deriveFont(9); | |
814 | * g.setFont(f); | |
815 | * | |
816 | * // g.setFont(g.getFont().deriveFont( // | |
817 | * AffineTransform.getScaleInstance( // | |
818 | * width/g.getFontMetrics().stringWidth("Label"), // | |
819 | * height/g.getFontMetrics().getHeight()))); g.drawString("Label", | |
820 | * width/2, 0); | |
821 | */ | |
822 | ||
823 | } | |
824 | 0 | else if (col.isGraduatedColour()) |
825 | { | |
826 | 0 | Color maxCol = col.getMaxColour(); |
827 | 0 | g.setColor(maxCol); |
828 | 0 | g.fillRect(d.width / 2, 0, d.width / 2, d.height); |
829 | ||
830 | } | |
831 | } | |
832 | ||
833 | 0 | if (hasLink) |
834 | { | |
835 | 0 | g.drawImage(linkImage, stringWidth + 25, |
836 | (getSize().height - linkImage.getHeight(this)) / 2, this); | |
837 | } | |
838 | } | |
839 | } | |
840 | ||
841 | /** | |
842 | * Hide columns containing (or not containing) a given feature type | |
843 | * | |
844 | * @param type | |
845 | * @param columnsContaining | |
846 | */ | |
847 | 0 | void hideFeatureColumns(final String type, boolean columnsContaining) |
848 | { | |
849 | 0 | if (ap.alignFrame.avc.markColumnsContainingFeatures(columnsContaining, |
850 | false, false, type)) | |
851 | { | |
852 | 0 | if (ap.alignFrame.avc.markColumnsContainingFeatures( |
853 | !columnsContaining, false, false, type)) | |
854 | { | |
855 | 0 | ap.alignFrame.viewport.hideSelectedColumns(); |
856 | } | |
857 | } | |
858 | } | |
859 | ||
860 | 0 | @Override |
861 | public void mousePressed(MouseEvent e) | |
862 | { | |
863 | // TODO Auto-generated method stub | |
864 | ||
865 | } | |
866 | ||
867 | } |