2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
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.
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.
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.
23 import jalview.api.FeatureColourI;
24 import jalview.api.FeatureSettingsControllerI;
25 import jalview.bin.Jalview;
26 import jalview.datamodel.AlignmentI;
27 import jalview.datamodel.SequenceI;
28 import jalview.datamodel.features.FeatureMatcher;
29 import jalview.datamodel.features.FeatureMatcherI;
30 import jalview.datamodel.features.FeatureMatcherSet;
31 import jalview.datamodel.features.FeatureMatcherSetI;
32 import jalview.gui.Help.HelpId;
33 import jalview.gui.JalviewColourChooser.ColourChooserListener;
34 import jalview.io.JalviewFileChooser;
35 import jalview.io.JalviewFileView;
36 import jalview.schemes.FeatureColour;
37 import jalview.util.MessageManager;
38 import jalview.util.Platform;
39 import jalview.util.dialogrunner.RunResponse;
40 import jalview.viewmodel.seqfeatures.FeatureRendererModel.FeatureSettingsBean;
41 import jalview.xml.binding.jalview.JalviewUserColours;
42 import jalview.xml.binding.jalview.JalviewUserColours.Colour;
43 import jalview.xml.binding.jalview.JalviewUserColours.Filter;
44 import jalview.xml.binding.jalview.ObjectFactory;
46 import java.awt.BorderLayout;
47 import java.awt.Color;
48 import java.awt.Component;
49 import java.awt.Dimension;
51 import java.awt.Graphics;
52 import java.awt.GridLayout;
53 import java.awt.Point;
54 import java.awt.Rectangle;
55 import java.awt.event.ActionEvent;
56 import java.awt.event.ActionListener;
57 import java.awt.event.ItemEvent;
58 import java.awt.event.ItemListener;
59 import java.awt.event.MouseAdapter;
60 import java.awt.event.MouseEvent;
61 import java.awt.event.MouseMotionAdapter;
62 import java.beans.PropertyChangeEvent;
63 import java.beans.PropertyChangeListener;
65 import java.io.FileInputStream;
66 import java.io.FileOutputStream;
67 import java.io.InputStreamReader;
68 import java.io.OutputStreamWriter;
69 import java.io.PrintWriter;
70 import java.util.Arrays;
71 import java.util.Comparator;
72 import java.util.HashMap;
73 import java.util.HashSet;
74 import java.util.Hashtable;
75 import java.util.Iterator;
76 import java.util.List;
80 import javax.help.HelpSetException;
81 import javax.swing.AbstractCellEditor;
82 import javax.swing.BorderFactory;
83 import javax.swing.Icon;
84 import javax.swing.JButton;
85 import javax.swing.JCheckBox;
86 import javax.swing.JCheckBoxMenuItem;
87 import javax.swing.JInternalFrame;
88 import javax.swing.JLabel;
89 import javax.swing.JLayeredPane;
90 import javax.swing.JMenuItem;
91 import javax.swing.JPanel;
92 import javax.swing.JPopupMenu;
93 import javax.swing.JScrollPane;
94 import javax.swing.JSlider;
95 import javax.swing.JTable;
96 import javax.swing.ListSelectionModel;
97 import javax.swing.SwingConstants;
98 import javax.swing.ToolTipManager;
99 import javax.swing.border.Border;
100 import javax.swing.event.ChangeEvent;
101 import javax.swing.event.ChangeListener;
102 import javax.swing.plaf.TableUI;
103 import javax.swing.table.AbstractTableModel;
104 import javax.swing.table.TableCellEditor;
105 import javax.swing.table.TableCellRenderer;
106 import javax.swing.table.TableColumn;
107 import javax.xml.bind.JAXBContext;
108 import javax.xml.bind.JAXBElement;
109 import javax.xml.bind.Marshaller;
110 import javax.xml.stream.XMLInputFactory;
111 import javax.xml.stream.XMLStreamReader;
113 public class FeatureSettings extends JPanel
114 implements FeatureSettingsControllerI
116 private static final String SEQUENCE_FEATURE_COLOURS = MessageManager
117 .getString("label.sequence_feature_colours");
120 * column indices of fields in Feature Settings table
122 static final int TYPE_COLUMN = 0;
124 static final int COLOUR_COLUMN = 1;
126 static final int FILTER_COLUMN = 2;
128 static final int SHOW_COLUMN = 3;
130 private static final int COLUMN_COUNT = 4;
132 private static final int MIN_WIDTH = 400;
134 private static final int MIN_HEIGHT = 400;
136 private final static String BASE_TOOLTIP = MessageManager.getString("label.click_to_edit");
138 final FeatureRenderer fr;
140 public final AlignFrame af;
143 * 'original' fields hold settings to restore on Cancel
145 Object[][] originalData;
147 float originalTransparency;
149 Map<String, FeatureMatcherSetI> originalFilters;
151 final JInternalFrame frame;
153 JScrollPane scrollPane = new JScrollPane();
159 JSlider transparency = new JSlider();
162 * when true, constructor is still executing - so ignore UI events
164 protected volatile boolean inConstruction = true;
166 int selectedRow = -1;
168 JButton fetchDAS = new JButton();
170 JButton saveDAS = new JButton();
172 JButton cancelDAS = new JButton();
174 boolean resettingTable = false;
177 * true when Feature Settings are updating from feature renderer
179 boolean handlingUpdate = false;
182 * holds {featureCount, totalExtent} for each feature type
184 Map<String, float[]> typeWidth = null;
191 public FeatureSettings(AlignFrame alignFrame)
193 this.af = alignFrame;
194 fr = af.getFeatureRenderer();
196 // save transparency for restore on Cancel
197 originalTransparency = fr.getTransparency();
198 int originalTransparencyAsPercent = (int) (originalTransparency * 100);
199 transparency.setMaximum(100 - originalTransparencyAsPercent);
201 originalFilters = new HashMap<>(fr.getFeatureFilters()); // shallow copy
206 } catch (Exception ex)
208 ex.printStackTrace();
214 public String getToolTipText(MouseEvent e)
217 int column = table.columnAtPoint(e.getPoint());
218 int row = table.rowAtPoint(e.getPoint());
223 tip = JvSwingUtils.wrapTooltip(true, MessageManager
224 .getString("label.feature_settings_click_drag"));
227 FeatureColourI colour = (FeatureColourI) table.getValueAt(row,
229 tip = getColorTooltip(colour, true);
232 FeatureMatcherSet o = (FeatureMatcherSet) table.getValueAt(row,
235 ? MessageManager.getString("label.filters_tooltip")
247 * Position the tooltip near the bottom edge of, and half way across, the
251 public Point getToolTipLocation(MouseEvent e)
253 Point point = e.getPoint();
254 int column = table.columnAtPoint(point);
255 int row = table.rowAtPoint(point);
256 Rectangle r = getCellRect(row, column, false);
257 Point loc = new Point(r.x + r.width / 2, r.y + r.height - 3);
262 // next line is needed to avoid (quiet) exceptions thrown
263 // when column ordering changes so that the above constants
265 table.getTableHeader().setReorderingAllowed(false); // BH 2018
267 table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));
268 ToolTipManager.sharedInstance().registerComponent(table);
270 table.setDefaultEditor(FeatureColour.class, new ColorEditor(this));
271 table.setDefaultRenderer(FeatureColour.class, new ColorRenderer());
273 table.setDefaultEditor(FeatureMatcherSet.class, new FilterEditor(this));
274 table.setDefaultRenderer(FeatureMatcherSet.class, new FilterRenderer());
276 TableColumn colourColumn = new TableColumn(COLOUR_COLUMN, 75,
277 new ColorRenderer(), new ColorEditor(this));
278 table.addColumn(colourColumn);
280 TableColumn filterColumn = new TableColumn(FILTER_COLUMN, 75,
281 new FilterRenderer(), new FilterEditor(this));
282 table.addColumn(filterColumn);
284 table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
286 table.addMouseListener(new MouseAdapter()
289 public void mousePressed(MouseEvent evt)
291 selectedRow = table.rowAtPoint(evt.getPoint());
292 String type = (String) table.getValueAt(selectedRow, TYPE_COLUMN);
293 if (evt.isPopupTrigger())
295 Object colour = table.getValueAt(selectedRow, COLOUR_COLUMN);
296 showPopupMenu(selectedRow, type, colour, evt.getPoint());
298 else if (evt.getClickCount() == 2)
300 boolean invertSelection = evt.isAltDown();
301 boolean toggleSelection = Platform.isControlDown(evt);
302 boolean extendSelection = evt.isShiftDown();
303 fr.ap.alignFrame.avc.markColumnsContainingFeatures(
304 invertSelection, extendSelection, toggleSelection, type);
308 // isPopupTrigger fires on mouseReleased on Windows
310 public void mouseReleased(MouseEvent evt)
312 selectedRow = table.rowAtPoint(evt.getPoint());
313 if (evt.isPopupTrigger())
315 String type = (String) table.getValueAt(selectedRow, TYPE_COLUMN);
316 Object colour = table.getValueAt(selectedRow, COLOUR_COLUMN);
317 showPopupMenu(selectedRow, type, colour, evt.getPoint());
322 table.addMouseMotionListener(new MouseMotionAdapter()
325 public void mouseDragged(MouseEvent evt)
327 int newRow = table.rowAtPoint(evt.getPoint());
328 if (newRow != selectedRow && selectedRow != -1 && newRow != -1)
331 * reposition 'selectedRow' to 'newRow' (the dragged to location)
332 * this could be more than one row away for a very fast drag action
333 * so just swap it with adjacent rows until we get it there
335 Object[][] data = ((FeatureTableModel) table.getModel())
337 int direction = newRow < selectedRow ? -1 : 1;
338 for (int i = selectedRow; i != newRow; i += direction)
340 Object[] temp = data[i];
341 data[i] = data[i + direction];
342 data[i + direction] = temp;
344 updateFeatureRenderer(data);
346 selectedRow = newRow;
350 // table.setToolTipText(JvSwingUtils.wrapTooltip(true,
351 // MessageManager.getString("label.feature_settings_click_drag")));
352 scrollPane.setViewportView(table);
354 if (af.getViewport().isShowSequenceFeatures() || !fr.hasRenderOrder())
356 fr.findAllFeatures(true); // display everything!
359 discoverAllFeatureData();
360 final PropertyChangeListener change;
361 final FeatureSettings fs = this;
362 fr.addPropertyChangeListener(change = new PropertyChangeListener()
365 public void propertyChange(PropertyChangeEvent evt)
367 if (!fs.resettingTable && !fs.handlingUpdate)
369 fs.handlingUpdate = true;
371 // new groups may be added with new sequence feature types only
372 fs.handlingUpdate = false;
378 frame = new JInternalFrame();
379 frame.setContentPane(this);
380 if (Platform.isAMac())
382 Desktop.addInternalFrame(frame,
383 MessageManager.getString("label.sequence_feature_settings"),
388 Desktop.addInternalFrame(frame,
389 MessageManager.getString("label.sequence_feature_settings"),
392 frame.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
394 frame.addInternalFrameListener(
395 new javax.swing.event.InternalFrameAdapter()
398 public void internalFrameClosed(
399 javax.swing.event.InternalFrameEvent evt)
401 fr.removePropertyChangeListener(change);
404 frame.setLayer(JLayeredPane.PALETTE_LAYER);
405 inConstruction = false;
409 * Constructs and shows a popup menu of possible actions on the selected row and
417 protected void showPopupMenu(final int rowSelected, final String type,
418 final Object typeCol, final Point pt)
420 final FeatureColourI featureColour = (FeatureColourI) typeCol;
422 JPopupMenu men = new JPopupMenu(MessageManager
423 .formatMessage("label.settings_for_param", new String[]
425 JMenuItem scr = new JMenuItem(
426 MessageManager.getString("label.sort_by_score"));
428 final FeatureSettings me = this;
429 scr.addActionListener(new ActionListener()
433 public void actionPerformed(ActionEvent e)
436 .sortAlignmentByFeatureScore(Arrays.asList(new String[]
440 JMenuItem dens = new JMenuItem(
441 MessageManager.getString("label.sort_by_density"));
442 dens.addActionListener(new ActionListener()
446 public void actionPerformed(ActionEvent e)
449 .sortAlignmentByFeatureDensity(Arrays.asList(new String[]
456 * variable colour options include colour by label, by score,
457 * by selected attribute text, or attribute value
459 final JCheckBoxMenuItem variableColourCB = new JCheckBoxMenuItem(
460 MessageManager.getString("label.variable_colour"));
461 variableColourCB.setSelected(!featureColour.isSimpleColour());
462 men.add(variableColourCB);
465 * checkbox action listener doubles up as listener to OK
466 * from the variable colour / filters dialog
468 variableColourCB.addActionListener(new ActionListener()
471 public void actionPerformed(ActionEvent e)
473 if (e.getSource() == variableColourCB)
475 men.setVisible(true); // BH 2018 for JavaScript because this is a checkbox
476 men.setVisible(false); // BH 2018 for JavaScript because this is a checkbox
477 if (featureColour.isSimpleColour())
480 * toggle simple colour to variable colour - show dialog
482 FeatureTypeSettings fc = new FeatureTypeSettings(me.fr, type);
483 fc.addActionListener(this);
488 * toggle variable to simple colour - show colour chooser
490 String title = MessageManager.formatMessage("label.select_colour_for", type);
491 ColourChooserListener listener = new ColourChooserListener()
494 public void colourSelected(Color c)
496 table.setValueAt(new FeatureColour(c), rowSelected,
499 me.updateFeatureRenderer(
500 ((FeatureTableModel) table.getModel()).getData(),
504 JalviewColourChooser.showColourChooser(me, title, featureColour.getMaxColour(), listener);
509 if (e.getSource() instanceof FeatureTypeSettings)
512 * update after OK in feature colour dialog; the updated
513 * colour will have already been set in the FeatureRenderer
515 FeatureColourI fci = fr.getFeatureColours().get(type);
516 table.setValueAt(fci, rowSelected, COLOUR_COLUMN);
517 // BH 2018 setting a table value does not invalidate it.
518 System.out.println("FeatureSettings is valied" + table.isValid());
525 JMenuItem selCols = new JMenuItem(
526 MessageManager.getString("label.select_columns_containing"));
527 selCols.addActionListener(new ActionListener()
530 public void actionPerformed(ActionEvent arg0)
532 fr.ap.alignFrame.avc.markColumnsContainingFeatures(false, false,
536 JMenuItem clearCols = new JMenuItem(MessageManager
537 .getString("label.select_columns_not_containing"));
538 clearCols.addActionListener(new ActionListener()
541 public void actionPerformed(ActionEvent arg0)
543 fr.ap.alignFrame.avc.markColumnsContainingFeatures(true, false,
547 JMenuItem hideCols = new JMenuItem(
548 MessageManager.getString("label.hide_columns_containing"));
549 hideCols.addActionListener(new ActionListener()
552 public void actionPerformed(ActionEvent arg0)
554 fr.ap.alignFrame.hideFeatureColumns(type, true);
557 JMenuItem hideOtherCols = new JMenuItem(
558 MessageManager.getString("label.hide_columns_not_containing"));
559 hideOtherCols.addActionListener(new ActionListener()
562 public void actionPerformed(ActionEvent arg0)
564 fr.ap.alignFrame.hideFeatureColumns(type, false);
570 men.add(hideOtherCols);
571 men.show(table, pt.x, pt.y);
575 synchronized public void discoverAllFeatureData()
577 Set<String> allGroups = new HashSet<>();
578 AlignmentI alignment = af.getViewport().getAlignment();
580 for (int i = 0; i < alignment.getHeight(); i++)
582 SequenceI seq = alignment.getSequenceAt(i);
583 for (String group : seq.getFeatures().getFeatureGroups(true))
585 if (group != null && !allGroups.contains(group))
587 allGroups.add(group);
588 checkGroupState(group);
599 * Synchronise gui group list and check visibility of group
602 * @return true if group is visible
604 private boolean checkGroupState(String group)
606 boolean visible = fr.checkGroupVisibility(group, true);
608 for (int g = 0; g < groupPanel.getComponentCount(); g++)
610 if (((JCheckBox) groupPanel.getComponent(g)).getText().equals(group))
612 ((JCheckBox) groupPanel.getComponent(g)).setSelected(visible);
617 final String grp = group;
618 final JCheckBox check = new JCheckBox(group, visible);
619 check.setFont(new Font("Serif", Font.BOLD, 12));
620 check.setToolTipText(group);
621 check.addItemListener(new ItemListener()
624 public void itemStateChanged(ItemEvent evt)
626 fr.setGroupVisibility(check.getText(), check.isSelected());
627 resetTable(new String[] { grp });
628 af.alignPanel.paintAlignment(true, true);
631 groupPanel.add(check);
635 synchronized void resetTable(String[] groupChanged)
641 resettingTable = true;
642 typeWidth = new Hashtable<>();
643 // TODO: change avWidth calculation to 'per-sequence' average and use long
646 Set<String> displayableTypes = new HashSet<>();
647 Set<String> foundGroups = new HashSet<>();
650 * determine which feature types may be visible depending on
651 * which groups are selected, and recompute average width data
653 for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
656 SequenceI seq = af.getViewport().getAlignment().getSequenceAt(i);
659 * get the sequence's groups for positional features
660 * and keep track of which groups are visible
662 Set<String> groups = seq.getFeatures().getFeatureGroups(true);
663 Set<String> visibleGroups = new HashSet<>();
664 for (String group : groups)
666 if (group == null || checkGroupState(group))
668 visibleGroups.add(group);
671 foundGroups.addAll(groups);
674 * get distinct feature types for visible groups
675 * record distinct visible types, and their count and total length
677 Set<String> types = seq.getFeatures().getFeatureTypesForGroups(true,
678 visibleGroups.toArray(new String[visibleGroups.size()]));
679 for (String type : types)
681 displayableTypes.add(type);
682 float[] avWidth = typeWidth.get(type);
685 avWidth = new float[2];
686 typeWidth.put(type, avWidth);
688 // todo this could include features with a non-visible group
689 // - do we greatly care?
690 // todo should we include non-displayable features here, and only
691 // update when features are added?
692 avWidth[0] += seq.getFeatures().getFeatureCount(true, type);
693 avWidth[1] += seq.getFeatures().getTotalFeatureLength(type);
697 Object[][] data = new Object[displayableTypes.size()][COLUMN_COUNT];
700 if (fr.hasRenderOrder())
704 fr.findAllFeatures(groupChanged != null); // prod to update
705 // colourschemes. but don't
707 // First add the checks in the previous render order,
708 // in case the window has been closed and reopened
710 List<String> frl = fr.getRenderOrder();
711 for (int ro = frl.size() - 1; ro > -1; ro--)
713 String type = frl.get(ro);
715 if (!displayableTypes.contains(type))
720 data[dataIndex][TYPE_COLUMN] = type;
721 data[dataIndex][COLOUR_COLUMN] = fr.getFeatureStyle(type);
722 FeatureMatcherSetI featureFilter = fr.getFeatureFilter(type);
723 data[dataIndex][FILTER_COLUMN] = featureFilter == null
724 ? new FeatureMatcherSet()
726 data[dataIndex][SHOW_COLUMN] = new Boolean(
727 af.getViewport().getFeaturesDisplayed().isVisible(type));
729 displayableTypes.remove(type);
734 * process any extra features belonging only to
735 * a group which was just selected
737 while (!displayableTypes.isEmpty())
739 String type = displayableTypes.iterator().next();
740 data[dataIndex][TYPE_COLUMN] = type;
742 data[dataIndex][COLOUR_COLUMN] = fr.getFeatureStyle(type);
743 if (data[dataIndex][COLOUR_COLUMN] == null)
745 // "Colour has been updated in another view!!"
746 fr.clearRenderOrder();
749 FeatureMatcherSetI featureFilter = fr.getFeatureFilter(type);
750 data[dataIndex][FILTER_COLUMN] = featureFilter == null
751 ? new FeatureMatcherSet()
753 data[dataIndex][SHOW_COLUMN] = new Boolean(true);
755 displayableTypes.remove(type);
758 if (originalData == null)
760 originalData = new Object[data.length][COLUMN_COUNT];
761 for (int i = 0; i < data.length; i++)
763 System.arraycopy(data[i], 0, originalData[i], 0, COLUMN_COUNT);
768 updateOriginalData(data);
771 table.setModel(new FeatureTableModel(data));
772 table.getColumnModel().getColumn(0).setPreferredWidth(200);
774 groupPanel.setLayout(
775 new GridLayout(fr.getFeatureGroupsSize() / 4 + 1, 4));
776 pruneGroups(foundGroups);
777 groupPanel.validate();
779 updateFeatureRenderer(data, groupChanged != null);
780 resettingTable = false;
784 * Updates 'originalData' (used for restore on Cancel) if we detect that changes
785 * have been made outwith this dialog
787 * <li>a new feature type added (and made visible)</li>
788 * <li>a feature colour changed (in the Amend Features dialog)</li>
793 protected void updateOriginalData(Object[][] foundData)
795 // todo LinkedHashMap instead of Object[][] would be nice
797 Object[][] currentData = ((FeatureTableModel) table.getModel())
799 for (Object[] row : foundData)
801 String type = (String) row[TYPE_COLUMN];
802 boolean found = false;
803 for (Object[] current : currentData)
805 if (type.equals(current[TYPE_COLUMN]))
809 * currently dependent on object equality here;
810 * really need an equals method on FeatureColour
812 if (!row[COLOUR_COLUMN].equals(current[COLOUR_COLUMN]))
815 * feature colour has changed externally - update originalData
817 for (Object[] original : originalData)
819 if (type.equals(original[TYPE_COLUMN]))
821 original[COLOUR_COLUMN] = row[COLOUR_COLUMN];
832 * new feature detected - add to original data (on top)
834 Object[][] newData = new Object[originalData.length
836 for (int i = 0; i < originalData.length; i++)
838 System.arraycopy(originalData[i], 0, newData[i + 1], 0,
842 originalData = newData;
848 * Remove from the groups panel any checkboxes for groups that are not in the
849 * foundGroups set. This enables removing a group from the display when the last
850 * feature in that group is deleted.
854 protected void pruneGroups(Set<String> foundGroups)
856 for (int g = 0; g < groupPanel.getComponentCount(); g++)
858 JCheckBox checkbox = (JCheckBox) groupPanel.getComponent(g);
859 if (!foundGroups.contains(checkbox.getText()))
861 groupPanel.remove(checkbox);
867 * reorder data based on the featureRenderers global priority list.
871 private void ensureOrder(Object[][] data)
873 boolean sort = false;
874 float[] order = new float[data.length];
875 for (int i = 0; i < order.length; i++)
877 order[i] = fr.getOrder(data[i][0].toString());
880 order[i] = fr.setOrder(data[i][0].toString(), i / order.length);
884 sort = sort || order[i - 1] > order[i];
889 jalview.util.QuickSort.sort(order, data);
894 * Offers a file chooser dialog, and then loads the feature colours and
895 * filters from file in XML format and unmarshals to Jalview feature settings
899 JalviewFileChooser chooser = new JalviewFileChooser("fc",
900 SEQUENCE_FEATURE_COLOURS);
901 chooser.setFileView(new JalviewFileView());
902 chooser.setDialogTitle(
903 MessageManager.getString("label.load_feature_colours"));
904 chooser.setToolTipText(MessageManager.getString("action.load"));
905 chooser.addResponse(0, new RunResponse(JalviewFileChooser.APPROVE_OPTION)
910 File file = chooser.getSelectedFile();
914 chooser.showOpenDialog(this);
918 * Loads feature colours and filters from XML stored in the given file
926 InputStreamReader in = new InputStreamReader(
927 new FileInputStream(file), "UTF-8");
929 JAXBContext jc = JAXBContext
930 .newInstance("jalview.xml.binding.jalview");
931 javax.xml.bind.Unmarshaller um = jc.createUnmarshaller();
932 XMLStreamReader streamReader = XMLInputFactory.newInstance()
933 .createXMLStreamReader(in);
934 JAXBElement<JalviewUserColours> jbe = um.unmarshal(streamReader,
935 JalviewUserColours.class);
936 JalviewUserColours jucs = jbe.getValue();
938 // JalviewUserColours jucs = JalviewUserColours.unmarshal(in);
941 * load feature colours
943 for (int i = jucs.getColour().size() - 1; i >= 0; i--)
945 Colour newcol = jucs.getColour().get(i);
946 FeatureColourI colour = jalview.project.Jalview2XML
947 .parseColour(newcol);
948 fr.setColour(newcol.getName(), colour);
949 fr.setOrder(newcol.getName(), i / (float) jucs.getColour().size());
953 * load feature filters; loaded filters will replace any that are
954 * currently defined, other defined filters are left unchanged
956 for (int i = 0; i < jucs.getFilter().size(); i++)
958 Filter filterModel = jucs.getFilter().get(i);
959 String featureType = filterModel.getFeatureType();
960 FeatureMatcherSetI filter = jalview.project.Jalview2XML
961 .parseFilter(featureType, filterModel.getMatcherSet());
962 if (!filter.isEmpty())
964 fr.setFeatureFilter(featureType, filter);
969 * update feature settings table
974 Object[][] data = ((FeatureTableModel) table.getModel())
977 updateFeatureRenderer(data, false);
980 } catch (Exception ex)
982 System.out.println("Error loading User Colour File\n" + ex);
987 * Offers a file chooser dialog, and then saves the current feature colours
988 * and any filters to the selected file in XML format
992 JalviewFileChooser chooser = new JalviewFileChooser("fc",
993 SEQUENCE_FEATURE_COLOURS);
994 chooser.setFileView(new JalviewFileView());
995 chooser.setDialogTitle(
996 MessageManager.getString("label.save_feature_colours"));
997 chooser.setToolTipText(MessageManager.getString("action.save"));
998 int option = chooser.showSaveDialog(this);
999 if (option == JalviewFileChooser.APPROVE_OPTION)
1001 File file = chooser.getSelectedFile();
1007 * Saves feature colours and filters to the given file
1011 void save(File file)
1013 JalviewUserColours ucs = new JalviewUserColours();
1014 ucs.setSchemeName("Sequence Features");
1017 PrintWriter out = new PrintWriter(new OutputStreamWriter(
1018 new FileOutputStream(file), "UTF-8"));
1021 * sort feature types by colour order, from 0 (highest)
1024 Set<String> fr_colours = fr.getAllFeatureColours();
1025 String[] sortedTypes = fr_colours
1026 .toArray(new String[fr_colours.size()]);
1027 Arrays.sort(sortedTypes, new Comparator<String>()
1030 public int compare(String type1, String type2)
1032 return Float.compare(fr.getOrder(type1), fr.getOrder(type2));
1037 * save feature colours
1039 for (String featureType : sortedTypes)
1041 FeatureColourI fcol = fr.getFeatureStyle(featureType);
1042 Colour col = jalview.project.Jalview2XML.marshalColour(featureType,
1044 ucs.getColour().add(col);
1048 * save any feature filters
1050 for (String featureType : sortedTypes)
1052 FeatureMatcherSetI filter = fr.getFeatureFilter(featureType);
1053 if (filter != null && !filter.isEmpty())
1055 Iterator<FeatureMatcherI> iterator = filter.getMatchers().iterator();
1056 FeatureMatcherI firstMatcher = iterator.next();
1057 jalview.xml.binding.jalview.FeatureMatcherSet ms = jalview.project.Jalview2XML
1058 .marshalFilter(firstMatcher, iterator,
1060 Filter filterModel = new Filter();
1061 filterModel.setFeatureType(featureType);
1062 filterModel.setMatcherSet(ms);
1063 ucs.getFilter().add(filterModel);
1066 JAXBContext jaxbContext = JAXBContext
1067 .newInstance(JalviewUserColours.class);
1068 Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
1069 jaxbMarshaller.marshal(
1070 new ObjectFactory().createJalviewUserColours(ucs), out);
1072 // jaxbMarshaller.marshal(object, pout);
1073 // marshaller.marshal(object);
1076 // ucs.marshal(out);
1078 } catch (Exception ex)
1080 ex.printStackTrace();
1084 public void invertSelection()
1086 Object[][] data = ((FeatureTableModel) table.getModel()).getData();
1087 for (int i = 0; i < data.length; i++)
1089 data[i][SHOW_COLUMN] = !(Boolean) data[i][SHOW_COLUMN];
1091 updateFeatureRenderer(data, true);
1095 public void orderByAvWidth()
1097 if (table == null || table.getModel() == null)
1101 Object[][] data = ((FeatureTableModel) table.getModel()).getData();
1102 float[] width = new float[data.length];
1106 for (int i = 0; i < data.length; i++)
1108 awidth = typeWidth.get(data[i][TYPE_COLUMN]);
1111 width[i] = awidth[1] / awidth[0];// *awidth[0]*awidth[2]; - better
1112 // weight - but have to make per
1113 // sequence, too (awidth[2])
1114 // if (width[i]==1) // hack to distinguish single width sequences.
1125 boolean sort = false;
1126 for (int i = 0; i < width.length; i++)
1128 // awidth = (float[]) typeWidth.get(data[i][0]);
1131 width[i] = fr.getOrder(data[i][TYPE_COLUMN].toString());
1134 width[i] = fr.setOrder(data[i][TYPE_COLUMN].toString(),
1140 width[i] /= max; // normalize
1141 fr.setOrder(data[i][TYPE_COLUMN].toString(), width[i]); // store for later
1145 sort = sort || width[i - 1] > width[i];
1150 jalview.util.QuickSort.sort(width, data);
1151 // update global priority order
1154 updateFeatureRenderer(data, false);
1159 * Repaints the table using alternative code for Java and J2S
1161 private void repaintTable()
1166 // Here is a needed intervention
1167 // because generally we don't "repaint"
1168 // the table. We re-create the HTML divs
1169 // that is associated with it. A better
1170 // way to do this would be to fire a property change.
1171 @SuppressWarnings("unused")
1172 TableUI ui = table.getUI();
1174 * @j2sNative ui.repaintTable$();
1185 frame.setClosed(true);
1186 } catch (Exception exe)
1192 public void updateFeatureRenderer(Object[][] data)
1194 updateFeatureRenderer(data, true);
1198 * Update the priority order of features; only repaint if this changed the order
1199 * of visible features
1204 void updateFeatureRenderer(Object[][] data, boolean visibleNew)
1206 FeatureSettingsBean[] rowData = getTableAsBeans(data);
1208 if (fr.setFeaturePriority(rowData, visibleNew))
1210 af.alignPanel.paintAlignment(true, true);
1215 * Converts table data into an array of data beans
1217 private FeatureSettingsBean[] getTableAsBeans(Object[][] data)
1219 FeatureSettingsBean[] rowData = new FeatureSettingsBean[data.length];
1220 for (int i = 0; i < data.length; i++)
1222 String type = (String) data[i][TYPE_COLUMN];
1223 FeatureColourI colour = (FeatureColourI) data[i][COLOUR_COLUMN];
1224 FeatureMatcherSetI theFilter = (FeatureMatcherSetI) data[i][FILTER_COLUMN];
1225 Boolean isShown = (Boolean) data[i][SHOW_COLUMN];
1226 rowData[i] = new FeatureSettingsBean(type, colour, theFilter,
1232 private void jbInit() throws Exception
1234 this.setLayout(new BorderLayout());
1236 JPanel settingsPane = new JPanel();
1237 settingsPane.setLayout(new BorderLayout());
1239 JPanel bigPanel = new JPanel();
1240 bigPanel.setLayout(new BorderLayout());
1242 groupPanel = new JPanel();
1243 bigPanel.add(groupPanel, BorderLayout.NORTH);
1245 JButton invert = new JButton(
1246 MessageManager.getString("label.invert_selection"));
1247 invert.setFont(JvSwingUtils.getLabelFont());
1248 invert.addActionListener(new ActionListener()
1251 public void actionPerformed(ActionEvent e)
1257 JButton optimizeOrder = new JButton(
1258 MessageManager.getString("label.optimise_order"));
1259 optimizeOrder.setFont(JvSwingUtils.getLabelFont());
1260 optimizeOrder.addActionListener(new ActionListener()
1263 public void actionPerformed(ActionEvent e)
1269 JButton sortByScore = new JButton(
1270 MessageManager.getString("label.seq_sort_by_score"));
1271 sortByScore.setFont(JvSwingUtils.getLabelFont());
1272 sortByScore.addActionListener(new ActionListener()
1275 public void actionPerformed(ActionEvent e)
1277 af.avc.sortAlignmentByFeatureScore(null);
1280 JButton sortByDens = new JButton(
1281 MessageManager.getString("label.sequence_sort_by_density"));
1282 sortByDens.setFont(JvSwingUtils.getLabelFont());
1283 sortByDens.addActionListener(new ActionListener()
1286 public void actionPerformed(ActionEvent e)
1288 af.avc.sortAlignmentByFeatureDensity(null);
1292 JButton help = new JButton(MessageManager.getString("action.help"));
1293 help.setFont(JvSwingUtils.getLabelFont());
1294 help.addActionListener(new ActionListener()
1297 public void actionPerformed(ActionEvent e)
1301 Help.showHelpWindow(HelpId.SequenceFeatureSettings);
1302 } catch (HelpSetException e1)
1304 e1.printStackTrace();
1308 help.setFont(JvSwingUtils.getLabelFont());
1309 help.setText(MessageManager.getString("action.help"));
1310 help.addActionListener(new ActionListener()
1313 public void actionPerformed(ActionEvent e)
1317 Help.showHelpWindow(HelpId.SequenceFeatureSettings);
1318 } catch (HelpSetException e1)
1320 e1.printStackTrace();
1325 JButton cancel = new JButton(MessageManager.getString("action.cancel"));
1326 cancel.setFont(JvSwingUtils.getLabelFont());
1327 cancel.addActionListener(new ActionListener()
1330 public void actionPerformed(ActionEvent e)
1332 fr.setTransparency(originalTransparency);
1333 fr.setFeatureFilters(originalFilters);
1334 updateFeatureRenderer(originalData);
1339 JButton ok = new JButton(MessageManager.getString("action.ok"));
1340 ok.setFont(JvSwingUtils.getLabelFont());
1341 ok.addActionListener(new ActionListener()
1344 public void actionPerformed(ActionEvent e)
1350 JButton loadColours = new JButton(
1351 MessageManager.getString("label.load_colours"));
1352 loadColours.setFont(JvSwingUtils.getLabelFont());
1353 loadColours.setToolTipText(
1354 MessageManager.getString("label.load_colours_tooltip"));
1355 loadColours.addActionListener(new ActionListener()
1358 public void actionPerformed(ActionEvent e)
1364 JButton saveColours = new JButton(
1365 MessageManager.getString("label.save_colours"));
1366 saveColours.setFont(JvSwingUtils.getLabelFont());
1367 saveColours.setToolTipText(
1368 MessageManager.getString("label.save_colours_tooltip"));
1369 saveColours.addActionListener(new ActionListener()
1372 public void actionPerformed(ActionEvent e)
1377 transparency.addChangeListener(new ChangeListener()
1380 public void stateChanged(ChangeEvent evt)
1382 if (!inConstruction)
1384 fr.setTransparency((100 - transparency.getValue()) / 100f);
1385 af.alignPanel.paintAlignment(true, true);
1390 transparency.setMaximum(70);
1391 transparency.setToolTipText(
1392 MessageManager.getString("label.transparency_tip"));
1394 JPanel transPanel = new JPanel(new GridLayout(1, 2));
1395 bigPanel.add(transPanel, BorderLayout.SOUTH);
1397 JPanel transbuttons = new JPanel(new GridLayout(5, 1));
1398 transbuttons.add(optimizeOrder);
1399 transbuttons.add(invert);
1400 transbuttons.add(sortByScore);
1401 transbuttons.add(sortByDens);
1402 transbuttons.add(help);
1403 transPanel.add(transparency);
1404 transPanel.add(transbuttons);
1406 JPanel buttonPanel = new JPanel();
1407 buttonPanel.add(ok);
1408 buttonPanel.add(cancel);
1409 buttonPanel.add(loadColours);
1410 buttonPanel.add(saveColours);
1411 bigPanel.add(scrollPane, BorderLayout.CENTER);
1412 settingsPane.add(bigPanel, BorderLayout.CENTER);
1413 settingsPane.add(buttonPanel, BorderLayout.SOUTH);
1414 this.add(settingsPane);
1418 * Answers a suitable tooltip to show on the colour cell of the table
1422 * if true include 'click to edit' and similar text
1425 public static String getColorTooltip(FeatureColourI fcol,
1432 if (fcol.isSimpleColour())
1434 return withHint ? BASE_TOOLTIP : null;
1436 String description = fcol.getDescription();
1437 description = description.replaceAll("<", "<");
1438 description = description.replaceAll(">", ">");
1439 StringBuilder tt = new StringBuilder(description);
1442 tt.append("<br>").append(BASE_TOOLTIP).append("</br>");
1444 return JvSwingUtils.wrapTooltip(true, tt.toString());
1447 public static void renderGraduatedColor(JLabel comp, FeatureColourI gcol,
1450 boolean thr = false;
1451 StringBuilder tx = new StringBuilder();
1453 if (gcol.isColourByAttribute())
1455 tx.append(FeatureMatcher
1456 .toAttributeDisplayName(gcol.getAttributeName()));
1458 else if (!gcol.isColourByLabel())
1460 tx.append(MessageManager.getString("label.score"));
1463 if (gcol.isAboveThreshold())
1468 if (gcol.isBelowThreshold())
1473 if (gcol.isColourByLabel())
1479 if (!gcol.isColourByAttribute())
1487 Color newColor = gcol.getMaxColour();
1488 comp.setBackground(newColor);
1489 // System.err.println("Width is " + w / 2);
1490 Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w, h, thr);
1491 comp.setIcon(ficon);
1492 // tt+="RGB value: Max (" + newColor.getRed() + ", "
1493 // + newColor.getGreen() + ", " + newColor.getBlue()
1494 // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
1495 // + ", " + minCol.getBlue() + ")");
1497 comp.setHorizontalAlignment(SwingConstants.CENTER);
1498 comp.setText(tx.toString());
1501 // ///////////////////////////////////////////////////////////////////////
1502 // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
1503 // ///////////////////////////////////////////////////////////////////////
1504 class FeatureTableModel extends AbstractTableModel
1506 private String[] columnNames = {
1507 MessageManager.getString("label.feature_type"),
1508 MessageManager.getString("action.colour"),
1509 MessageManager.getString("label.filter"),
1510 MessageManager.getString("label.show") };
1512 private Object[][] data;
1514 FeatureTableModel(Object[][] data)
1519 public Object[][] getData()
1524 public void setData(Object[][] data)
1530 public int getColumnCount()
1532 return columnNames.length;
1535 public Object[] getRow(int row)
1541 public int getRowCount()
1547 public String getColumnName(int col)
1549 return columnNames[col];
1553 public Object getValueAt(int row, int col)
1555 return data[row][col];
1559 * Answers the class of the object in column c of the first row of the table
1562 public Class<?> getColumnClass(int c)
1564 Object v = getValueAt(0, c);
1565 return v == null ? null : v.getClass();
1569 public boolean isCellEditable(int row, int col)
1571 return col == 0 ? false : true;
1575 public void setValueAt(Object value, int row, int col)
1577 data[row][col] = value;
1578 fireTableCellUpdated(row, col);
1579 updateFeatureRenderer(data);
1584 class ColorRenderer extends JLabel implements TableCellRenderer
1586 Border unselectedBorder = null;
1588 Border selectedBorder = null;
1590 public ColorRenderer()
1592 setOpaque(true); // MUST do this for background to show up.
1593 setHorizontalTextPosition(SwingConstants.CENTER);
1594 setVerticalTextPosition(SwingConstants.CENTER);
1598 public Component getTableCellRendererComponent(JTable tbl, Object color,
1599 boolean isSelected, boolean hasFocus, int row, int column)
1601 FeatureColourI cellColour = (FeatureColourI) color;
1603 setBackground(tbl.getBackground());
1604 if (!cellColour.isSimpleColour())
1606 Rectangle cr = tbl.getCellRect(row, column, false);
1607 FeatureSettings.renderGraduatedColor(this, cellColour,
1608 (int) cr.getWidth(), (int) cr.getHeight());
1614 setBackground(cellColour.getColour());
1618 if (selectedBorder == null)
1620 selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1621 tbl.getSelectionBackground());
1623 setBorder(selectedBorder);
1627 if (unselectedBorder == null)
1629 unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1630 tbl.getBackground());
1632 setBorder(unselectedBorder);
1639 class FilterRenderer extends JLabel implements TableCellRenderer
1641 javax.swing.border.Border unselectedBorder = null;
1643 javax.swing.border.Border selectedBorder = null;
1645 public FilterRenderer()
1647 setOpaque(true); // MUST do this for background to show up.
1648 setHorizontalTextPosition(SwingConstants.CENTER);
1649 setVerticalTextPosition(SwingConstants.CENTER);
1653 public Component getTableCellRendererComponent(JTable tbl,
1654 Object filter, boolean isSelected, boolean hasFocus, int row,
1657 FeatureMatcherSetI theFilter = (FeatureMatcherSetI) filter;
1659 String asText = theFilter.toString();
1660 setBackground(tbl.getBackground());
1661 this.setText(asText);
1666 if (selectedBorder == null)
1668 selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1669 tbl.getSelectionBackground());
1671 setBorder(selectedBorder);
1675 if (unselectedBorder == null)
1677 unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
1678 tbl.getBackground());
1680 setBorder(unselectedBorder);
1688 * update comp using rendering settings from gcol
1693 public static void renderGraduatedColor(JLabel comp, FeatureColourI gcol)
1695 int w = comp.getWidth(), h = comp.getHeight();
1698 w = (int) comp.getPreferredSize().getWidth();
1699 h = (int) comp.getPreferredSize().getHeight();
1706 renderGraduatedColor(comp, gcol, w, h);
1709 class ColorEditor extends AbstractCellEditor
1710 implements TableCellEditor, ActionListener
1714 FeatureColourI currentColor;
1716 FeatureTypeSettings chooser;
1722 protected static final String EDIT = "edit";
1724 int rowSelected = 0;
1726 public ColorEditor(FeatureSettings fs)
1729 // Set up the editor (from the table's point of view),
1730 // which is a button.
1731 // This button brings up the color chooser dialog,
1732 // which is the editor from the user's point of view.
1733 button = new JButton();
1734 button.setActionCommand(EDIT);
1735 button.addActionListener(this);
1736 button.setBorderPainted(false);
1740 * Handles events from the editor button, and from the colour/filters
1741 * dialog's OK button
1744 public void actionPerformed(ActionEvent e)
1746 if (button == e.getSource())
1748 if (currentColor.isSimpleColour())
1751 * simple colour chooser
1753 String ttl = MessageManager.formatMessage("label.select_colour_for", type);
1754 ColourChooserListener listener = new ColourChooserListener()
1757 public void colourSelected(Color c)
1759 currentColor = new FeatureColour(c);
1760 me.table.setValueAt(currentColor, rowSelected, COLOUR_COLUMN);
1761 fireEditingStopped();
1764 public void cancel()
1766 fireEditingStopped();
1769 JalviewColourChooser.showColourChooser(button, ttl, currentColor.getColour(), listener);
1774 * variable colour and filters dialog
1776 chooser = new FeatureTypeSettings(me.fr, type);
1777 if (!Jalview.isJS())
1779 chooser.setRequestFocusEnabled(true);
1780 chooser.requestFocus();
1782 chooser.addActionListener(this);
1783 fireEditingStopped();
1789 * after OK in variable colour dialog, any changes to colour
1790 * (or filters!) are already set in FeatureRenderer, so just
1791 * update table data without triggering updateFeatureRenderer
1793 currentColor = fr.getFeatureColours().get(type);
1794 FeatureMatcherSetI currentFilter = me.fr.getFeatureFilter(type);
1795 if (currentFilter == null)
1797 currentFilter = new FeatureMatcherSet();
1799 Object[] data = ((FeatureTableModel) table.getModel())
1800 .getData()[rowSelected];
1801 data[COLOUR_COLUMN] = currentColor;
1802 data[FILTER_COLUMN] = currentFilter;
1804 fireEditingStopped();
1805 me.table.validate();
1809 // Implement the one CellEditor method that AbstractCellEditor doesn't.
1811 public Object getCellEditorValue()
1813 return currentColor;
1816 // Implement the one method defined by TableCellEditor.
1818 public Component getTableCellEditorComponent(JTable theTable, Object value,
1819 boolean isSelected, int row, int column)
1821 currentColor = (FeatureColourI) value;
1822 this.rowSelected = row;
1823 type = me.table.getValueAt(row, TYPE_COLUMN).toString();
1824 button.setOpaque(true);
1825 button.setBackground(me.getBackground());
1826 if (!currentColor.isSimpleColour())
1828 JLabel btn = new JLabel();
1829 btn.setSize(button.getSize());
1830 FeatureSettings.renderGraduatedColor(btn, currentColor);
1831 button.setBackground(btn.getBackground());
1832 button.setIcon(btn.getIcon());
1833 button.setText(btn.getText());
1838 button.setIcon(null);
1839 button.setBackground(currentColor.getColour());
1846 * The cell editor for the Filter column. It displays the text of any filters
1847 * for the feature type in that row (in full as a tooltip, possible abbreviated
1848 * as display text). On click in the cell, opens the Feature Display Settings
1849 * dialog at the Filters tab.
1851 class FilterEditor extends AbstractCellEditor
1852 implements TableCellEditor, ActionListener
1856 FeatureMatcherSetI currentFilter;
1864 protected static final String EDIT = "edit";
1866 int rowSelected = 0;
1868 public FilterEditor(FeatureSettings me)
1871 button = new JButton();
1872 button.setActionCommand(EDIT);
1873 button.addActionListener(this);
1874 button.setBorderPainted(false);
1878 * Handles events from the editor button
1881 public void actionPerformed(ActionEvent e)
1883 if (button == e.getSource())
1885 FeatureTypeSettings chooser = new FeatureTypeSettings(me.fr, type);
1886 chooser.addActionListener(this);
1887 chooser.setRequestFocusEnabled(true);
1888 chooser.requestFocus();
1889 if (lastLocation != null)
1891 // todo open at its last position on screen
1892 chooser.setBounds(lastLocation.x, lastLocation.y,
1893 chooser.getWidth(), chooser.getHeight());
1896 fireEditingStopped();
1898 else if (e.getSource() instanceof Component)
1902 * after OK in variable colour dialog, any changes to filter
1903 * (or colours!) are already set in FeatureRenderer, so just
1904 * update table data without triggering updateFeatureRenderer
1906 FeatureColourI currentColor = fr.getFeatureColours().get(type);
1907 currentFilter = me.fr.getFeatureFilter(type);
1908 if (currentFilter == null)
1910 currentFilter = new FeatureMatcherSet();
1912 Object[] data = ((FeatureTableModel) table.getModel())
1913 .getData()[rowSelected];
1914 data[COLOUR_COLUMN] = currentColor;
1915 data[FILTER_COLUMN] = currentFilter;
1916 fireEditingStopped();
1917 me.table.validate();
1922 public Object getCellEditorValue()
1924 return currentFilter;
1928 public Component getTableCellEditorComponent(JTable theTable, Object value,
1929 boolean isSelected, int row, int column)
1931 currentFilter = (FeatureMatcherSetI) value;
1932 this.rowSelected = row;
1933 type = me.table.getValueAt(row, TYPE_COLUMN).toString();
1934 button.setOpaque(true);
1935 button.setBackground(me.getBackground());
1936 button.setText(currentFilter.toString());
1937 button.setIcon(null);
1943 class FeatureIcon implements Icon
1945 FeatureColourI gcol;
1949 boolean midspace = false;
1951 int width = 50, height = 20;
1953 int s1, e1; // start and end of midpoint band for thresholded symbol
1955 Color mpcolour = Color.white;
1957 FeatureIcon(FeatureColourI gfc, Color bg, int w, int h, boolean mspace)
1977 public int getIconWidth()
1983 public int getIconHeight()
1989 public void paintIcon(Component c, Graphics g, int x, int y)
1992 if (gcol.isColourByLabel())
1995 g.fillRect(0, 0, width, height);
1996 // need an icon here.
1997 g.setColor(gcol.getMaxColour());
1999 g.setFont(new Font("Verdana", Font.PLAIN, 9));
2001 // g.setFont(g.getFont().deriveFont(
2002 // AffineTransform.getScaleInstance(
2003 // width/g.getFontMetrics().stringWidth("Label"),
2004 // height/g.getFontMetrics().getHeight())));
2006 g.drawString(MessageManager.getString("label.label"), 0, 0);
2011 Color minCol = gcol.getMinColour();
2013 g.fillRect(0, 0, s1, height);
2016 g.setColor(Color.white);
2017 g.fillRect(s1, 0, e1 - s1, height);
2019 g.setColor(gcol.getMaxColour());
2020 // g.fillRect(0, e1, width - e1, height); // BH 2018
2021 g.fillRect(e1, 0, width - e1, height);