X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fjalview%2Fgui%2FFeatureSettings.java;h=ea492e245bc134a1ca76a15210afe2b3d389ec80;hb=08b496fd543b6cf3b564e470d961bf0807800ef0;hp=5e4f5407f8f734848f0333fbcda12eaf9af84314;hpb=8c0f35fa0bee850e670c157157cc335d8a1a49ae;p=jalview.git diff --git a/src/jalview/gui/FeatureSettings.java b/src/jalview/gui/FeatureSettings.java index 5e4f540..ea492e2 100755 --- a/src/jalview/gui/FeatureSettings.java +++ b/src/jalview/gui/FeatureSettings.java @@ -23,6 +23,9 @@ import java.util.*; import java.awt.*; import java.awt.event.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + import javax.swing.*; import javax.swing.event.*; import javax.swing.table.*; @@ -34,7 +37,7 @@ public class FeatureSettings extends JPanel { DasSourceBrowser dassourceBrowser; - jalview.io.DasSequenceFeatureFetcher dasFeatureFetcher; + jalview.ws.DasSequenceFeatureFetcher dasFeatureFetcher; JPanel settingsPane = new JPanel(); JPanel dasSettingsPane = new JPanel(); @@ -118,29 +121,57 @@ public class FeatureSettings if (af.getViewport().featuresDisplayed == null || fr.renderOrder == null) { - fr.findAllFeatures(); + fr.findAllFeatures(true); // display everything! } setTableData(); + final PropertyChangeListener change; + final FeatureSettings fs=this; + fr.addPropertyChangeListener(change=new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent evt) + { + if (!fs.resettingTable && !fs.handlingUpdate) { + fs.handlingUpdate=true; + fs.resetTable(null); // new groups may be added with new seuqence feature types only + fs.handlingUpdate=false; + } + } + + }); frame = new JInternalFrame(); frame.setContentPane(this); Desktop.addInternalFrame(frame, "Sequence Feature Settings", 400, 450); + frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter() + { + public void internalFrameClosed( + javax.swing.event.InternalFrameEvent evt) + { + fr.removePropertyChangeListener(change); + } + ; + }); frame.setLayer(JLayeredPane.PALETTE_LAYER); } + /** + * true when Feature Settings are updating from feature renderer + */ + private boolean handlingUpdate=false; + /** + * contains a float[3] for each feature type string. created by setTableData + */ + Hashtable typeWidth=null; synchronized public void setTableData() { if (fr.featureGroups == null) { fr.featureGroups = new Hashtable(); } - Vector allFeatures = new Vector(); Vector allGroups = new Vector(); SequenceFeature[] tmpfeatures; String group; - for (int i = 0; i < af.getViewport().alignment.getHeight(); i++) { if (af.getViewport().alignment.getSequenceAt(i).getDatasetSequence(). @@ -167,54 +198,10 @@ public class FeatureSettings if (!allGroups.contains(group)) { allGroups.addElement(group); - - boolean visible = true; - if (fr.featureGroups.containsKey(group)) - { - visible = ( (Boolean) fr.featureGroups.get(group)).booleanValue(); - } - - if (groupPanel == null) - { - groupPanel = new JPanel(); - } - - boolean alreadyAdded = false; - for (int g = 0; g < groupPanel.getComponentCount(); g++) + if (group!=null) { - if ( ( (JCheckBox) groupPanel.getComponent(g)) - .getText().equals(group)) - { - alreadyAdded = true; - break; - } + checkGroupState(group); } - - if (alreadyAdded) - { - continue; - } - - fr.featureGroups.put(group, new Boolean(visible)); - - final JCheckBox check = new JCheckBox(group, visible); - check.setFont(new Font("Serif", Font.BOLD, 12)); - check.addItemListener(new ItemListener() - { - public void itemStateChanged(ItemEvent evt) - { - fr.featureGroups.put(check.getText(), - new Boolean(check.isSelected())); - af.alignPanel.seqPanel.seqCanvas.repaint(); - if (af.alignPanel.overviewPanel != null) - { - af.alignPanel.overviewPanel.updateOverviewImage(); - } - - resetTable(true); - } - }); - groupPanel.add(check); } } @@ -226,19 +213,87 @@ public class FeatureSettings } } - resetTable(false); + resetTable(null); validate(); } + /** + * + * @param group + * @return true if group has been seen before and is already added to set. + */ + private boolean checkGroupState(String group) { + boolean visible; + if (fr.featureGroups.containsKey(group)) + { + visible = ( (Boolean) fr.featureGroups.get(group)).booleanValue(); + } else { + visible=true; // new group is always made visible + } + + if (groupPanel == null) + { + groupPanel = new JPanel(); + } + + boolean alreadyAdded = false; + for (int g = 0; g < groupPanel.getComponentCount(); g++) + { + if ( ( (JCheckBox) groupPanel.getComponent(g)) + .getText().equals(group)) + { + alreadyAdded = true; + ((JCheckBox)groupPanel.getComponent(g)).setSelected(visible); + break; + } + } + + if (alreadyAdded) + { + + return true; + } - void resetTable(boolean groupsChanged) + fr.featureGroups.put(group, new Boolean(visible)); + final String grp = group; + final JCheckBox check = new JCheckBox(group, visible); + check.setFont(new Font("Serif", Font.BOLD, 12)); + check.addItemListener(new ItemListener() + { + public void itemStateChanged(ItemEvent evt) + { + fr.featureGroups.put(check.getText(), + new Boolean(check.isSelected())); + af.alignPanel.seqPanel.seqCanvas.repaint(); + if (af.alignPanel.overviewPanel != null) + { + af.alignPanel.overviewPanel.updateOverviewImage(); + } + + resetTable(new String[] { grp } ); + } + }); + groupPanel.add(check); + return false; + } + boolean resettingTable=false; + synchronized void resetTable(String[] groupChanged) { + if (resettingTable==true) + { + return; + } + resettingTable=true; + typeWidth=new Hashtable(); + // TODO: change avWidth calculation to 'per-sequence' average and use long rather than float + float[] avWidth=null; SequenceFeature[] tmpfeatures; String group = null, type; Vector visibleChecks = new Vector(); //Find out which features should be visible depending on which groups //are selected / deselected + //and recompute average width ordering for (int i = 0; i < af.getViewport().alignment.getHeight(); i++) { @@ -263,12 +318,26 @@ public class FeatureSettings if (group == null || fr.featureGroups.get(group) == null || ( (Boolean) fr.featureGroups.get(group)).booleanValue()) { + if (group!=null) + checkGroupState(group); type = tmpfeatures[index].getType(); if (!visibleChecks.contains(type)) { visibleChecks.addElement(type); } } + if (!typeWidth.containsKey(tmpfeatures[index].getType())) { + typeWidth.put(tmpfeatures[index].getType(), avWidth=new float[3]); + } else { + avWidth = (float[]) typeWidth.get(tmpfeatures[index].getType()); + } + avWidth[0]++; + if (tmpfeatures[index].getBegin()>tmpfeatures[index].getEnd()) + { + avWidth[1]+=1+tmpfeatures[index].getBegin()-tmpfeatures[index].getEnd(); + } else { + avWidth[1]+=1+tmpfeatures[index].getEnd()-tmpfeatures[index].getBegin(); + } index++; } } @@ -279,6 +348,8 @@ public class FeatureSettings if (fr.renderOrder != null) { + if (!handlingUpdate) + fr.findAllFeatures(groupChanged!=null); // prod to update colourschemes. but don't affect display //First add the checks in the previous render order, //in case the window has been closed and reopened for (int ro = fr.renderOrder.length - 1; ro > -1; ro--) @@ -292,8 +363,7 @@ public class FeatureSettings data[dataIndex][0] = type; data[dataIndex][1] = fr.getColour(type); - data[dataIndex][2] = new Boolean(af.getViewport().featuresDisplayed. - containsKey(type)); + data[dataIndex][2] = new Boolean(af.getViewport().featuresDisplayed.containsKey(type)); dataIndex++; visibleChecks.removeElement(type); } @@ -337,8 +407,27 @@ public class FeatureSettings bigPanel.add(groupPanel, BorderLayout.NORTH); } - updateFeatureRenderer(data); - + updateFeatureRenderer(data, groupChanged!=null); + resettingTable=false; + } + /** + * reorder data based on the featureRenderers global priority list. + * @param data + */ + private void ensureOrder(Object[][] data) + { + boolean sort=false; + float[] order = new float[data.length]; + for (int i=0;i1) + sort = sort || order[i-1]>order[i]; + } + if (sort) + jalview.util.QuickSort.sort(order, data); } void load() @@ -368,15 +457,21 @@ public class FeatureSettings JalviewUserColours(); jucs = (jalview.binding.JalviewUserColours) jucs.unmarshal(in); - for (int i = 0; i < jucs.getColourCount(); i++) + for (int i = jucs.getColourCount()-1; i >=0; i--) { - fr.setColour(jucs.getColour(i).getName(), + String name; + fr.setColour(name=jucs.getColour(i).getName(), new Color(Integer.parseInt(jucs.getColour(i).getRGB(), 16))); + fr.setOrder(name,(i==0) ? 0 : i/jucs.getColourCount()); + } + if (table!=null) { + resetTable(null); + Object[][] data=((FeatureTableModel) table.getModel()).getData(); + ensureOrder(data); + updateFeatureRenderer(data,false); + table.repaint(); } - - setTableData(); - af.alignPanel.paintAlignment(true); } catch (Exception ex) { @@ -411,15 +506,24 @@ public class FeatureSettings new FileOutputStream(choice), "UTF-8")); Enumeration e = fr.featureColours.keys(); + float[] sortOrder = new float[fr.featureColours.size()]; + String[] sortTypes = new String[fr.featureColours.size()]; + int i=0; while (e.hasMoreElements()) { + sortTypes[i] = e.nextElement().toString(); + sortOrder[i] = fr.getOrder(sortTypes[i]); + i++; + } + jalview.util.QuickSort.sort(sortOrder, sortTypes); + sortOrder=null; + for (i=0; i0) { + width[i] = awidth[1]/awidth[0];// *awidth[0]*awidth[2]; - better weight - but have to make per sequence, too (awidth[2]) + //if (width[i]==1) // hack to distinguish single width sequences. + num++; + } else { + width[i]=0; + } + if (max0) + sort = sort || width[i-1]>width[i]; + } + if (sort) + jalview.util.QuickSort.sort(width, data); + // update global priority order + updateFeatureRenderer(data,false); + table.repaint(); + } public void close() { try @@ -455,13 +602,12 @@ public class FeatureSettings public void updateFeatureRenderer(Object[][] data) { - fr.setFeaturePriority(data); + updateFeatureRenderer(data, true); + } + private void updateFeatureRenderer(Object[][] data, boolean visibleNew) + { + fr.setFeaturePriority(data, visibleNew); af.alignPanel.paintAlignment(true); - - if (af.alignPanel.overviewPanel != null) - { - af.alignPanel.overviewPanel.updateOverviewImage(); - } } int selectedRow = -1; @@ -481,6 +627,8 @@ public class FeatureSettings JButton fetchDAS = new JButton(); JButton saveDAS = new JButton(); JButton cancelDAS = new JButton(); + JButton optimizeOrder = new JButton(); + JPanel transbuttons = new JPanel(new BorderLayout()); private void jbInit() throws Exception { @@ -497,6 +645,13 @@ public class FeatureSettings invertSelection(); } }); + optimizeOrder.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11)); + optimizeOrder.setText("Optimise Order"); + optimizeOrder.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + orderByAvWidth(); + } + }); cancel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11)); cancel.setText("Cancel"); cancel.addActionListener(new ActionListener() @@ -576,7 +731,9 @@ public class FeatureSettings tabbedPane.addTab("DAS Settings", dasSettingsPane); bigPanel.add(transPanel, java.awt.BorderLayout.SOUTH); transPanel.add(transparency); - transPanel.add(invert); + transbuttons.add(invert, java.awt.BorderLayout.NORTH); + transbuttons.add(optimizeOrder,java.awt.BorderLayout.SOUTH); + transPanel.add(transbuttons); buttonPanel.add(ok); buttonPanel.add(cancel); buttonPanel.add(loadColours); @@ -595,23 +752,32 @@ public class FeatureSettings fetchDAS.setEnabled(false); cancelDAS.setEnabled(true); Vector selectedSources = dassourceBrowser.getSelectedSources(); - + doDasFeatureFetch(selectedSources, true, true); + } + /** + * get the features from selectedSources for all or the current selection + * @param selectedSources + * @param checkDbRefs + * @param promptFetchDbRefs + */ + private void doDasFeatureFetch(Vector selectedSources, boolean checkDbRefs, boolean promptFetchDbRefs) + { SequenceI[] dataset, seqs; int iSize; - - if (af.getViewport().getSelectionGroup() != null - && af.getViewport().getSelectionGroup().getSize() > 0) + AlignViewport vp = af.getViewport(); + if (vp.getSelectionGroup() != null + && vp.getSelectionGroup().getSize() > 0) { - iSize = af.getViewport().getSelectionGroup().getSize(); + iSize = vp.getSelectionGroup().getSize(); dataset = new SequenceI[iSize]; - seqs = af.getViewport().getSelectionGroup(). + seqs = vp.getSelectionGroup(). getSequencesInOrder( - af.getViewport().getAlignment()); + vp.getAlignment()); } else { - iSize = af.getViewport().getAlignment().getHeight(); - seqs = af.getViewport().getAlignment().getSequencesArray(); + iSize = vp.getAlignment().getHeight(); + seqs = vp.getAlignment().getSequencesArray(); } dataset = new SequenceI[iSize]; @@ -620,15 +786,64 @@ public class FeatureSettings dataset[i] = seqs[i].getDatasetSequence(); } + cancelDAS.setEnabled(true); dasFeatureFetcher = - new jalview.io.DasSequenceFeatureFetcher( + new jalview.ws.DasSequenceFeatureFetcher( dataset, this, - selectedSources); - cancelDAS.setEnabled(true); + selectedSources, checkDbRefs, promptFetchDbRefs); af.getViewport().setShowSequenceFeatures(true); af.showSeqFeatures.setSelected(true); } + /** + * properly initialise DAS fetcher and then initiate a new thread to fetch features from the named sources (rather than any turned on by default) + * @param sources + */ + public void fetchDasFeatures(Vector sources) + { + Thread thr = new Thread(new Runnable() { + public void run() { + // this actually initialises the das source list + dassourceBrowser.paintComponent(null); // yuk + } + }); + thr.start(); + while (dassourceBrowser.loadingDasSources || dassourceBrowser.dasSources==null) + { + try { Thread.sleep(10); } catch (Exception e) {}; + } + Vector resolved = new Vector(); + if (sources!=null) + { + for (int i=0;i0) + { + final Vector dassources = resolved; + SwingUtilities.invokeLater(new Runnable() { + + public void run() + { + fetchDAS.setEnabled(false); + cancelDAS.setEnabled(true); + doDasFeatureFetch(dassources, true, false); + + }}); + } + } public void saveDAS_actionPerformed(ActionEvent e) { @@ -643,10 +858,24 @@ public class FeatureSettings public void cancelDAS_actionPerformed(ActionEvent e) { - dasFeatureFetcher.cancel(); + if (dasFeatureFetcher!=null) + { + dasFeatureFetcher.cancel(); + } fetchDAS.setEnabled(true); cancelDAS.setEnabled(false); } + public void noDasSourceActive() + { + complete(); + JOptionPane.showInternalConfirmDialog(Desktop.desktop, + "No das sources were selected.\n" + + "Please select some sources and\n" + +" try again.", + "No Sources Selected", + JOptionPane.DEFAULT_OPTION, + JOptionPane.INFORMATION_MESSAGE); + } ///////////////////////////////////////////////////////////////////////// // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html