00001 package org.gel.mauve.gui.sequence;
00002
00003 import java.awt.BorderLayout;
00004 import java.awt.Dimension;
00005 import java.awt.GridLayout;
00006 import java.awt.event.ActionEvent;
00007 import java.awt.event.ActionListener;
00008 import java.util.Enumeration;
00009 import java.util.HashSet;
00010 import java.util.Hashtable;
00011 import java.util.Iterator;
00012 import java.util.LinkedList;
00013 import java.util.Set;
00014
00015 import javax.swing.BorderFactory;
00016 import javax.swing.JCheckBox;
00017 import javax.swing.JFrame;
00018 import javax.swing.JPanel;
00019 import javax.swing.JScrollPane;
00020 import javax.swing.SwingUtilities;
00021 import javax.swing.border.TitledBorder;
00022
00023 import org.biojava.bio.gui.sequence.FeatureBlockSequenceRenderer;
00024 import org.biojava.bio.gui.sequence.FeatureRenderer;
00025 import org.biojava.bio.gui.sequence.FilteringRenderer;
00026 import org.biojava.bio.gui.sequence.MultiLineRenderer;
00027 import org.biojava.bio.gui.sequence.OverlayRendererWrapper;
00028 import org.biojava.utils.ChangeVetoException;
00029 import org.gel.mauve.BaseViewerModel;
00030 import org.gel.mauve.FilterCacheSpec;
00031 import org.gel.mauve.SeqFeatureData;
00032 import org.gel.mauve.SupportedFormat;
00033 import org.gel.mauve.gui.MySymbolSequenceRenderer;
00034
00041 public class FeatureFilterer extends JFrame implements ActionListener {
00042
00046 protected BaseViewerModel model;
00047
00052 protected LinkedList multis;
00053
00057 protected Hashtable multi_map;
00058
00062 protected Hashtable multi_to_symbol;
00063
00069 protected Hashtable filter_specs;
00070
00074 protected JPanel checks;
00075
00076 protected JScrollPane scroll;
00077 JPanel outer;
00078
00082 protected static final Hashtable FILTERERS = new Hashtable ();
00083
00091 protected FeatureFilterer (BaseViewerModel mod) {
00092 super ("Feature Filterer");
00093 model = mod;
00094 filter_specs = new Hashtable ();
00095 multis = new LinkedList ();
00096 multi_map = new Hashtable ();
00097 multi_to_symbol = new Hashtable ();
00098 initFeatureTypes ();
00099 initGUI ();
00100 FILTERERS.put (mod, this);
00101 }
00102
00106 protected void initGUI () {
00107 Enumeration keys = filter_specs.keys ();
00108 checks = new JPanel (new GridLayout (0, 1));
00109 scroll = new JScrollPane (checks);
00110 scroll.setMaximumSize (new Dimension (220, 500));
00111 while (keys.hasMoreElements ())
00112 addCheckBox ((String) keys.nextElement ());
00113 getContentPane ().setLayout (new BorderLayout (5, 5));
00114 outer = (JPanel) getContentPane ();
00115 outer.add (scroll);
00116 TitledBorder title = BorderFactory
00117 .createTitledBorder ("All checked types will be displayed");
00118 outer.setBorder (BorderFactory.createCompoundBorder (BorderFactory
00119 .createCompoundBorder (BorderFactory.createEmptyBorder (5, 8,
00120 10, 8), title), BorderFactory.createEmptyBorder (5, 5,
00121 5, 5)));
00122 Dimension size = title.getMinimumSize (outer);
00123 outer.setPreferredSize (new Dimension (size.width + 26, outer
00124 .getPreferredSize ().height));
00125
00126 pack ();
00127 }
00128
00129 protected void addCheckBox (final String type) {
00130 SwingUtilities.invokeLater (new Runnable () {
00131 public void run () {
00132 boolean vis = false;
00133 if (isVisible ()) {
00134 vis = true;
00135 setVisible (false);
00136 }
00137 JCheckBox item = new JCheckBox (type, true);
00138 item.addActionListener (FeatureFilterer.this);
00139 checks.add (item);
00140 Dimension size = getSize ();
00141 size.height = Math.min (size.height
00142 + item.getPreferredSize ().height, 500);
00143 setSize (size);
00144 if (vis)
00145 setVisible (true);
00146 }
00147 });
00148 }
00149
00154 protected void initFeatureTypes () {
00155 int count = model.getSequenceCount ();
00156 for (int i = 0; i < count; i++) {
00157 SupportedFormat format = model.getGenomeBySourceIndex (i)
00158 .getAnnotationFormat ();
00159 if(format == null)
00160 continue;
00161 FilterCacheSpec [] specs = format.getFilterCacheSpecs ();
00162 for (int j = 0; j < specs.length; j++) {
00163
00164
00165 if (specs[j].getFeatureRenderer () != null) {
00166 addSpecForType (specs[j]);
00167 }
00168 }
00169 }
00170 }
00171
00172 protected void addSpecForType (FilterCacheSpec spec) {
00173 String type = SeqFeatureData.getTypeFromFilterSpec (spec);
00174 LinkedList vals = (LinkedList) filter_specs.get (type);
00175 if (vals == null) {
00176 vals = new LinkedList ();
00177 filter_specs.put (type, vals);
00178 }
00179 vals.add (new Object [] {spec, null});
00180 }
00181
00191 public void addMultiRenderer (MultiLineRenderer multi,
00192 MySymbolSequenceRenderer my_symbol) {
00193 multis.add (multi);
00194 multi_map.put (multi, new HashSet ());
00195 multi_to_symbol.put (multi, my_symbol);
00196 }
00197
00208 public void addOverlayRenderer (MultiLineRenderer multi,
00209 OverlayRendererWrapper over) {
00210 try {
00211 FeatureRenderer rend = ((FeatureBlockSequenceRenderer) ((FilteringRenderer) over
00212 .getRenderer ()).getRenderer ()).getFeatureRenderer ();
00213 Iterator itty = filter_specs.values ().iterator ();
00214 outer: while (itty.hasNext ()) {
00215 Iterator it = ((LinkedList) itty.next ()).iterator ();
00216 while (it.hasNext ()) {
00217 Object [] val = (Object []) it.next ();
00218 if (((FilterCacheSpec) val[FlatFileFeatureConstants.FILTER_SPEC_INDEX])
00219 .getFeatureRenderer ().equals (rend)) {
00220 if (val[FlatFileFeatureConstants.OVERLAY_REND_INDEX] == null) {
00221 val[FlatFileFeatureConstants.OVERLAY_REND_INDEX] = over;
00222 HashSet set = (HashSet) multi_map.get (multi);
00223 if (set == null)
00224 System.out
00225 .println ("multi not yet added: " + multi);
00226 else
00227 set.add (over);
00228 continue outer;
00229 }
00230 }
00231 }
00232 }
00233 } catch (ClassCastException e) {
00234 e.printStackTrace ();
00235 }
00236 }
00237
00245 public void actionPerformed (ActionEvent e) {
00246 if (e.getSource () instanceof JCheckBox) {
00247 JCheckBox box = (JCheckBox) e.getSource ();
00248 Iterator itty = ((LinkedList) filter_specs
00249 .get (box.getLabel ())).iterator ();
00250 while (itty.hasNext ()) {
00251 Object [] val = (Object []) itty.next ();
00252 OverlayRendererWrapper over = (OverlayRendererWrapper) val[FlatFileFeatureConstants.OVERLAY_REND_INDEX];
00253 System.out.println ("overlay: " + over);
00254 addOrRemove (over, box.isSelected ());
00255 }
00256 if (box.isSelected ()) {
00257 resetMultiRenderers ();
00258 }
00259 } else
00260 setVisible (true);
00261 }
00262
00263 public void addOrRemove (OverlayRendererWrapper over, boolean add) {
00264 Iterator it = multis.iterator ();
00265 while (it.hasNext ()) {
00266 MultiLineRenderer multi = (MultiLineRenderer) it.next ();
00267 System.out.println ("playing with multi: " + multi);
00268 if (((HashSet) multi_map.get (multi)).contains (over)) {
00269 System.out.println ("more than playing");
00270 try {
00271 if (add)
00272 multi.addRenderer (over);
00273 else
00274 multi.removeRenderer (over);
00275 } catch (ChangeVetoException e) {
00276
00277 e.printStackTrace();
00278 }
00279 }
00280 }
00281 }
00282
00283 protected void resetMultiRenderers () {
00284 Iterator itty = multis.iterator ();
00285 while (itty.hasNext ()) {
00286 try {
00287 MultiLineRenderer multi = (MultiLineRenderer) itty.next ();
00288 MySymbolSequenceRenderer rend = (MySymbolSequenceRenderer) multi_to_symbol
00289 .get (multi);
00290 multi.removeRenderer (rend);
00291 multi.addRenderer (rend);
00292 } catch (ChangeVetoException e) {
00293
00294 e.printStackTrace ();
00295 }
00296 }
00297 }
00298
00299 public Set getFeatureTypes () {
00300 return filter_specs.keySet ();
00301 }
00302
00311 public static FeatureFilterer getFilterer (BaseViewerModel mod) {
00312 FeatureFilterer filter = (FeatureFilterer) FILTERERS.get (mod);
00313 if (filter == null)
00314 filter = new FeatureFilterer (mod);
00315 return filter;
00316 }
00317
00325 public static void removeFilterer (BaseViewerModel mod) {
00326 FILTERERS.remove (mod);
00327 }
00328
00329 }