merge commit
authorCharles Ofoegbu <tcnofoegbu@dundee.ac.uk>
Tue, 25 Nov 2014 17:49:58 +0000 (17:49 +0000)
committerCharles Ofoegbu <tcnofoegbu@dundee.ac.uk>
Tue, 25 Nov 2014 17:49:58 +0000 (17:49 +0000)
44 files changed:
.classpath
build.xml
help/html/features/chimera.html
help/html/features/preferences.html
help/html/webServices/JABAWS.html
resources/lang/Messages.properties
resources/lang/Messages_es.properties
src/jalview/appletgui/APopupMenu.java
src/jalview/appletgui/AlignFrame.java
src/jalview/appletgui/RedundancyPanel.java
src/jalview/appletgui/SeqPanel.java
src/jalview/bin/Cache.java
src/jalview/bin/Jalview.java
src/jalview/bin/JalviewLite.java
src/jalview/commands/EditCommand.java
src/jalview/commands/RemoveGapColCommand.java
src/jalview/commands/RemoveGapsCommand.java
src/jalview/commands/SlideSequencesCommand.java
src/jalview/commands/TrimRegionCommand.java
src/jalview/datamodel/ColumnSelection.java
src/jalview/datamodel/HiddenSequences.java
src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AlignViewport.java
src/jalview/gui/ChimeraViewFrame.java
src/jalview/gui/Desktop.java
src/jalview/gui/FeatureSettings.java
src/jalview/gui/Help.java
src/jalview/gui/PopupMenu.java
src/jalview/gui/Preferences.java
src/jalview/gui/RedundancyPanel.java
src/jalview/gui/SVGOptions.java [new file with mode: 0644]
src/jalview/gui/SeqPanel.java
src/jalview/gui/WsJobParameters.java
src/jalview/gui/WsPreferences.java
src/jalview/jbgui/GPreferences.java
src/jalview/util/ImageMaker.java
src/jalview/viewmodel/AlignmentViewport.java
src/jalview/ws/jws2/JabaWsServerQuery.java
src/jalview/ws/jws2/Jws2Discoverer.java
src/jalview/ws/jws2/MsaWSClient.java
test/jalview/commands/EditCommandTest.java [new file with mode: 0644]
test/jalview/gui/HelpTest.java [new file with mode: 0644]
test/jalview/ws/jabaws/JalviewJabawsTestUtils.java

index 26cfdb0..69a49b0 100644 (file)
        <classpathentry kind="lib" path="lib/log4j-to-slf4j-2.0-rc2.jar"/>
        <classpathentry kind="lib" path="lib/slf4j-log4j12-1.7.7.jar"/>
        <classpathentry kind="lib" path="lib/VARNAv3-91.jar"/>
+
        <classpathentry kind="lib" path="lib/jfreesvg-2.1.jar"/>
        <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/plugin.jar"/>
        <classpathentry kind="lib" path="lib/xml-apis.jar"/>
-       <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/plugin17"/>
        <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
        <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
        <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Plugin.jar"/>
+       <classpathentry kind="lib" path="lib/jfreesvg-2.1.jar"/>
        <classpathentry kind="output" path="classes"/>
 </classpath>
index 19b41e5..d8ebe1e 100755 (executable)
--- a/build.xml
+++ b/build.xml
         <include name="*.jar"/>
       </fileset> -->
       </path>
+       
     <!-- Jalview Version String displayed by application on startup and used to check for updates -->
     <property name="JALVIEW_VERSION" value="DEVELOPMENT" />
+       
+    <property name="INSTALLATION" value="Source" />
+       
     <!-- 2.4 (VAMSAS)" -->
     <!-- Include debugging information in javac true or false -->
     <property name="javac.debug" value="true" />
     <properties file="${outputDir}/.build_properties">
       <header>
           ---Jalview Build Details---
-        </header>
+        </header>      
       <property name="VERSION" value="${JALVIEW_VERSION}" />
+      <property name="INSTALLATION" value="${INSTALLATION}" />
       <property name="BUILD_DATE" value="${build.date}" />
     </properties>
   </target>
index e866597..236701a 100644 (file)
@@ -133,6 +133,8 @@ atoms in the displayed structures. For comprehensive details of Chimera's comman
                they are insertions (relative to the associated sequence in the
                alignment) and grey if they are N or C terminal flanks outside the
                region mapped to the alignment window's sequence.</em></li>
+               <li><strong>By Chain<br>
+               </strong><em>Uses the Chimera 'rainbow chain' command to apply a different colour to each chain.</em></li>
                <li><strong>Charge &amp; Cysteine<br>
                </strong><em> Highlights cysteines in yellow, anionic (Aspartic Acid or
                Glutamic Acid) residues in red, and cationic (Lysine or Arginine)
index 5d4ab4d..657359e 100755 (executable)
@@ -121,7 +121,8 @@ called to derive secondary structure information for RNA chains.
 column for the backbone atoms in the PDB file will be extracted as annotation lines shown on the alignment. 
 <p><em>Default structure viewer</em> - choose JMOL or CHIMERA for viewing 3D structures. 
 <p><em>Path to Chimera program</em> - Optional, as Jalview will search standard installation paths for Windows, Linux or MacOS. 
-If you have installed Chimera in a non-standard location, you can specify it here. Enter the full path to the Chimera executable program.  
+If you have installed Chimera in a non-standard location, you can specify it here, by entering the full path to the Chimera executable program.
+Double-click this field to open a file chooser dialog.  
 
 <p><a name="connections"><strong>&quot;Connections&quot;
 Preferences tab</strong></a></p>
index a27a0d5..8c964b4 100644 (file)
@@ -60,5 +60,7 @@ Your JABAWS servers list is stored in your Jalview preferences, so you
 will only have to configure Jalview once for each new server.</p>
 <p><em>Support for accessing JABAWS servers was introduced in
 Jalview 2.6.</em></p>
+<p><em>Option for adding JABAWS servers which fails validation 
+was introduced from version 2.8.2 </em></p>
 </body>
 </html>
index 511e5e9..cabee76 100644 (file)
@@ -107,7 +107,7 @@ action.change_params = Change Parameters
 action.apply = Apply
 action.apply_threshold_all_groups = Apply threshold to all groups
 action.apply_all_groups = Apply to all Groups
-action.by_chain = By chain
+action.by_chain = By Chain
 action.by_sequence = By Sequence
 action.paste_annotations = Paste Annotations
 action.format = Format
@@ -249,8 +249,8 @@ label.autoadd_secstr = Add secondary structure annotation to alignment
 label.autoadd_temp = Add Temperature Factor annotation to alignment
 label.structure_viewer = Default structure viewer
 label.chimera_path = Path to Chimera program
-label.chimera_path_tip = Jalview will try standard locations, plus any path entered here.
-label.invalid_path = File not found or not executable
+label.chimera_path_tip = Jalview will first try any path entered here, else standard installation locations.<br>Double-click to browse for file.
+label.invalid_chimera_path = Chimera path not found or not executable
 label.min_colour = Minimum Colour
 label.max_colour = Maximum Colour
 label.use_original_colours = Use Original Colours
@@ -344,7 +344,7 @@ label.dont_ask_me_again = Don't ask me again
 label.select_eps_character_rendering_style = Select EPS character rendering style
 label.invert_selection = Invert Selection
 label.optimise_order = Optimise Order
-label.seq_sort_by_score = Seq sort by Score
+label.seq_sort_by_score = Sequence sort by Score
 label.load_colours = Load Colours
 label.save_colours = Save Colours
 label.fetch_das_features = Fetch DAS Features
@@ -778,7 +778,9 @@ label.services_at = Services at {0}
 label.rest_client_submit = {0} using {1}
 label.fetch_retrieve_from =Retrieve from {0}</html>
 label.fetch_retrieve_from_all_sources = Retrieve from all {0} sources in {1}<br>First is :{2}<html> 
-label.feature_settings_click_drag = <html>Click/drag feature types up or down to change render order.<br/>Double click to select columns containing feature in alignment/current selection<br/>Pressing Alt will select columns outside features rather than inside<br/>Pressing Shift to modify current selection (rather than clear current selection)<br/>Press CTRL or Command/Meta to toggle columns in/outside features<br/></html>
+#label.feature_settings_click_drag = <html>Click/drag feature types up or down to change render order.<br/>Double click to select columns containing feature in alignment/current selection<br/>Pressing Alt will select columns outside features rather than inside<br/>Pressing Shift to modify current selection (rather than clear current selection)<br/>Press CTRL or Command/Meta to toggle columns in/outside features<br/></html>
+label.feature_settings_click_drag = Drag up or down to change render order.<br/>Double click to select columns containing feature.
+label.transparency_tip = Adjust transparency to 'see through' feature colours.
 label.opt_and_params_further_details = see further details by right-clicking
 label.opt_and_params_show_brief_desc_image_link = <html>Click to show brief description<br><img src="{0}"/> Right click for further information.</html> 
 label.opt_and_params_show_brief_desc = <html>Click to show brief description<br></html>
index a1663d9..dc403d0 100644 (file)
@@ -748,7 +748,7 @@ label.services_at = Servicios en {0}
 label.rest_client_submit = {0} utilizando {1}
 label.fetch_retrieve_from =Recuperar de {0}
 label.fetch_retrieve_from_all_sources = Recuperar de todas las fuentes {0} en {1}<br>La primera es :{2}
-label.feature_settings_click_drag = Haga clic o arrastre los tipos de las características hacia arriba o hacia abajo para cambiar el orden de visualización.<br/>Haga doble clic para seleccionar las columnas que contienen las características del alineamiento/selección actual.<br/>Presionando Alt seleccionará las columnas exteriores a las características en lugar de las interiores<br/>Presione Shift para modificar la selección actual (en lugar de borrarla)<br/>Presione CTRL o Command/Meta para cambiar las columans externas o internas a las características<br/>
+label.feature_settings_click_drag = Haga clic o arrastre los tipos de las características hacia arriba o hacia abajo para cambiar el orden de visualización.<br/>Haga doble clic para seleccionar las columnas que contienen las características del alineamiento/selección actual.<br/>
 label.opt_and_params_further_details = ver los detalles adicionales haciendo clic en el botón derecho
 label.opt_and_params_show_brief_desc_image_link = Haga clic para ver una descripción breve<br><img src="{0}"/>Haga clic en el botón derecho para obtener información adicional.
 label.opt_and_params_show_brief_desc = Haga clic para ver una descripción breve<br>
index eba1200..98a4a1c 100644 (file)
  */
 package jalview.appletgui;
 
-import java.util.*;
-
-import java.awt.*;
-import java.awt.event.*;
-
-import jalview.analysis.*;
-import jalview.commands.*;
-import jalview.datamodel.*;
-import jalview.schemes.*;
-import jalview.util.MessageManager;
-import jalview.util.UrlLink;
+import jalview.analysis.AAFrequency;
+import jalview.analysis.Conservation;
+import jalview.commands.ChangeCaseCommand;
+import jalview.commands.EditCommand;
+import jalview.commands.EditCommand.Action;
+import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.PDBEntry;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
 import jalview.io.AppletFormatAdapter;
 import jalview.io.SequenceAnnotationReport;
+import jalview.schemes.Blosum62ColourScheme;
+import jalview.schemes.BuriedColourScheme;
+import jalview.schemes.ClustalxColourScheme;
+import jalview.schemes.HelixColourScheme;
+import jalview.schemes.HydrophobicColourScheme;
+import jalview.schemes.NucleotideColourScheme;
+import jalview.schemes.PIDColourScheme;
+import jalview.schemes.ResidueProperties;
+import jalview.schemes.StrandColourScheme;
+import jalview.schemes.TaylorColourScheme;
+import jalview.schemes.TurnColourScheme;
+import jalview.schemes.ZappoColourScheme;
+import jalview.util.MessageManager;
+import jalview.util.UrlLink;
+
+import java.awt.CheckboxMenuItem;
+import java.awt.Frame;
+import java.awt.Menu;
+import java.awt.MenuItem;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.util.Vector;
 
 public class APopupMenu extends java.awt.PopupMenu implements
         ActionListener, ItemListener
@@ -549,7 +573,9 @@ public class APopupMenu extends java.awt.PopupMenu implements
       if (sg != null)
       {
         if (seq == null)
+        {
           seq = (Sequence) sg.getSequenceAt(0);
+        }
 
         EditNameDialog dialog = new EditNameDialog(seq.getSequenceAsString(
                 sg.getStartRes(), sg.getEndRes() + 1), null,
@@ -560,7 +586,7 @@ public class APopupMenu extends java.awt.PopupMenu implements
         if (dialog.accept)
         {
           EditCommand editCommand = new EditCommand(MessageManager.getString("label.edit_sequences"),
-                  EditCommand.REPLACE, dialog.getName().replace(' ',
+                  Action.REPLACE, dialog.getName().replace(' ',
                           ap.av.getGapCharacter()),
                   sg.getSequencesAsArray(ap.av.getHiddenRepSequences()),
                   sg.getStartRes(), sg.getEndRes() + 1,
@@ -742,11 +768,15 @@ public class APopupMenu extends java.awt.PopupMenu implements
       PDBEntry entry = (PDBEntry) seq.getPDBId().firstElement();
 
       if (ap.av.applet.jmolAvailable)
+      {
         new jalview.appletgui.AppletJmol(entry, new Sequence[]
         { seq }, null, ap, AppletFormatAdapter.URL);
+      }
       else
+      {
         new MCview.AppletPDBViewer(entry, new Sequence[]
         { seq }, null, ap, AppletFormatAdapter.URL);
+      }
 
     }
     else
index 34ec2cf..ed64215 100644 (file)
@@ -27,6 +27,7 @@ import jalview.api.SequenceStructureBinding;
 import jalview.bin.JalviewLite;
 import jalview.commands.CommandI;
 import jalview.commands.EditCommand;
+import jalview.commands.EditCommand.Action;
 import jalview.commands.OrderCommand;
 import jalview.commands.RemoveGapColCommand;
 import jalview.commands.RemoveGapsCommand;
@@ -1833,7 +1834,8 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     }
 
     // !newAlignment
-    addHistoryItem(new EditCommand(MessageManager.getString("label.add_sequences"), EditCommand.PASTE,
+    addHistoryItem(new EditCommand(
+            MessageManager.getString("label.add_sequences"), Action.PASTE,
             seqs, 0, viewport.getAlignment().getWidth(),
             viewport.getAlignment()));
 
@@ -1883,8 +1885,9 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     /*
      * //ADD HISTORY ITEM
      */
-    addHistoryItem(new EditCommand(MessageManager.getString("label.cut_sequences"), EditCommand.CUT, cut,
-            sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,
+    addHistoryItem(new EditCommand(
+            MessageManager.getString("label.cut_sequences"), Action.CUT,
+            cut, sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,
             viewport.getAlignment()));
 
     viewport.setSelectionGroup(null);
index 1547862..8e364f0 100644 (file)
  */
 package jalview.appletgui;
 
-import java.util.*;
-import java.util.List;
-import java.awt.*;
-import java.awt.event.*;
-
 import jalview.analysis.AlignSeq;
-import jalview.commands.*;
-import jalview.datamodel.*;
+import jalview.commands.CommandI;
+import jalview.commands.EditCommand;
+import jalview.commands.EditCommand.Action;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
 import jalview.util.MessageManager;
 
+import java.awt.Frame;
+import java.awt.event.ActionEvent;
+import java.awt.event.AdjustmentEvent;
+import java.awt.event.AdjustmentListener;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+import java.util.Vector;
+
 public class RedundancyPanel extends SliderPanel implements Runnable,
         WindowListener
 {
@@ -197,7 +207,7 @@ public class RedundancyPanel extends SliderPanel implements Runnable,
       }
 
       EditCommand cut = new EditCommand(MessageManager.getString("action.remove_redundancy"),
-              EditCommand.CUT, deleted, 0, width, ap.av.getAlignment());
+              Action.CUT, deleted, 0, width, ap.av.getAlignment());
       AlignmentI alignment = ap.av.getAlignment();
       for (int i = 0; i < del.size(); i++)
       {
index de4d979..592fd4f 100644 (file)
  */
 package jalview.appletgui;
 
-import java.util.*;
-
-import java.awt.*;
-import java.awt.event.*;
-
-import jalview.commands.*;
-import jalview.datamodel.*;
-import jalview.schemes.*;
+import jalview.commands.EditCommand;
+import jalview.commands.EditCommand.Action;
+import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.SearchResults;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.schemes.ResidueProperties;
 import jalview.structure.SelectionSource;
 import jalview.structure.SequenceListener;
 import jalview.structure.StructureSelectionManager;
 import jalview.util.MessageManager;
 
+import java.awt.BorderLayout;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Panel;
+import java.awt.Point;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.util.Vector;
+
 public class SeqPanel extends Panel implements MouseMotionListener,
         MouseListener, SequenceListener
 {
@@ -147,7 +159,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
   void setCursorPosition()
   {
-    SequenceI sequence = (Sequence) av.getAlignment().getSequenceAt(
+    SequenceI sequence = av.getAlignment().getSequenceAt(
             seqCanvas.cursorY);
 
     seqCanvas.cursorX = sequence.findIndex(getKeyboardNo1()) - 1;
@@ -240,7 +252,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
   void setSelectionAreaAtCursor(boolean topLeft)
   {
-    SequenceI sequence = (Sequence) av.getAlignment().getSequenceAt(
+    SequenceI sequence = av.getAlignment().getSequenceAt(
             seqCanvas.cursorY);
 
     if (av.getSelectionGroup() != null)
@@ -648,7 +660,9 @@ public class SeqPanel extends Panel implements MouseMotionListener,
   {
     String tmp = sequence.hashCode() + index + "";
     if (lastMessage == null || !lastMessage.equals(tmp))
+    {
       ssm.mouseOverSequence(sequence, index, pos, av);
+    }
 
     lastMessage = tmp;
   }
@@ -698,7 +712,9 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
     int respos = sequence.findPosition(res);
     if (ssm != null)
+    {
       mouseOverSequence(sequence, res, respos);
+    }
 
     StringBuffer text = new StringBuffer("Sequence " + (seq + 1) + " ID: "
             + sequence.getName());
@@ -813,7 +829,9 @@ public class SeqPanel extends Panel implements MouseMotionListener,
                         .containsKey(features[i].featureGroup)
                 && !((Boolean) seqCanvas.fr.featureGroups
                         .get(features[i].featureGroup)).booleanValue())
+        {
           continue;
+        }
 
         if ((features[i].getBegin() <= res)
                 && (features[i].getEnd() >= res))
@@ -938,7 +956,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     {
       if (av.isHiddenRepSequence(seq))
       {
-        sg = (SequenceGroup) av.getRepresentedSequences(seq);
+        sg = av.getRepresentedSequences(seq);
         groupEditing = true;
       }
     }
@@ -1164,7 +1182,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
         }
         else
         {
-          editCommand.appendEdit(EditCommand.INSERT_GAP, groupSeqs,
+          editCommand.appendEdit(Action.INSERT_GAP, groupSeqs,
                   startres, startres - lastres, av.getAlignment(), true);
         }
       }
@@ -1180,7 +1198,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
         }
         else
         {
-          editCommand.appendEdit(EditCommand.DELETE_GAP, groupSeqs,
+          editCommand.appendEdit(Action.DELETE_GAP, groupSeqs,
                   startres, lastres - startres, av.getAlignment(), true);
         }
 
@@ -1202,7 +1220,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
         }
         else
         {
-          editCommand.appendEdit(EditCommand.INSERT_GAP, new SequenceI[]
+          editCommand.appendEdit(Action.INSERT_GAP, new SequenceI[]
           { seq }, lastres, startres - lastres, av.getAlignment(), true);
         }
       }
@@ -1237,7 +1255,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
 
           if (max > 0)
           {
-            editCommand.appendEdit(EditCommand.DELETE_GAP, new SequenceI[]
+            editCommand.appendEdit(Action.DELETE_GAP, new SequenceI[]
             { seq }, startres, max, av.getAlignment(), true);
           }
         }
@@ -1273,10 +1291,10 @@ public class SeqPanel extends Panel implements MouseMotionListener,
       }
     }
 
-    editCommand.appendEdit(EditCommand.DELETE_GAP, seq, blankColumn, 1,
+    editCommand.appendEdit(Action.DELETE_GAP, seq, blankColumn, 1,
             av.getAlignment(), true);
 
-    editCommand.appendEdit(EditCommand.INSERT_GAP, seq, j, 1,
+    editCommand.appendEdit(Action.INSERT_GAP, seq, j, 1,
             av.getAlignment(), true);
 
   }
@@ -1284,10 +1302,10 @@ public class SeqPanel extends Panel implements MouseMotionListener,
   void deleteChar(int j, SequenceI[] seq, int fixedColumn)
   {
 
-    editCommand.appendEdit(EditCommand.DELETE_GAP, seq, j, 1,
+    editCommand.appendEdit(Action.DELETE_GAP, seq, j, 1,
             av.getAlignment(), true);
 
-    editCommand.appendEdit(EditCommand.INSERT_GAP, seq, fixedColumn, 1,
+    editCommand.appendEdit(Action.INSERT_GAP, seq, fixedColumn, 1,
             av.getAlignment(), true);
   }
 
@@ -1312,7 +1330,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
       return;
     }
 
-    SequenceI sequence = (Sequence) av.getAlignment().getSequenceAt(seq);
+    SequenceI sequence = av.getAlignment().getSequenceAt(seq);
 
     if (sequence == null || res > sequence.getLength())
     {
index 24ed1b4..3b0a23e 100755 (executable)
@@ -150,6 +150,7 @@ import org.apache.log4j.SimpleLayout;
  * <li>FOLLOW_SELECTIONS (true) Controls whether a new alignment view should
  * respond to selections made in other alignments containing the same sequences.
  * </li>
+ * <li>JWS2HOSTURLS comma-separated list of URLs to try for JABAWS services</li>
  * <li>SHOW_WSDISCOVERY_ERRORS (true) Controls if the web service URL discovery
  * warning dialog box is displayed.</li>
  * <li>ANNOTATIONCOLOUR_MIN (orange) Shade used for minimum value of annotation
index 184c267..f80f341 100755 (executable)
@@ -24,6 +24,7 @@ import jalview.gui.AlignFrame;
 import jalview.gui.Desktop;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
+import jalview.ws.jws2.Jws2Discoverer;
 
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
@@ -34,6 +35,7 @@ import java.io.IOException;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.lang.reflect.Constructor;
+import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URL;
 import java.net.URLDecoder;
@@ -106,40 +108,7 @@ public class Jalview
 
     if (aparser.contains("help") || aparser.contains("h"))
     {
-      System.out
-              .println("Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n"
-                      + "-nodisplay\tRun Jalview without User Interface.\n"
-                      + "-props FILE\tUse the given Jalview properties file instead of users default.\n"
-                      + "-colour COLOURSCHEME\tThe colourscheme to be applied to the alignment\n"
-                      + "-annotations FILE\tAdd precalculated annotations to the alignment.\n"
-                      + "-tree FILE\tLoad the given newick format tree file onto the alignment\n"
-                      + "-features FILE\tUse the given file to mark features on the alignment.\n"
-                      + "-fasta FILE\tCreate alignment file FILE in Fasta format.\n"
-                      + "-clustal FILE\tCreate alignment file FILE in Clustal format.\n"
-                      + "-pfam FILE\tCreate alignment file FILE in PFAM format.\n"
-                      + "-msf FILE\tCreate alignment file FILE in MSF format.\n"
-                      + "-pileup FILE\tCreate alignment file FILE in Pileup format\n"
-                      + "-pir FILE\tCreate alignment file FILE in PIR format.\n"
-                      + "-blc FILE\tCreate alignment file FILE in BLC format.\n"
-                      + "-jalview FILE\tCreate alignment file FILE in Jalview format.\n"
-                      + "-png FILE\tCreate PNG image FILE from alignment.\n"
-                      + "-imgMap FILE\tCreate HTML file FILE with image map of PNG image.\n"
-                      + "-eps FILE\tCreate EPS file FILE from alignment.\n"
-                      + "-questionnaire URL\tQueries the given URL for information about any Jalview user questionnaires.\n"
-                      + "-noquestionnaire\tTurn off questionnaire check.\n"
-                      + "-nousagestats\tTurn off google analytics tracking for this session.\n"
-                      + "-sortbytree OR -nosortbytree\tEnable or disable sorting of the given alignment by the given tree\n"
-                      // +
-                      // "-setprop PROPERTY=VALUE\tSet the given Jalview property, after all other properties files have been read\n\t (quote the 'PROPERTY=VALUE' pair to ensure spaces are passed in correctly)"
-                      + "-dasserver nickname=URL\tAdd and enable a das server with given nickname\n\t\t\t(alphanumeric or underscores only) for retrieval of features for all alignments.\n"
-                      + "\t\t\tSources that also support the sequence command may be specified by prepending the URL with sequence:\n"
-                      + "\t\t\t e.g. sequence:http://localdas.somewhere.org/das/source)\n"
-                      + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
-                      // +
-                      // "-vdoc vamsas-document\tImport vamsas document into new session or join existing session with same URN\n"
-                      // + "-vses vamsas-session\tJoin session with given URN\n"
-                      + "-groovy FILE\tExecute groovy script in FILE, after all other arguments have been processed (if FILE is the text 'STDIN' then the file will be read from STDIN)\n"
-                      + "\n~Read documentation in Application or visit http://www.jalview.org for description of Features and Annotations file~\n\n");
+      showUsage();
       System.exit(0);
     }
     if (aparser.contains("nodisplay") || aparser.contains("nogui")
@@ -150,6 +119,20 @@ public class Jalview
     }
     Cache.loadProperties(aparser.getValue("props")); // must do this before
     // anything else!
+
+    final String jabawsUrl = aparser.getValue("jabaws");
+    if (jabawsUrl != null)
+    {
+      try
+      {
+        Jws2Discoverer.getDiscoverer().setPreferredUrl(jabawsUrl);
+      } catch (MalformedURLException e)
+      {
+        System.err.println("Invalid jabaws parameter: " + jabawsUrl
+                + " ignored");
+      }
+    }
+
     String defs = aparser.getValue("setprop");
     while (defs != null)
     {
@@ -619,6 +602,45 @@ public class Jalview
     }
   }
 
+  private static void showUsage()
+  {
+    System.out
+            .println("Usage: jalview -open [FILE] [OUTPUT_FORMAT] [OUTPUT_FILE]\n\n"
+                    + "-nodisplay\tRun Jalview without User Interface.\n"
+                    + "-props FILE\tUse the given Jalview properties file instead of users default.\n"
+                    + "-colour COLOURSCHEME\tThe colourscheme to be applied to the alignment\n"
+                    + "-annotations FILE\tAdd precalculated annotations to the alignment.\n"
+                    + "-tree FILE\tLoad the given newick format tree file onto the alignment\n"
+                    + "-features FILE\tUse the given file to mark features on the alignment.\n"
+                    + "-fasta FILE\tCreate alignment file FILE in Fasta format.\n"
+                    + "-clustal FILE\tCreate alignment file FILE in Clustal format.\n"
+                    + "-pfam FILE\tCreate alignment file FILE in PFAM format.\n"
+                    + "-msf FILE\tCreate alignment file FILE in MSF format.\n"
+                    + "-pileup FILE\tCreate alignment file FILE in Pileup format\n"
+                    + "-pir FILE\tCreate alignment file FILE in PIR format.\n"
+                    + "-blc FILE\tCreate alignment file FILE in BLC format.\n"
+                    + "-jalview FILE\tCreate alignment file FILE in Jalview format.\n"
+                    + "-png FILE\tCreate PNG image FILE from alignment.\n"
+                    + "-imgMap FILE\tCreate HTML file FILE with image map of PNG image.\n"
+                    + "-eps FILE\tCreate EPS file FILE from alignment.\n"
+                    + "-questionnaire URL\tQueries the given URL for information about any Jalview user questionnaires.\n"
+                    + "-noquestionnaire\tTurn off questionnaire check.\n"
+                    + "-nousagestats\tTurn off google analytics tracking for this session.\n"
+                    + "-sortbytree OR -nosortbytree\tEnable or disable sorting of the given alignment by the given tree\n"
+                    // +
+                    // "-setprop PROPERTY=VALUE\tSet the given Jalview property, after all other properties files have been read\n\t (quote the 'PROPERTY=VALUE' pair to ensure spaces are passed in correctly)"
+                    + "-jabaws URL\tSpecify URL for Jabaws services (e.g. for a local installation).\n"
+                    + "-dasserver nickname=URL\tAdd and enable a das server with given nickname\n\t\t\t(alphanumeric or underscores only) for retrieval of features for all alignments.\n"
+                    + "\t\t\tSources that also support the sequence command may be specified by prepending the URL with sequence:\n"
+                    + "\t\t\t e.g. sequence:http://localdas.somewhere.org/das/source)\n"
+                    + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
+                    // +
+                    // "-vdoc vamsas-document\tImport vamsas document into new session or join existing session with same URN\n"
+                    // + "-vses vamsas-session\tJoin session with given URN\n"
+                    + "-groovy FILE\tExecute groovy script in FILE, after all other arguments have been processed (if FILE is the text 'STDIN' then the file will be read from STDIN)\n"
+                    + "\n~Read documentation in Application or visit http://www.jalview.org for description of Features and Annotations file~\n\n");
+  }
+
   private static void startUsageStats(final Desktop desktop)
   {
     /**
index 0abd31b..ae8bc98 100644 (file)
@@ -1269,7 +1269,7 @@ public class JalviewLite extends Applet implements
 
   public static boolean debug = false;
 
-  static String builddate = null, version = null;
+  static String builddate = null, version = null, installation = null;
 
   private static void initBuildDetails()
   {
@@ -1277,6 +1277,7 @@ public class JalviewLite extends Applet implements
     {
       builddate = "unknown";
       version = "test";
+      installation = "Webstart";
       java.net.URL url = JalviewLite.class
               .getResource("/.build_properties");
       if (url != null)
@@ -1296,6 +1297,10 @@ public class JalviewLite extends Applet implements
             {
               builddate = line.substring(line.indexOf("=") + 1);
             }
+            if (line.indexOf("INSTALLATION") > -1)
+            {
+              installation = line.substring(line.indexOf("=") + 1);
+            }
           }
         } catch (Exception ex)
         {
@@ -1311,6 +1316,12 @@ public class JalviewLite extends Applet implements
     return builddate;
   }
 
+  public static String getInstallation()
+  {
+    initBuildDetails();
+    return installation;
+  }
+
   public static String getVersion()
   {
     initBuildDetails();
@@ -1360,6 +1371,7 @@ public class JalviewLite extends Applet implements
 
       System.err.println("JalviewLite Version " + getVersion());
       System.err.println("Build Date : " + getBuildDate());
+      System.err.println("Installation : " + getInstallation());
 
     }
     String externalsviewer = getParameter("externalstructureviewer");
index 5c698a8..82de3b2 100644 (file)
@@ -27,8 +27,10 @@ import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 
+import java.util.ArrayList;
 import java.util.Hashtable;
 import java.util.List;
+import java.util.ListIterator;
 
 /**
  * 
@@ -54,19 +56,12 @@ import java.util.List;
  */
 public class EditCommand implements CommandI
 {
-  public static final int INSERT_GAP = 0;
-
-  public static final int DELETE_GAP = 1;
-
-  public static final int CUT = 2;
-
-  public static final int PASTE = 3;
-
-  public static final int REPLACE = 4;
-
-  public static final int INSERT_NUC = 5;
+  public enum Action
+  {
+    INSERT_GAP, DELETE_GAP, CUT, PASTE, REPLACE, INSERT_NUC
+  };
 
-  Edit[] edits;
+  private List<Edit> edits = new ArrayList<Edit>();
 
   String description;
 
@@ -79,32 +74,75 @@ public class EditCommand implements CommandI
     this.description = description;
   }
 
-  public EditCommand(String description, int command, SequenceI[] seqs,
+  public EditCommand(String description, Action command, SequenceI[] seqs,
           int position, int number, AlignmentI al)
   {
     this.description = description;
-    if (command == CUT || command == PASTE)
+    if (command == Action.CUT || command == Action.PASTE)
     {
-      edits = new Edit[]
-      { new Edit(command, seqs, position, number, al) };
+      setEdit(new Edit(command, seqs, position, number, al));
     }
 
     performEdit(0, null);
   }
 
-  public EditCommand(String description, int command, String replace,
+  public EditCommand(String description, Action command, String replace,
           SequenceI[] seqs, int position, int number, AlignmentI al)
   {
     this.description = description;
-    if (command == REPLACE)
+    if (command == Action.REPLACE)
     {
-      edits = new Edit[]
-      { new Edit(command, seqs, position, number, al, replace) };
+      setEdit(new Edit(command, seqs, position, number, al, replace));
     }
 
     performEdit(0, null);
   }
 
+  /**
+   * Set the list of edits to the specified item (only).
+   * 
+   * @param e
+   */
+  protected void setEdit(Edit e)
+  {
+    edits.clear();
+    edits.add(e);
+  }
+
+  /**
+   * Add the given edit command to the stored list of commands.
+   * 
+   * @param e
+   */
+  protected void addEdit(Edit e)
+  {
+    edits.add(e);
+  }
+
+  /**
+   * Clear the list of stored edit commands.
+   * 
+   */
+  protected void clearEdits()
+  {
+    edits.clear();
+  }
+
+  /**
+   * Returns the i'th stored Edit command.
+   * 
+   * @param i
+   * @return
+   */
+  protected Edit getEdit(int i)
+  {
+    if (i >= 0 && i < edits.size())
+    {
+      return edits.get(i);
+    }
+    return null;
+  }
+
   @Override
   final public String getDescription()
   {
@@ -114,12 +152,17 @@ public class EditCommand implements CommandI
   @Override
   public int getSize()
   {
-    return edits == null ? 0 : edits.length;
+    return edits.size();
   }
 
+  /**
+   * Return the alignment for the first edit (or null if no edit).
+   * 
+   * @return
+   */
   final public AlignmentI getAlignment()
   {
-    return edits[0].al;
+    return (edits.isEmpty() ? null : edits.get(0).al);
   }
 
   /**
@@ -135,7 +178,8 @@ public class EditCommand implements CommandI
    * @param al
    * @param performEdit
    */
-  final public void appendEdit(int command, SequenceI[] seqs, int position,
+  final public void appendEdit(Action command, SequenceI[] seqs,
+          int position,
           int number, AlignmentI al, boolean performEdit)
   {
     appendEdit(command, seqs, position, number, al, performEdit, null);
@@ -153,7 +197,8 @@ public class EditCommand implements CommandI
    * @param performEdit
    * @param views
    */
-  final public void appendEdit(int command, SequenceI[] seqs, int position,
+  final public void appendEdit(Action command, SequenceI[] seqs,
+          int position,
           int number, AlignmentI al, boolean performEdit, AlignmentI[] views)
   {
     Edit edit = new Edit(command, seqs, position, number,
@@ -164,52 +209,62 @@ public class EditCommand implements CommandI
       edit.fullAlignmentHeight = true;
     }
 
-    if (edits != null)
-    {
-      Edit[] temp = new Edit[edits.length + 1];
-      System.arraycopy(edits, 0, temp, 0, edits.length);
-      edits = temp;
-      edits[edits.length - 1] = edit;
-    }
-    else
-    {
-      edits = new Edit[]
-      { edit };
-    }
+    edits.add(edit);
 
     if (performEdit)
     {
-      performEdit(edits.length - 1, views);
+      performEdit(edit, views);
     }
   }
 
+  /**
+   * Execute all the edit commands, starting at the given commandIndex
+   * 
+   * @param commandIndex
+   * @param views
+   */
   final void performEdit(int commandIndex, AlignmentI[] views)
   {
-    int eSize = edits.length;
-    for (int e = commandIndex; e < eSize; e++)
+    ListIterator<Edit> iterator = edits.listIterator(commandIndex);
+    while (iterator.hasNext())
     {
-      switch (edits[e].command)
-      {
-      case INSERT_GAP:
-        insertGap(edits[e]);
-        break;
-      case DELETE_GAP:
-        deleteGap(edits[e]);
-        break;
-      case CUT:
-        cut(edits[e], views);
-        break;
-      case PASTE:
-        paste(edits[e], views);
-        break;
-      case REPLACE:
-        replace(edits[e]);
-        break;
+      Edit edit = iterator.next();
+      performEdit(edit, views);
+    }
+  }
+
+  /**
+   * Execute one edit command in all the specified alignment views
+   * 
+   * @param edit
+   * @param views
+   */
+  protected void performEdit(Edit edit, AlignmentI[] views)
+  {
+    switch (edit.command)
+    {
+    case INSERT_GAP:
+      insertGap(edit);
+      break;
+    case DELETE_GAP:
+      deleteGap(edit);
+      break;
+    case CUT:
+      cut(edit, views);
+      break;
+    case PASTE:
+      paste(edit, views);
+      break;
+    case REPLACE:
+      replace(edit);
+      break;
+    case INSERT_NUC:
       // TODO:add deleteNuc for UNDO
       // case INSERT_NUC:
       // insertNuc(edits[e]);
-      // break;
-      }
+      break;
+    default:
+      break;
     }
   }
 
@@ -219,32 +274,49 @@ public class EditCommand implements CommandI
     performEdit(0, views);
   }
 
+  /**
+   * Undo the stored list of commands, in reverse order.
+   */
   @Override
   final public void undoCommand(AlignmentI[] views)
   { 
-    for(Edit e : edits){
-       switch (e.command)
-        {
-        case INSERT_GAP:
-          deleteGap(e);
-          break;
-        case DELETE_GAP:
-          insertGap(e);
-          break;
-        case CUT:
-          paste(e, views);
-          break;
-        case PASTE:
-          cut(e, views);
-          break;
-        case REPLACE:
-          replace(e);
-          break;
-        }
+    ListIterator<Edit> iterator = edits.listIterator(edits.size());
+    while (iterator.hasPrevious())
+    {
+      Edit e = iterator.previous();
+      switch (e.command)
+      {
+      case INSERT_GAP:
+        deleteGap(e);
+        break;
+      case DELETE_GAP:
+        insertGap(e);
+        break;
+      case CUT:
+        paste(e, views);
+        break;
+      case PASTE:
+        cut(e, views);
+        break;
+      case REPLACE:
+        replace(e);
+        break;
+      case INSERT_NUC:
+        // not implemented
+        break;
+      default:
+        break;
+      }
     }
   }
 
-  final void insertGap(Edit command)
+  /**
+   * Insert gap(s) in sequences as specified by the command, and adjust
+   * annotations.
+   * 
+   * @param command
+   */
+  final private void insertGap(Edit command)
   {
 
     for (int s = 0; s < command.seqs.length; s++)
@@ -270,7 +342,13 @@ public class EditCommand implements CommandI
   // adjustAnnotations(command, true, false, null);
   // }
 
-  final void deleteGap(Edit command)
+  /**
+   * Delete gap(s) in sequences as specified by the command, and adjust
+   * annotations.
+   * 
+   * @param command
+   */
+  final private void deleteGap(Edit command)
   {
     for (int s = 0; s < command.seqs.length; s++)
     {
@@ -281,6 +359,13 @@ public class EditCommand implements CommandI
     adjustAnnotations(command, false, false, null);
   }
 
+  /**
+   * Carry out a Cut action. The cut characters are saved in case Undo is
+   * requested.
+   * 
+   * @param command
+   * @param views
+   */
   void cut(Edit command, AlignmentI[] views)
   {
     boolean seqDeleted = false;
@@ -288,29 +373,30 @@ public class EditCommand implements CommandI
 
     for (int i = 0; i < command.seqs.length; i++)
     {
-      if (command.seqs[i].getLength() > command.position)
+      final SequenceI sequence = command.seqs[i];
+      if (sequence.getLength() > command.position)
       {
-        command.string[i] = command.seqs[i].getSequence(command.position,
+        command.string[i] = sequence.getSequence(command.position,
                 command.position + command.number);
-        SequenceI oldds = command.seqs[i].getDatasetSequence();
+        SequenceI oldds = sequence.getDatasetSequence();
         if (command.oldds != null && command.oldds[i] != null)
         {
           // we are redoing an undone cut.
-          command.seqs[i].setDatasetSequence(null);
+          sequence.setDatasetSequence(null);
         }
-        command.seqs[i].deleteChars(command.position, command.position
+        sequence.deleteChars(command.position, command.position
                 + command.number);
         if (command.oldds != null && command.oldds[i] != null)
         {
           // oldds entry contains the cut dataset sequence.
-          command.seqs[i].setDatasetSequence(command.oldds[i]);
+          sequence.setDatasetSequence(command.oldds[i]);
           command.oldds[i] = oldds;
         }
         else
         {
           // modify the oldds if necessary
-          if (oldds != command.seqs[i].getDatasetSequence()
-                  || command.seqs[i].getSequenceFeatures() != null)
+          if (oldds != sequence.getDatasetSequence()
+                  || sequence.getSequenceFeatures() != null)
           {
             if (command.oldds == null)
             {
@@ -320,16 +406,16 @@ public class EditCommand implements CommandI
             adjustFeatures(
                     command,
                     i,
-                    command.seqs[i].findPosition(command.position),
-                    command.seqs[i].findPosition(command.position
+                    sequence.findPosition(command.position),
+                    sequence.findPosition(command.position
                             + command.number), false);
           }
         }
       }
 
-      if (command.seqs[i].getLength() < 1)
+      if (sequence.getLength() < 1)
       {
-        command.al.deleteSequence(command.seqs[i]);
+        command.al.deleteSequence(sequence);
         seqDeleted = true;
       }
     }
@@ -337,6 +423,13 @@ public class EditCommand implements CommandI
     adjustAnnotations(command, false, seqDeleted, views);
   }
 
+  /**
+   * Perform the given Paste command. This may be to add cut or copied sequences
+   * to an alignment, or to undo a 'Cut' action on a region of the alignment.
+   * 
+   * @param command
+   * @param views
+   */
   void paste(Edit command, AlignmentI[] views)
   {
     StringBuffer tmp;
@@ -540,7 +633,7 @@ public class EditCommand implements CommandI
     if (modifyVisibility && !insert)
     {
       // only occurs if a sequence was added or deleted.
-      command.deletedAnnotationRows = new Hashtable();
+      command.deletedAnnotationRows = new Hashtable<SequenceI, AlignmentAnnotation[]>();
     }
     if (command.fullAlignmentHeight)
     {
@@ -624,7 +717,7 @@ public class EditCommand implements CommandI
                     && command.deletedAnnotationRows
                             .containsKey(command.seqs[s]))
             {
-              AlignmentAnnotation[] revealed = (AlignmentAnnotation[]) command.deletedAnnotationRows
+              AlignmentAnnotation[] revealed = command.deletedAnnotationRows
                       .get(command.seqs[s]);
               command.seqs[s].setAlignmentAnnotation(revealed);
               if (revealed != null)
@@ -695,7 +788,7 @@ public class EditCommand implements CommandI
 
     if (!insert)
     {
-      command.deletedAnnotations = new Hashtable();
+      command.deletedAnnotations = new Hashtable<String, Annotation[]>();
     }
 
     int aSize;
@@ -758,7 +851,7 @@ public class EditCommand implements CommandI
                   && command.deletedAnnotations
                           .containsKey(annotations[a].annotationId))
           {
-            Annotation[] restore = (Annotation[]) command.deletedAnnotations
+            Annotation[] restore = command.deletedAnnotations
                     .get(annotations[a].annotationId);
 
             System.arraycopy(restore, 0, temp, command.position,
@@ -776,7 +869,7 @@ public class EditCommand implements CommandI
                   && command.deletedAnnotations
                           .containsKey(annotations[a].annotationId))
           {
-            Annotation[] restore = (Annotation[]) command.deletedAnnotations
+            Annotation[] restore = command.deletedAnnotations
                     .get(annotations[a].annotationId);
 
             temp = new Annotation[annotations[a].annotations.length
@@ -871,7 +964,7 @@ public class EditCommand implements CommandI
       if (command.editedFeatures != null
               && command.editedFeatures.containsKey(seq))
       {
-        sequence.setSequenceFeatures((SequenceFeature[]) command.editedFeatures
+        sequence.setSequenceFeatures(command.editedFeatures
                 .get(seq));
       }
 
@@ -927,7 +1020,7 @@ public class EditCommand implements CommandI
 
     if (command.editedFeatures == null)
     {
-      command.editedFeatures = new Hashtable();
+      command.editedFeatures = new Hashtable<SequenceI, SequenceFeature[]>();
     }
 
     command.editedFeatures.put(seq, oldsf);
@@ -940,15 +1033,15 @@ public class EditCommand implements CommandI
 
     boolean fullAlignmentHeight = false;
 
-    Hashtable deletedAnnotationRows;
+    Hashtable<SequenceI, AlignmentAnnotation[]> deletedAnnotationRows;
 
-    Hashtable deletedAnnotations;
+    Hashtable<String, Annotation[]> deletedAnnotations;
 
-    Hashtable editedFeatures;
+    Hashtable<SequenceI, SequenceFeature[]> editedFeatures;
 
     AlignmentI al;
 
-    int command;
+    Action command;
 
     char[][] string;
 
@@ -960,7 +1053,7 @@ public class EditCommand implements CommandI
 
     char gapChar;
 
-    Edit(int command, SequenceI[] seqs, int position, int number,
+    Edit(Action command, SequenceI[] seqs, int position, int number,
             char gapChar)
     {
       this.command = command;
@@ -970,7 +1063,7 @@ public class EditCommand implements CommandI
       this.gapChar = gapChar;
     }
 
-    Edit(int command, SequenceI[] seqs, int position, int number,
+    Edit(Action command, SequenceI[] seqs, int position, int number,
             AlignmentI al)
     {
       this.gapChar = al.getGapCharacter();
@@ -989,7 +1082,7 @@ public class EditCommand implements CommandI
       fullAlignmentHeight = (al.getHeight() == seqs.length);
     }
 
-    Edit(int command, SequenceI[] seqs, int position, int number,
+    Edit(Action command, SequenceI[] seqs, int position, int number,
             AlignmentI al, String replace)
     {
       this.command = command;
index 6172ce8..ac93d4e 100644 (file)
@@ -39,7 +39,8 @@ package jalview.commands;
  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-import jalview.datamodel.*;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceI;
 
 public class RemoveGapColCommand extends EditCommand
 {
@@ -55,7 +56,7 @@ public class RemoveGapColCommand extends EditCommand
     int startCol = -1, endCol = -1;
     columnsDeleted = 0;
 
-    edits = new Edit[0];
+    clearEdits();
 
     boolean delete = true;
     for (int i = start; i <= end; i++)
@@ -86,7 +87,8 @@ public class RemoveGapColCommand extends EditCommand
 
       if (!delete && startCol > -1)
       {
-        this.appendEdit(DELETE_GAP, seqs, startCol - columnsDeleted, endCol
+        this.appendEdit(Action.DELETE_GAP, seqs, startCol - columnsDeleted,
+                endCol
                 - startCol, al, false, null);
 
         columnsDeleted += (endCol - startCol);
@@ -100,7 +102,8 @@ public class RemoveGapColCommand extends EditCommand
       // This is for empty columns at the
       // end of the alignment
 
-      this.appendEdit(DELETE_GAP, seqs, startCol - columnsDeleted, end
+      this.appendEdit(Action.DELETE_GAP, seqs, startCol - columnsDeleted,
+              end
               - startCol + 1, al, false, null);
 
       columnsDeleted += (end - startCol + 1);
index 2e8d744..60d09f7 100644 (file)
@@ -39,7 +39,8 @@ package jalview.commands;
  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-import jalview.datamodel.*;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceI;
 
 public class RemoveGapsCommand extends EditCommand
 {
@@ -74,7 +75,7 @@ public class RemoveGapsCommand extends EditCommand
 
     int j, jSize;
 
-    edits = new Edit[0];
+    clearEdits();
 
     boolean delete = true;
     char[] sequence;
@@ -108,7 +109,7 @@ public class RemoveGapsCommand extends EditCommand
 
         if (!delete && startCol > -1)
         {
-          this.appendEdit(DELETE_GAP, new SequenceI[]
+          this.appendEdit(Action.DELETE_GAP, new SequenceI[]
           { seqs[s] }, start + startCol - deletedCols, endCol - startCol,
                   al, false, null);
 
@@ -119,7 +120,7 @@ public class RemoveGapsCommand extends EditCommand
       }
       if (delete && startCol > -1)
       {
-        this.appendEdit(DELETE_GAP, new SequenceI[]
+        this.appendEdit(Action.DELETE_GAP, new SequenceI[]
         { seqs[s] }, start + startCol - deletedCols, jSize - startCol, al,
                 false, null);
       }
index 1ad3d9e..382085c 100644 (file)
@@ -20,7 +20,7 @@
  */
 package jalview.commands;
 
-import jalview.datamodel.*;
+import jalview.datamodel.SequenceI;
 
 public class SlideSequencesCommand extends EditCommand
 {
@@ -37,21 +37,29 @@ public class SlideSequencesCommand extends EditCommand
     for (i = 0; i < lSize; i++)
     {
       for (j = 0; j < slideSize; j++)
+      {
         if (!jalview.util.Comparison.isGap(seqsLeft[i].getCharAt(j)))
         {
           gapsInsertedBegin = true;
           break;
         }
+      }
     }
 
+    Edit e = null;
+
     if (!gapsInsertedBegin)
-      edits = new Edit[]
-      { new Edit(DELETE_GAP, seqsLeft, 0, slideSize, gapChar) };
+    {
+      e = new Edit(Action.DELETE_GAP, seqsLeft, 0, slideSize, gapChar);
+      setEdit(e);
+    }
     else
-      edits = new Edit[]
-      { new Edit(INSERT_GAP, seqsRight, 0, slideSize, gapChar) };
+    {
+      e = new Edit(Action.INSERT_GAP, seqsRight, 0, slideSize, gapChar);
+      setEdit(e);
+    }
 
-    performEdit(0, null);
+    performEdit(e, null);
   }
 
   public boolean getGapsInsertedBegin()
@@ -63,12 +71,12 @@ public class SlideSequencesCommand extends EditCommand
   {
     boolean same = false;
 
-    if (command.edits[0].seqs.length == edits[0].seqs.length)
+    if (command.getEdit(0).seqs.length == getEdit(0).seqs.length)
     {
       same = true;
-      for (int i = 0; i < command.edits[0].seqs.length; i++)
+      for (int i = 0; i < command.getEdit(0).seqs.length; i++)
       {
-        if (edits[0].seqs[i] != command.edits[0].seqs[i])
+        if (getEdit(0).seqs[i] != command.getEdit(0).seqs[i])
         {
           same = false;
         }
@@ -77,10 +85,7 @@ public class SlideSequencesCommand extends EditCommand
 
     if (same)
     {
-      Edit[] temp = new Edit[command.edits.length + 1];
-      System.arraycopy(command.edits, 0, temp, 0, command.edits.length);
-      command.edits = temp;
-      command.edits[command.edits.length - 1] = edits[0];
+      command.addEdit(getEdit(0));
     }
 
     return same;
index a757d1a..ebbe827 100644 (file)
  */
 package jalview.commands;
 
-import java.util.*;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.util.ShiftList;
 
-import jalview.datamodel.*;
-import jalview.util.*;
+import java.util.List;
 
 public class TrimRegionCommand extends EditCommand
 {
@@ -39,7 +42,7 @@ public class TrimRegionCommand extends EditCommand
 
   SequenceGroup selectionGroup;
 
-  Vector deletedHiddenColumns;
+  List<int[]> deletedHiddenColumns;
 
   int columnsDeleted;
 
@@ -59,8 +62,7 @@ public class TrimRegionCommand extends EditCommand
 
       columnsDeleted = column;
 
-      edits = new Edit[]
-      { new Edit(CUT, seqs, 0, column, al) };
+      setEdit(new Edit(Action.CUT, seqs, 0, column, al));
     }
     else if (command.equalsIgnoreCase(TRIM_RIGHT))
     {
@@ -72,17 +74,16 @@ public class TrimRegionCommand extends EditCommand
 
       columnsDeleted = width - 1;
 
-      edits = new Edit[]
-      { new Edit(CUT, seqs, column + 1, width, al) };
+      setEdit(new Edit(Action.CUT, seqs, column + 1, width, al));
     }
 
     // We need to keep a record of the sequence start
     // in order to restore the state after a redo
-    int i, isize = edits[0].seqs.length;
+    int i, isize = getEdit(0).seqs.length;
     start = new int[isize];
     for (i = 0; i < isize; i++)
     {
-      start[i] = edits[0].seqs[i].getStart();
+      start[i] = getEdit(0).seqs[i].getStart();
     }
 
     performEdit(0, null);
@@ -160,7 +161,7 @@ public class TrimRegionCommand extends EditCommand
       int[] region;
       for (int i = 0; i < deletedHiddenColumns.size(); i++)
       {
-        region = (int[]) deletedHiddenColumns.elementAt(i);
+        region = deletedHiddenColumns.get(i);
         colSel.hideColumns(region[0], region[1]);
       }
     }
index 35d467a..f414d13 100644 (file)
  */
 package jalview.datamodel;
 
-import java.util.*;
+import jalview.util.ShiftList;
 
-import jalview.util.*;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Vector;
 
 /**
  * NOTE: Columns are zero based.
@@ -186,9 +189,9 @@ public class ColumnSelection
    * @param left
    *          shift in edit (+ve for removal, or -ve for inserts)
    */
-  public Vector compensateForEdit(int start, int change)
+  public List<int[]> compensateForEdit(int start, int change)
   {
-    Vector deletedHiddenColumns = null;
+    List<int[]> deletedHiddenColumns = null;
     for (int i = 0; i < size(); i++)
     {
       int temp = columnAt(i);
@@ -201,14 +204,14 @@ public class ColumnSelection
 
     if (hiddenColumns != null)
     {
-      deletedHiddenColumns = new Vector();
+      deletedHiddenColumns = new ArrayList<int[]>();
       int hSize = hiddenColumns.size();
       for (int i = 0; i < hSize; i++)
       {
         int[] region = (int[]) hiddenColumns.elementAt(i);
         if (region[0] > start && start + change > region[1])
         {
-          deletedHiddenColumns.addElement(hiddenColumns.elementAt(i));
+          deletedHiddenColumns.add(region);
 
           hiddenColumns.removeElementAt(i);
           i--;
@@ -752,6 +755,7 @@ public class ColumnSelection
   public boolean isVisible(int column)
   {
     if (hiddenColumns != null)
+    {
       for (int i = 0; i < hiddenColumns.size(); i++)
       {
         int[] region = (int[]) hiddenColumns.elementAt(i);
@@ -760,6 +764,7 @@ public class ColumnSelection
           return false;
         }
       }
+    }
 
     return true;
   }
@@ -1018,7 +1023,9 @@ public class ColumnSelection
         w += els.length;
       }
       if (w == 0)
+      {
         return;
+      }
       Enumeration e = annels.elements();
       alignmentAnnotation.annotations = new Annotation[w];
       w = 0;
index aefb5cc..bfeafd6 100755 (executable)
@@ -20,7 +20,9 @@
  */
 package jalview.datamodel;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 
 public class HiddenSequences
 {
@@ -143,34 +145,34 @@ public class HiddenSequences
     alignment.deleteSequence(sequence);
   }
 
-  public Vector showAll(
+  public List<SequenceI> showAll(
           Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
   {
-    Vector revealedSeqs = new Vector();
+    List<SequenceI> revealedSeqs = new ArrayList<SequenceI>();
     for (int i = 0; i < hiddenSequences.length; i++)
     {
       if (hiddenSequences[i] != null)
       {
-        Vector tmp = showSequence(i, hiddenRepSequences);
-        for (int t = 0; t < tmp.size(); t++)
+        List<SequenceI> tmp = showSequence(i, hiddenRepSequences);
+        for (SequenceI seq : tmp)
         {
-          revealedSeqs.addElement(tmp.elementAt(t));
+          revealedSeqs.add(seq);
         }
       }
     }
     return revealedSeqs;
   }
 
-  public Vector showSequence(int alignmentIndex,
+  public List<SequenceI> showSequence(int alignmentIndex,
           Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
   {
-    Vector revealedSeqs = new Vector();
+    List<SequenceI> revealedSeqs = new ArrayList<SequenceI>();
     SequenceI repSequence = alignment.getSequenceAt(alignmentIndex);
     if (repSequence != null && hiddenRepSequences != null
             && hiddenRepSequences.containsKey(repSequence))
     {
       hiddenRepSequences.remove(repSequence);
-      revealedSeqs.addElement(repSequence);
+      revealedSeqs.add(repSequence);
     }
 
     int start = adjustForHiddenSeqs(alignmentIndex - 1);
@@ -192,7 +194,7 @@ public class HiddenSequences
         {
           if (seq.getLength() > 0)
           {
-            revealedSeqs.addElement(seq);
+            revealedSeqs.add(seq);
             asequences.add(alignmentIndex, seq);
           }
           else
index 090b61d..fb03f04 100644 (file)
@@ -343,8 +343,7 @@ public abstract class JalviewChimeraBinding extends
   public void colourByChain()
   {
     colourBySequence = false;
-    // this is not a valid Chimera command; is there one? Menu option hidden
-    evalStateCommand("select *;color chain",false);
+    evalStateCommand("rainbow chain", false);
   }
 
   public void colourByCharge()
index 8bea101..04df3d6 100644 (file)
@@ -34,6 +34,7 @@ import jalview.api.analysis.ScoreModelI;
 import jalview.bin.Cache;
 import jalview.commands.CommandI;
 import jalview.commands.EditCommand;
+import jalview.commands.EditCommand.Action;
 import jalview.commands.OrderCommand;
 import jalview.commands.RemoveGapColCommand;
 import jalview.commands.RemoveGapsCommand;
@@ -1417,7 +1418,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     if (viewport.historyList.size() > 0)
     {
       undoMenuItem.setEnabled(true);
-      CommandI command = (CommandI) viewport.historyList.peek();
+      CommandI command = viewport.historyList.peek();
       undoMenuItem.setText(MessageManager.formatMessage(
               "label.undo_command", new String[]
               { command.getDescription() }));
@@ -1432,7 +1433,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     {
       redoMenuItem.setEnabled(true);
 
-      CommandI command = (CommandI) viewport.redoList.peek();
+      CommandI command = viewport.redoList.peek();
       redoMenuItem.setText(MessageManager.formatMessage(
               "label.redo_command", new String[]
               { command.getDescription() }));
@@ -1496,7 +1497,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     {
       return;
     }
-    CommandI command = (CommandI) viewport.historyList.pop();
+    CommandI command = viewport.historyList.pop();
     viewport.redoList.push(command);
     command.undoCommand(getViewAlignments());
 
@@ -1535,7 +1536,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       return;
     }
 
-    CommandI command = (CommandI) viewport.redoList.pop();
+    CommandI command = viewport.redoList.pop();
     viewport.historyList.push(command);
     command.doCommand(getViewAlignments());
 
@@ -1997,7 +1998,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         // /////
         // ADD HISTORY ITEM
         //
-        addHistoryItem(new EditCommand(MessageManager.getString("label.add_sequences"), EditCommand.PASTE,
+        addHistoryItem(new EditCommand(
+                MessageManager.getString("label.add_sequences"),
+                Action.PASTE,
                 sequences, 0, alignment.getWidth(), alignment));
       }
       // Add any annotations attached to sequences
@@ -2268,8 +2271,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     /*
      * //ADD HISTORY ITEM
      */
-    addHistoryItem(new EditCommand(MessageManager.getString("label.cut_sequences"), EditCommand.CUT, cut,
-            sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,
+    addHistoryItem(new EditCommand(
+            MessageManager.getString("label.cut_sequences"), Action.CUT,
+            cut, sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1,
             viewport.getAlignment()));
 
     viewport.setSelectionGroup(null);
index 91cc51e..0b3fa70 100644 (file)
@@ -42,6 +42,7 @@ import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
 import jalview.analysis.NJTree;
 import jalview.api.AlignViewportI;
 import jalview.bin.Cache;
+import jalview.commands.CommandI;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Annotation;
@@ -140,9 +141,9 @@ public class AlignViewport extends AlignmentViewport implements
 
   boolean gatherViewsHere = false;
 
-  Stack historyList = new Stack();
+  Stack<CommandI> historyList = new Stack<CommandI>();
 
-  Stack redoList = new Stack();
+  Stack<CommandI> redoList = new Stack<CommandI>();
 
   int thresholdTextColour = 0;
 
index cfac4ef..02865e1 100644 (file)
@@ -144,9 +144,6 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable,
       _alignwith = new Vector<AlignmentPanel>();
     }
 
-    // no colour by chain command in Chimera?
-    chainColour.setVisible(false);
-
     // save As not yet implemented
     savemenu.setVisible(false);
 
index 23ba893..007fefd 100644 (file)
@@ -323,8 +323,11 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     }
     jconsole = new Console(this, showjconsole);
     // add essential build information
-    jconsole.setHeader("Jalview Desktop "
+    jconsole.setHeader("Jalview Version: "
             + jalview.bin.Cache.getProperty("VERSION") + "\n"
+            + "Jalview Installation: "
+            + jalview.bin.Cache.getDefault("INSTALLATION", "unknown")
+            + "\n"
             + "Build Date: "
             + jalview.bin.Cache.getDefault("BUILD_DATE", "unknown") + "\n"
             + "Java version: " + System.getProperty("java.version") + "\n"
@@ -2602,7 +2605,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
                                                 + ermsg
                                                 + "</td></tr></table>"
                                                 + "<p>It may be that you have invalid JABA URLs<br/>in your web service preferences,"
-                                                + " or mis-configured HTTP proxy settings.</p>"
+                                                + "<br>or as a command-line argument, or mis-configured HTTP proxy settings.</p>"
                                                 + "<p>Check the <em>Connections</em> and <em>Web services</em> tab<br/>of the"
                                                 + " Tools->Preferences dialog box to change them.</p></html>"),
                                 "Web Service Configuration Problem",
index 2190858..8f841d1 100644 (file)
@@ -27,6 +27,7 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
+import jalview.gui.Help.HelpId;
 import jalview.io.JalviewFileChooser;
 import jalview.schemes.AnnotationColourGradient;
 import jalview.schemes.GraduatedColor;
@@ -61,6 +62,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Vector;
 
+import javax.help.HelpSetException;
 import javax.swing.AbstractCellEditor;
 import javax.swing.BorderFactory;
 import javax.swing.Icon;
@@ -132,7 +134,19 @@ public class FeatureSettings extends JPanel
       ex.printStackTrace();
     }
 
-    table = new JTable();
+    table = new JTable() {
+      @Override
+      public String getToolTipText(MouseEvent e) {
+        if (table.columnAtPoint(e.getPoint()) == 0) {
+          /*
+           * Tooltip for feature name only
+           */
+          return JvSwingUtils.wrapTooltip(true,
+                MessageManager.getString("label.feature_settings_click_drag"));
+        }
+        return null;
+      }
+    };
     table.getTableHeader().setFont(new Font("Verdana", Font.PLAIN, 12));
     table.setFont(new Font("Verdana", Font.PLAIN, 12));
     table.setDefaultRenderer(Color.class, new ColorRenderer());
@@ -201,8 +215,8 @@ public class FeatureSettings extends JPanel
         }
       }
     });
-    table.setToolTipText(JvSwingUtils
-                    .wrapTooltip(true, MessageManager.getString("label.feature_settings_click_drag")));
+//    table.setToolTipText(JvSwingUtils.wrapTooltip(true,
+//            MessageManager.getString("label.feature_settings_click_drag")));
     scrollPane.setViewportView(table);
 
     dassourceBrowser = new DasSourceBrowser(this);
@@ -572,7 +586,9 @@ public class FeatureSettings extends JPanel
                 || ((Boolean) fr.featureGroups.get(group)).booleanValue())
         {
           if (group != null)
+          {
             checkGroupState(group);
+          }
           type = tmpfeatures[index].getType();
           if (!visibleChecks.contains(type))
           {
@@ -610,7 +626,9 @@ public class FeatureSettings extends JPanel
     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,
@@ -691,12 +709,18 @@ public class FeatureSettings extends JPanel
     {
       order[i] = fr.getOrder(data[i][0].toString());
       if (order[i] < 0)
+      {
         order[i] = fr.setOrder(data[i][0].toString(), i / order.length);
+      }
       if (i > 1)
+      {
         sort = sort || order[i - 1] > order[i];
+      }
     }
     if (sort)
+    {
       jalview.util.QuickSort.sort(order, data);
+    }
   }
 
   void load()
@@ -887,7 +911,9 @@ public class FeatureSettings extends JPanel
   public void orderByAvWidth()
   {
     if (table == null || table.getModel() == null)
+    {
       return;
+    }
     Object[][] data = ((FeatureTableModel) table.getModel()).getData();
     float[] width = new float[data.length];
     float[] awidth;
@@ -909,7 +935,9 @@ public class FeatureSettings extends JPanel
         width[i] = 0;
       }
       if (max < width[i])
+      {
         max = width[i];
+      }
     }
     boolean sort = false;
     for (int i = 0; i < width.length; i++)
@@ -929,11 +957,15 @@ public class FeatureSettings extends JPanel
         fr.setOrder(data[i][0].toString(), width[i]); // store for later
       }
       if (i > 0)
+      {
         sort = sort || width[i - 1] > width[i];
+      }
     }
     if (sort)
+     {
       jalview.util.QuickSort.sort(width, data);
     // update global priority order
+    }
 
     updateFeatureRenderer(data, false);
     table.repaint();
@@ -1001,7 +1033,9 @@ public class FeatureSettings extends JPanel
 
   JButton sortByDens = new JButton();
 
-  JPanel transbuttons = new JPanel(new GridLayout(4, 1));
+  JButton help = new JButton();
+
+  JPanel transbuttons = new JPanel(new GridLayout(5, 1));
 
   private void jbInit() throws Exception
   {
@@ -1047,6 +1081,21 @@ public class FeatureSettings extends JPanel
         sortByDens(null);
       }
     });
+    help.setFont(JvSwingUtils.getLabelFont());
+    help.setText(MessageManager.getString("action.help"));
+    help.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        try
+        {
+          Help.showHelpWindow(HelpId.SequenceFeatureSettings);
+        } catch (HelpSetException e1)
+        {
+          e1.printStackTrace();
+        }
+      }
+    });
     cancel.setFont(JvSwingUtils.getLabelFont());
     cancel.setText(MessageManager.getString("action.cancel"));
     cancel.addActionListener(new ActionListener()
@@ -1094,6 +1143,8 @@ public class FeatureSettings extends JPanel
     });
 
     transparency.setMaximum(70);
+    transparency.setToolTipText(MessageManager
+            .getString("label.transparency_tip"));
     fetchDAS.setText(MessageManager.getString("label.fetch_das_features"));
     fetchDAS.addActionListener(new ActionListener()
     {
@@ -1129,6 +1180,9 @@ public class FeatureSettings extends JPanel
     transbuttons.add(invert);
     transbuttons.add(sortByScore);
     transbuttons.add(sortByDens);
+    transbuttons.add(help);
+    JPanel sliderPanel = new JPanel();
+    sliderPanel.add(transparency);
     transPanel.add(transparency);
     transPanel.add(transbuttons);
     buttonPanel.add(ok);
index dac17c0..ae3f457 100644 (file)
@@ -2,6 +2,7 @@ package jalview.gui;
 
 import java.net.URL;
 
+import javax.help.BadIDException;
 import javax.help.HelpBroker;
 import javax.help.HelpSet;
 import javax.help.HelpSetException;
@@ -14,6 +15,23 @@ import javax.help.HelpSetException;
  */
 public class Help
 {
+  public enum HelpId
+  {
+    Home("home"), SequenceFeatureSettings("seqfeatures.settings");
+
+    private String id;
+
+    private HelpId(String loc)
+    {
+      this.id = loc;
+    }
+
+    @Override
+    public String toString()
+    {
+      return this.id;
+    }
+  }
 
   private static final long HALF_A_MO = 500; // half a second
 
@@ -33,10 +51,11 @@ public class Help
    * 
    * This is a workaround for issue JAL-914 - both Desktop and AlignFrame
    * responding to F1 key, resulting in duplicate help windows opened.
+   * @param id TODO
    * 
    * @throws HelpSetException
    */
-  public static void showHelpWindow() throws HelpSetException
+  public static void showHelpWindow(HelpId id) throws HelpSetException
   {
     long timeNow = System.currentTimeMillis();
 
@@ -48,8 +67,21 @@ public class Help
       HelpSet hs = new HelpSet(cl, url);
 
       HelpBroker hb = hs.createHelpBroker();
-      hb.setCurrentID("home");
+      try
+      {
+        hb.setCurrentID(id.toString());
+      } catch (BadIDException bad)
+      {
+        System.out.println("Bad help link: " + id.toString()
+                + ": must match a target in help.jhm");
+        throw bad;
+      }
       hb.setDisplayed(true);
     }
   }
+
+  public static void showHelpWindow() throws HelpSetException
+  {
+    showHelpWindow(HelpId.Home);
+  }
 }
index dc26a36..9976471 100644 (file)
@@ -25,6 +25,7 @@ import jalview.analysis.AlignmentAnnotationUtils;
 import jalview.analysis.Conservation;
 import jalview.commands.ChangeCaseCommand;
 import jalview.commands.EditCommand;
+import jalview.commands.EditCommand.Action;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.Annotation;
 import jalview.datamodel.DBRefEntry;
@@ -2707,7 +2708,7 @@ public class PopupMenu extends JPopupMenu
       {
         EditCommand editCommand = new EditCommand(
                 MessageManager.getString("label.edit_sequences"),
-                EditCommand.REPLACE, dialog.getName().replace(' ',
+                Action.REPLACE, dialog.getName().replace(' ',
                         ap.av.getGapCharacter()),
                 sg.getSequencesAsArray(ap.av.getHiddenRepSequences()),
                 sg.getStartRes(), sg.getEndRes() + 1, ap.av.getAlignment());
index 09f3686..b082bc6 100755 (executable)
@@ -291,17 +291,7 @@ public class Preferences extends GPreferences
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        if (chimeraPath.getText().trim().length() > 0)
-        {
-          File f = new File(chimeraPath.getText());
-          if (!f.canExecute())
-          {
-            JOptionPane.showInternalMessageDialog(Desktop.desktop,
-                    MessageManager.getString("label.invalid_path"),
-                    MessageManager.getString("label.invalid_name"),
-                    JOptionPane.ERROR_MESSAGE);
-          }
-        }
+        validateChimeraPath();
       }
     });
 
@@ -376,6 +366,11 @@ public class Preferences extends GPreferences
    */
   public void ok_actionPerformed(ActionEvent e)
   {
+    if (!validateSettings())
+    {
+      return;
+    }
+
     /*
      * Save Visual settings
      */
@@ -601,6 +596,27 @@ public class Preferences extends GPreferences
   }
 
   /**
+   * Do any necessary validation before saving settings.
+   * 
+   * @return
+   */
+  private boolean validateSettings()
+  {
+    if (!validateStructure())
+    {
+      structureTab.requestFocusInWindow();
+      return false;
+    }
+    return true;
+  }
+
+  @Override
+  protected boolean validateStructure()
+  {
+    return validateChimeraPath();
+
+  }
+  /**
    * DOCUMENT ME!
    */
   public void startupFileTextfield_mouseClicked()
@@ -842,4 +858,25 @@ public class Preferences extends GPreferences
     userIdWidthlabel.setEnabled(!autoIdWidth.isSelected());
   }
 
+  /**
+   * Returns true if chimera path is to a valid executable, else show an error
+   * dialog.
+   */
+  private boolean validateChimeraPath()
+  {
+    if (chimeraPath.getText().trim().length() > 0)
+    {
+      File f = new File(chimeraPath.getText());
+      if (!f.canExecute())
+      {
+        JOptionPane.showInternalMessageDialog(Desktop.desktop,
+                MessageManager.getString("label.invalid_chimera_path"),
+                MessageManager.getString("label.invalid_name"),
+                JOptionPane.ERROR_MESSAGE);
+        return false;
+      }
+    }
+    return true;
+  }
+
 }
index 0e55cf8..ab0a0b8 100755 (executable)
  */
 package jalview.gui;
 
-import java.util.*;
-
-import java.awt.event.*;
-import javax.swing.*;
-import javax.swing.event.*;
-
 import jalview.analysis.AlignSeq;
-import jalview.commands.*;
-import jalview.datamodel.*;
-import jalview.jbgui.*;
+import jalview.commands.CommandI;
+import jalview.commands.EditCommand;
+import jalview.commands.EditCommand.Action;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.jbgui.GSliderPanel;
 import jalview.util.MessageManager;
 
+import java.awt.event.ActionEvent;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+import java.util.Vector;
+
+import javax.swing.JInternalFrame;
+import javax.swing.JProgressBar;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.InternalFrameAdapter;
+import javax.swing.event.InternalFrameEvent;
+
 /**
  * DOCUMENT ME!
  * 
@@ -44,7 +54,9 @@ public class RedundancyPanel extends GSliderPanel implements Runnable
 
   AlignmentPanel ap;
 
-  Stack historyList = new Stack(); // simpler than synching with alignFrame.
+  Stack<CommandI> historyList = new Stack<CommandI>();
+
+  // simpler than synching with alignFrame.
 
   float[] redundancy;
 
@@ -229,7 +241,7 @@ public class RedundancyPanel extends GSliderPanel implements Runnable
       }
 
       EditCommand cut = new EditCommand(MessageManager.getString("action.remove_redundancy"),
-              EditCommand.CUT, deleted, 0, width, ap.av.getAlignment());
+              Action.CUT, deleted, 0, width, ap.av.getAlignment());
 
       for (int i = 0; i < del.size(); i++)
       {
@@ -263,7 +275,7 @@ public class RedundancyPanel extends GSliderPanel implements Runnable
        return;
     }
     
-    CommandI command = (CommandI) historyList.pop();
+    CommandI command = historyList.pop();
     if (ap.av.historyList.contains(command))
     {
       command.undoCommand(af.getViewAlignments());
diff --git a/src/jalview/gui/SVGOptions.java b/src/jalview/gui/SVGOptions.java
new file mode 100644 (file)
index 0000000..b5e194b
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
+ * Copyright (C) 2014 The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.gui;
+
+import jalview.util.MessageManager;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.BorderFactory;
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+
+public class SVGOptions extends JPanel
+{
+  JDialog dialog;
+
+  public boolean cancelled = false;
+
+  String value;
+
+  public SVGOptions()
+  {
+    try
+    {
+      jbInit();
+    } catch (Exception ex)
+    {
+      ex.printStackTrace();
+    }
+
+    ButtonGroup bg = new ButtonGroup();
+    bg.add(lineart);
+    bg.add(text);
+
+    JOptionPane pane = new JOptionPane(null, JOptionPane.DEFAULT_OPTION,
+            JOptionPane.DEFAULT_OPTION, null, new Object[]
+            { this });
+
+    dialog = pane.createDialog(Desktop.desktop, "SVG Rendering options");
+    dialog.setVisible(true);
+
+  }
+
+  private void jbInit() throws Exception
+  {
+    lineart.setFont(JvSwingUtils.getLabelFont());
+    lineart.setText(MessageManager.getString("label.lineart"));
+    text.setFont(JvSwingUtils.getLabelFont());
+    text.setText(MessageManager.getString("action.text"));
+    text.setSelected(true);
+    askAgain.setFont(JvSwingUtils.getLabelFont());
+    askAgain.setText(MessageManager.getString("label.dont_ask_me_again"));
+    ok.setText(MessageManager.getString("action.ok"));
+    ok.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        ok_actionPerformed(e);
+      }
+    });
+    cancel.setText(MessageManager.getString("action.cancel"));
+    cancel.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        cancel_actionPerformed(e);
+      }
+    });
+    jLabel1.setFont(JvSwingUtils.getLabelFont());
+    jLabel1.setText("Select SVG character rendering style");
+    this.setLayout(borderLayout1);
+    jPanel3.setBorder(BorderFactory.createEtchedBorder());
+    jPanel2.add(text);
+    jPanel2.add(lineart);
+    jPanel2.add(askAgain);
+    jPanel1.add(ok);
+    jPanel1.add(cancel);
+    jPanel3.add(jLabel1);
+    jPanel3.add(jPanel2);
+    this.add(jPanel3, java.awt.BorderLayout.CENTER);
+    this.add(jPanel1, java.awt.BorderLayout.SOUTH);
+  }
+
+  JRadioButton lineart = new JRadioButton();
+
+  JRadioButton text = new JRadioButton();
+
+  JCheckBox askAgain = new JCheckBox();
+
+  JButton ok = new JButton();
+
+  JButton cancel = new JButton();
+
+  JPanel jPanel1 = new JPanel();
+
+  JLabel jLabel1 = new JLabel();
+
+  JPanel jPanel2 = new JPanel();
+
+  JPanel jPanel3 = new JPanel();
+
+  BorderLayout borderLayout1 = new BorderLayout();
+
+  public void ok_actionPerformed(ActionEvent e)
+  {
+    if (lineart.isSelected())
+    {
+      value = "Lineart";
+    }
+    else
+    {
+      value = "Text";
+    }
+
+    if (!askAgain.isSelected())
+    {
+      jalview.bin.Cache.applicationProperties.remove("SVG_RENDERING");
+    }
+    else
+    {
+      jalview.bin.Cache.setProperty("SVG_RENDERING", value);
+    }
+
+    dialog.setVisible(false);
+  }
+
+  public void cancel_actionPerformed(ActionEvent e)
+  {
+    cancelled = true;
+    dialog.setVisible(false);
+  }
+
+  public String getValue()
+  {
+    return value;
+  }
+}
index 6a9c8ee..4f331ab 100644 (file)
@@ -21,6 +21,7 @@
 package jalview.gui;
 
 import jalview.commands.EditCommand;
+import jalview.commands.EditCommand.Action;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.SearchResults;
 import jalview.datamodel.Sequence;
@@ -768,7 +769,8 @@ public class SeqPanel extends JPanel implements MouseListener,
       if (lastTooltip == null
               || !lastTooltip.equals(tooltipText.toString()))
       {
-        setToolTipText(tooltipText.toString());
+        setToolTipText(JvSwingUtils.wrapTooltip(true,
+                tooltipText.toString()));
         lastTooltip = tooltipText.toString();
       }
 
@@ -1190,7 +1192,7 @@ public class SeqPanel extends JPanel implements MouseListener,
         }
         else
         {
-          editCommand.appendEdit(EditCommand.INSERT_GAP, groupSeqs,
+          editCommand.appendEdit(Action.INSERT_GAP, groupSeqs,
                   startres, startres - lastres, av.getAlignment(), true);
         }
       }
@@ -1206,7 +1208,7 @@ public class SeqPanel extends JPanel implements MouseListener,
         }
         else
         {
-          editCommand.appendEdit(EditCommand.DELETE_GAP, groupSeqs,
+          editCommand.appendEdit(Action.DELETE_GAP, groupSeqs,
                   startres, lastres - startres, av.getAlignment(), true);
         }
 
@@ -1228,7 +1230,7 @@ public class SeqPanel extends JPanel implements MouseListener,
         }
         else
         {
-          editCommand.appendEdit(EditCommand.INSERT_GAP, new SequenceI[]
+          editCommand.appendEdit(Action.INSERT_GAP, new SequenceI[]
           { seq }, lastres, startres - lastres, av.getAlignment(), true);
         }
       }
@@ -1265,7 +1267,7 @@ public class SeqPanel extends JPanel implements MouseListener,
 
             if (max > 0)
             {
-              editCommand.appendEdit(EditCommand.DELETE_GAP,
+              editCommand.appendEdit(Action.DELETE_GAP,
                       new SequenceI[]
                       { seq }, startres, max, av.getAlignment(), true);
             }
@@ -1283,7 +1285,7 @@ public class SeqPanel extends JPanel implements MouseListener,
           }
           else
           {
-            editCommand.appendEdit(EditCommand.INSERT_NUC, new SequenceI[]
+            editCommand.appendEdit(Action.INSERT_NUC, new SequenceI[]
             { seq }, lastres, startres - lastres, av.getAlignment(), true);
           }
         }
@@ -1319,10 +1321,10 @@ public class SeqPanel extends JPanel implements MouseListener,
       }
     }
 
-    editCommand.appendEdit(EditCommand.DELETE_GAP, seq, blankColumn, 1,
+    editCommand.appendEdit(Action.DELETE_GAP, seq, blankColumn, 1,
             av.getAlignment(), true);
 
-    editCommand.appendEdit(EditCommand.INSERT_GAP, seq, j, 1,
+    editCommand.appendEdit(Action.INSERT_GAP, seq, j, 1,
             av.getAlignment(), true);
 
   }
@@ -1330,10 +1332,10 @@ public class SeqPanel extends JPanel implements MouseListener,
   void deleteChar(int j, SequenceI[] seq, int fixedColumn)
   {
 
-    editCommand.appendEdit(EditCommand.DELETE_GAP, seq, j, 1,
+    editCommand.appendEdit(Action.DELETE_GAP, seq, j, 1,
             av.getAlignment(), true);
 
-    editCommand.appendEdit(EditCommand.INSERT_GAP, seq, fixedColumn, 1,
+    editCommand.appendEdit(Action.INSERT_GAP, seq, fixedColumn, 1,
             av.getAlignment(), true);
   }
 
index 8c889c9..4a74c9c 100644 (file)
@@ -436,7 +436,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
   protected void revert_actionPerformed(ActionEvent e)
   {
     reInitDialog(lastParmSet);
-
+    updateWebServiceMenus();
   }
 
   protected void update_actionPerformed(ActionEvent e)
@@ -465,6 +465,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
       _deleteUserPreset(lastParmSet);
     }
     reInitDialog(null); // service default
+    updateWebServiceMenus();
   }
 
   protected void create_actionPerformed(ActionEvent e)
@@ -475,7 +476,9 @@ public class WsJobParameters extends JPanel implements ItemListener,
       _storeCurrentPreset(curname);
       lastParmSet = curname;
       isUserPreset = true;
+      reInitDialog(curname);
       initArgSetModified();
+      updateWebServiceMenus();
     }
     else
     {
@@ -953,7 +956,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
     {
       Vector<String> services = new Vector<String>();
       services.addElement(args[p++]);
-      Jws2Discoverer.setServiceUrls(services);
+      Jws2Discoverer.getDiscoverer().setServiceUrls(services);
     }
     try
     {
@@ -1295,7 +1298,18 @@ public class WsJobParameters extends JPanel implements ItemListener,
     SetNamePanel.validate();
     validate();
     settingDialog = false;
+  }
 
+  /**
+   * Rebuild the AlignFrame web service menus (after add/delete of a preset
+   * option).
+   */
+  protected void updateWebServiceMenus()
+  {
+    for (AlignFrame alignFrame : Desktop.getAlignframes())
+    {
+      alignFrame.BuildWebServiceMenu();
+    }
   }
 
   String curSetName = null;
index de89241..527750c 100644 (file)
@@ -33,6 +33,7 @@ import java.awt.Dimension;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.net.URL;
+import java.util.List;
 import java.util.Vector;
 
 import javax.swing.JLabel;
@@ -52,7 +53,9 @@ public class WsPreferences extends GWsPreferences
     initFromPreferences();
   }
 
-  Vector<String> wsUrls, oldUrls, rsbsUrls, oldRsbsUrls;
+  List<String> wsUrls;
+
+  Vector<String> oldUrls, rsbsUrls, oldRsbsUrls;
 
   private boolean needWsMenuUpdate;
 
@@ -62,8 +65,8 @@ public class WsPreferences extends GWsPreferences
   private void initFromPreferences()
   {
 
-    wsUrls = jalview.ws.jws2.Jws2Discoverer.getServiceUrls();
-    if (wsUrls != null)
+    wsUrls = Jws2Discoverer.getDiscoverer().getServiceUrls();
+    if (!wsUrls.isEmpty())
     {
       oldUrls = new Vector<String>(wsUrls);
     }
@@ -235,7 +238,7 @@ public class WsPreferences extends GWsPreferences
 
   private void updateServiceList()
   {
-    jalview.ws.jws2.Jws2Discoverer.setServiceUrls(wsUrls);
+    Jws2Discoverer.getDiscoverer().setServiceUrls(wsUrls);
   }
 
   private void updateRsbsServiceList()
@@ -256,7 +259,7 @@ public class WsPreferences extends GWsPreferences
     int sel = wsList.getSelectedRow();
     if (sel > -1)
     {
-      wsUrls.removeElementAt(sel);
+      wsUrls.remove(sel);
       update++;
       updateList();
     }
@@ -274,21 +277,22 @@ public class WsPreferences extends GWsPreferences
     int sel = wsList.getSelectedRow();
     if (sel > -1)
     {
-      String url = editUrl(wsUrls.elementAt(sel), MessageManager.getString("label.edit_jabaws_url"));
+      String url = editUrl(wsUrls.get(sel),
+              MessageManager.getString("label.edit_jabaws_url"));
       if (url != null)
       {
         int present = wsUrls.indexOf(url);
         if (present == -1)
         {
           update++;
-          wsUrls.setElementAt(url, sel);
+          wsUrls.set(sel, url);
           updateList();
         }
         else
         {
           if (present != sel)
           {
-            wsUrls.removeElementAt(sel);
+            wsUrls.remove(sel);
             updateList();
           }
         }
@@ -406,8 +410,8 @@ public class WsPreferences extends GWsPreferences
     if (p > -1 && p < wsUrls.size() - 1)
     {
       String t = wsUrls.get(p + 1);
-      wsUrls.setElementAt(wsUrls.elementAt(p), p + 1);
-      wsUrls.setElementAt(t, p);
+      wsUrls.set(p + 1, wsUrls.get(p));
+      wsUrls.set(p, t);
       updateList();
       wsList.getSelectionModel().setSelectionInterval(p + 1, p + 1);
       update++;
@@ -428,8 +432,8 @@ public class WsPreferences extends GWsPreferences
     if (p > 0)
     {
       String t = wsUrls.get(p - 1);
-      wsUrls.setElementAt(wsUrls.elementAt(p), p - 1);
-      wsUrls.setElementAt(t, p);
+      wsUrls.set(p - 1, wsUrls.get(p));
+      wsUrls.set(p, t);
       updateList();
       wsList.getSelectionModel().setSelectionInterval(p - 1, p - 1);
       update++;
@@ -487,7 +491,7 @@ public class WsPreferences extends GWsPreferences
 
       if (validate == JOptionPane.OK_OPTION)
       {
-        if (jalview.ws.jws2.Jws2Discoverer.testServiceUrl(foo))
+        if (Jws2Discoverer.testServiceUrl(foo))
         {
           return foo.toString();
         }
@@ -498,7 +502,7 @@ public class WsPreferences extends GWsPreferences
                           Desktop.desktop,
                           "The Server  '"
                                   + foo.toString()
-                                  + "' failed validation, do you want to proceed and add it anyway? ",
+                                  + "' failed validation,\ndo you want to add it anyway? ",
                           "Server Validation Failed",
                           JOptionPane.YES_NO_OPTION,
                           JOptionPane.INFORMATION_MESSAGE, null, null, null);
@@ -544,11 +548,11 @@ public class WsPreferences extends GWsPreferences
         int selind = wsList.getSelectedRow();
         if (selind > -1)
         {
-          wsUrls.insertElementAt(url, selind);
+          wsUrls.add(selind, url);
         }
         else
         {
-          wsUrls.addElement(url);
+          wsUrls.add(url);
         }
         update++;
         updateList();
@@ -651,8 +655,8 @@ public class WsPreferences extends GWsPreferences
   @Override
   protected void resetWs_actionPerformed(ActionEvent e)
   {
-    jalview.ws.jws2.Jws2Discoverer.setServiceUrls(null);
-    Vector nwsUrls = jalview.ws.jws2.Jws2Discoverer.getServiceUrls();
+    Jws2Discoverer.getDiscoverer().setServiceUrls(null);
+    List<String> nwsUrls = Jws2Discoverer.getDiscoverer().getServiceUrls();
     if (!wsUrls.equals(nwsUrls))
     {
       update++;
index a232377..5569c24 100755 (executable)
@@ -26,6 +26,7 @@ import jalview.util.MessageManager;
 
 import java.awt.BorderLayout;
 import java.awt.Color;
+import java.awt.Component;
 import java.awt.Dimension;
 import java.awt.FlowLayout;
 import java.awt.Font;
@@ -36,6 +37,7 @@ import java.awt.Insets;
 import java.awt.Rectangle;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
@@ -45,6 +47,7 @@ import javax.swing.DefaultListCellRenderer;
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
+import javax.swing.JFileChooser;
 import javax.swing.JLabel;
 import javax.swing.JList;
 import javax.swing.JPanel;
@@ -56,6 +59,8 @@ import javax.swing.SwingConstants;
 import javax.swing.border.Border;
 import javax.swing.border.EmptyBorder;
 import javax.swing.border.TitledBorder;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
 
@@ -128,8 +133,10 @@ public class GPreferences extends JPanel
   protected JCheckBox showNpTooltip = new JCheckBox();
 
   /*
-   * Annotations tab components
+   * Structure tab and components
    */
+  protected JPanel structureTab;
+
   protected JCheckBox structFromPdb = new JCheckBox();
 
   protected JCheckBox useRnaView = new JCheckBox();
@@ -239,7 +246,7 @@ public class GPreferences extends JPanel
    */
   private void jbInit() throws Exception
   {
-    JTabbedPane tabbedPane = new JTabbedPane();
+    final JTabbedPane tabbedPane = new JTabbedPane();
     this.setLayout(new BorderLayout());
     JPanel okCancelPanel = initOkCancelPanel();
     this.add(tabbedPane, BorderLayout.CENTER);
@@ -273,6 +280,31 @@ public class GPreferences extends JPanel
      */
     wsTab.setLayout(new BorderLayout());
     tabbedPane.add(wsTab, MessageManager.getString("label.web_services"));
+
+    /*
+     * Handler to validate a tab before leaving it - currently only for
+     * Structure.
+     */
+    tabbedPane.addChangeListener(new ChangeListener()
+    {
+      private Component lastTab;
+
+      @Override
+      public void stateChanged(ChangeEvent e)
+      {
+        if (lastTab == structureTab
+                && tabbedPane.getSelectedComponent() != structureTab)
+        {
+          if (!validateStructure())
+          {
+            tabbedPane.setSelectedComponent(structureTab);
+            return;
+          }
+        }
+        lastTab = tabbedPane.getSelectedComponent();
+      }
+
+    });
   }
 
   /**
@@ -691,7 +723,8 @@ public class GPreferences extends JPanel
    */
   private JPanel initStructureTab()
   {
-    JPanel structureTab = new JPanel();
+    structureTab = new JPanel();
+
     structureTab.setBorder(new TitledBorder(MessageManager
             .getString("label.structure_options")));
     structureTab.setLayout(null);
@@ -756,20 +789,81 @@ public class GPreferences extends JPanel
     pathLabel.setFont(new java.awt.Font("SansSerif", 0, 11));
     pathLabel.setHorizontalAlignment(SwingConstants.LEFT);
     pathLabel.setText(MessageManager.getString("label.chimera_path"));
-    pathLabel.setToolTipText(MessageManager
-            .getString("label.chimera_path_tip"));
+    final String tooltip = JvSwingUtils.wrapTooltip(true,
+            MessageManager.getString("label.chimera_path_tip"));
+    pathLabel.setToolTipText(tooltip);
     pathLabel.setBounds(new Rectangle(10, ypos, 140, height));
     structureTab.add(pathLabel);
 
     chimeraPath.setFont(verdana11);
     chimeraPath.setText("");
     chimeraPath.setBounds(new Rectangle(160, ypos, 300, height));
+    chimeraPath.addMouseListener(new MouseAdapter()
+    {
+      @Override
+      public void mouseClicked(MouseEvent e)
+      {
+        if (e.getClickCount() == 2)
+        {
+          String chosen = openFileChooser();
+          if (chosen != null)
+          {
+            chimeraPath.setText(chosen);
+          }
+        }
+      }
+    });
     structureTab.add(chimeraPath);
 
     return structureTab;
   }
 
   /**
+   * Show a dialog for the user to choose a file. Returns the chosen path, or
+   * null on Cancel.
+   * 
+   * @return
+   */
+  protected String openFileChooser()
+  {
+    String choice = null;
+    JFileChooser chooser = new JFileChooser();
+
+    // chooser.setFileView(new JalviewFileView());
+    chooser.setDialogTitle(MessageManager
+            .getString("label.open_local_file"));
+    chooser.setToolTipText(MessageManager.getString("action.open"));
+
+    int value = chooser.showOpenDialog(this);
+
+    if (value == JFileChooser.APPROVE_OPTION)
+    {
+      choice = chooser.getSelectedFile().getPath();
+    }
+    return choice;
+  }
+
+  /**
+   * Validate the structure tab preferences; if invalid, set focus on this tab.
+   * 
+   * @param e
+   */
+  protected boolean validateStructure(FocusEvent e)
+  {
+    if (!validateStructure())
+    {
+      e.getComponent().requestFocusInWindow();
+      return false;
+    }
+    return true;
+  }
+
+  protected boolean validateStructure()
+  {
+    return false;
+  }
+
+  /**
    * Initialises the Visual tabbed panel.
    * 
    * @return
index 61ef34f..b410be6 100755 (executable)
@@ -21,6 +21,7 @@
 package jalview.util;
 
 import jalview.gui.EPSOptions;
+import jalview.gui.SVGOptions;
 import jalview.io.JalviewFileChooser;
 
 import java.awt.Component;
@@ -34,6 +35,7 @@ import java.io.FileOutputStream;
 import javax.imageio.ImageIO;
 
 import org.jfree.graphics2d.svg.SVGGraphics2D;
+import org.jfree.graphics2d.svg.SVGHints;
 import org.jibble.epsgraphics.EpsGraphics2D;
 
 public class ImageMaker
@@ -219,11 +221,39 @@ public class ImageMaker
     Graphics2D ig2 = (Graphics2D) graphics;
     ig2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
             RenderingHints.VALUE_ANTIALIAS_ON);
+
   }
 
   void setupSVG(int width, int height, String title)
   {
+
     g2 = new SVGGraphics2D(width, height);
+    Graphics2D ig2 = g2;
+
+    String renderStyle = jalview.bin.Cache.getDefault("SVG_RENDERING",
+            "Prompt each time");
+
+    // If we need to prompt, and if the GUI is visible then
+    // Prompt for EPS rendering style
+    if (renderStyle.equalsIgnoreCase("Prompt each time")
+            && !(System.getProperty("java.awt.headless") != null && System
+                    .getProperty("java.awt.headless").equals("true")))
+    {
+      SVGOptions svgOption = new SVGOptions();
+      renderStyle = svgOption.getValue();
+
+      if (renderStyle == null || svgOption.cancelled)
+      {
+        return;
+      }
+    }
+
+    if (renderStyle.equalsIgnoreCase("lineart"))
+    {
+      ig2.setRenderingHint(SVGHints.KEY_DRAW_STRING_TYPE,
+              SVGHints.VALUE_DRAW_STRING_TYPE_VECTOR);
+    }
+
     graphics = g2;
   }
 
index 0fa4a3c..1b42faf 100644 (file)
@@ -20,7 +20,6 @@
  */
 package jalview.viewmodel;
 
-import jalview.analysis.AAFrequency;
 import jalview.analysis.Conservation;
 import jalview.api.AlignCalcManagerI;
 import jalview.api.AlignViewportI;
@@ -35,7 +34,6 @@ import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.schemes.Blosum62ColourScheme;
-import jalview.schemes.ClustalxColourScheme;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.PIDColourScheme;
 import jalview.schemes.ResidueProperties;
@@ -447,7 +445,9 @@ public abstract class AlignmentViewport implements AlignViewportI
           AlignmentAnnotation alignmentAnnotation)
   {
     if (!alignmentAnnotation.autoCalculated)
+    {
       return false;
+    }
     if (calculator.workingInvolvedWith(alignmentAnnotation))
     {
       // System.err.println("grey out ("+alignmentAnnotation.label+")");
@@ -899,11 +899,12 @@ public abstract class AlignmentViewport implements AlignViewportI
         selectionGroup = new SequenceGroup();
         selectionGroup.setEndRes(alignment.getWidth() - 1);
       }
-      Vector tmp = alignment.getHiddenSequences().showAll(
+      List<SequenceI> tmp = alignment.getHiddenSequences().showAll(
               hiddenRepSequences);
-      for (int t = 0; t < tmp.size(); t++)
+      for (SequenceI seq : tmp)
       {
-        selectionGroup.addSequence((SequenceI) tmp.elementAt(t), false);
+        selectionGroup.addSequence(seq, false);
+        setSequenceAnnotationsVisible(seq, true);
       }
 
       hasHiddenRows = false;
@@ -918,7 +919,8 @@ public abstract class AlignmentViewport implements AlignViewportI
 
   public void showSequence(int index)
   {
-    Vector tmp = alignment.getHiddenSequences().showSequence(index,
+    List<SequenceI> tmp = alignment.getHiddenSequences().showSequence(
+            index,
             hiddenRepSequences);
     if (tmp.size() > 0)
     {
@@ -928,9 +930,10 @@ public abstract class AlignmentViewport implements AlignViewportI
         selectionGroup.setEndRes(alignment.getWidth() - 1);
       }
 
-      for (int t = 0; t < tmp.size(); t++)
+      for (SequenceI seq : tmp)
       {
-        selectionGroup.addSequence((SequenceI) tmp.elementAt(t), false);
+        selectionGroup.addSequence(seq, false);
+        setSequenceAnnotationsVisible(seq, true);
       }
       // JBPNote: refactor: only update flag if we modified visiblity (used to
       // do this regardless)
@@ -964,12 +967,30 @@ public abstract class AlignmentViewport implements AlignViewportI
       for (int i = 0; i < seq.length; i++)
       {
         alignment.getHiddenSequences().hideSequence(seq[i]);
+        setSequenceAnnotationsVisible(seq[i], false);
       }
       hasHiddenRows = true;
       firePropertyChange("alignment", null, alignment.getSequences());
     }
   }
 
+  /**
+   * Set visibility for any annotations for the given sequence.
+   * 
+   * @param sequenceI
+   */
+  protected void setSequenceAnnotationsVisible(SequenceI sequenceI,
+          boolean visible)
+  {
+    for (AlignmentAnnotation ann : alignment.getAlignmentAnnotation())
+    {
+      if (ann.sequenceRef == sequenceI)
+      {
+        ann.visible = visible;
+      }
+    }
+  }
+
   public void hideRepSequences(SequenceI repSequence, SequenceGroup sg)
   {
     int sSize = sg.getSize();
index 2eb484b..74dce4d 100644 (file)
@@ -27,6 +27,9 @@ import jalview.bin.Cache;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
 import jalview.ws.jws2.jabaws2.Jws2InstanceFactory;
 
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -44,7 +47,7 @@ public class JabaWsServerQuery implements Runnable
 
   Jws2Discoverer jws2Discoverer = null;
 
-  String jwsservers = null;
+  String jwsserver = null;
 
   boolean quit = false, running = false;
 
@@ -65,10 +68,10 @@ public class JabaWsServerQuery implements Runnable
     this.quit = quit;
   }
 
-  public JabaWsServerQuery(Jws2Discoverer jws2Discoverer, String jwsservers)
+  public JabaWsServerQuery(Jws2Discoverer jws2Discoverer, String server)
   {
     this.jws2Discoverer = jws2Discoverer;
-    this.jwsservers = jwsservers;
+    this.jwsserver = server;
   }
 
   Services[] JABAWS1SERVERS = new Services[]
@@ -92,7 +95,9 @@ public class JabaWsServerQuery implements Runnable
     running = true;
     try
     {
-      if (Jws2Client.validURL(jwsservers))
+      // TODO this test doesn't seem to attempt a connection - should it?
+      // would save a lot of failed tries with UnknownHostException
+      if (isValidUrl(jwsserver))
       {
         compbio.data.msa.RegistryWS registry = null;
         Set svccategories = null;
@@ -109,7 +114,7 @@ public class JabaWsServerQuery implements Runnable
         try
         {
           // JBPNote: why is RegistryWS in compbio.data.msa ?
-          registry = Jws2Client.connectToRegistry(jwsservers);
+          registry = Jws2Client.connectToRegistry(jwsserver);
           if (registry != null)
           {
             // System.err.println("Test Services Output\n"
@@ -137,13 +142,14 @@ public class JabaWsServerQuery implements Runnable
           ex.printStackTrace();
           // if that failed, then we are probably working with a JABAWS1 server.
           // in that case, look for each service endpoint
-          System.err.println("JWS2 Discoverer: " + jwsservers
+          System.err.println("JWS2 Discoverer: " + jwsserver
                   + " is a JABAWS1 server. Using hardwired list.");
           for (Services srv : JABAWS1SERVERS)
           {
             srv_set.add(srv);
           }
         }
+
         for (Category cat : categories)
         {
           for (Services srv : cat.getServices())
@@ -160,18 +166,18 @@ public class JabaWsServerQuery implements Runnable
             JABAService service = null;
             try
             {
-              service = Jws2Client.connect(jwsservers, srv);
+              service = Jws2Client.connect(jwsserver, srv);
             } catch (Exception e)
             {
               System.err.println("Jws2 Discoverer: Problem on "
-                      + jwsservers + " with service " + srv + ":\n"
+                      + jwsserver + " with service " + srv + ":\n"
                       + e.getMessage());
               if (!(e instanceof javax.xml.ws.WebServiceException))
               {
                 e.printStackTrace();
               }
               // For moment, report service as a problem.
-              jws2Discoverer.addInvalidServiceUrl(jwsservers);
+              jws2Discoverer.addInvalidServiceUrl(jwsserver);
             }
             ;
             if (service != null)
@@ -183,16 +189,16 @@ public class JabaWsServerQuery implements Runnable
 
                 String description = registry.getServiceDescription(srv);
 
-                svc = Jws2InstanceFactory.newJws2Instance(jwsservers,
+                svc = Jws2InstanceFactory.newJws2Instance(jwsserver,
                         srv.toString(), cat.name, description, service);
               }
               if (svc == null)
               {
-                svc = Jws2InstanceFactory.newJws2Instance(jwsservers,
+                svc = Jws2InstanceFactory.newJws2Instance(jwsserver,
                         srv.toString(), cat.name,
                         "JABAWS 1 Alignment Service", service);
               }
-              jws2Discoverer.addService(jwsservers, svc);
+              jws2Discoverer.addService(jwsserver, svc);
             }
 
           }
@@ -200,25 +206,53 @@ public class JabaWsServerQuery implements Runnable
 
         if (noservices)
         {
-          jws2Discoverer.addUrlwithnoservices(jwsservers);
+          jws2Discoverer.addUrlwithnoservices(jwsserver);
         }
       }
       else
       {
-        jws2Discoverer.addInvalidServiceUrl(jwsservers);
-        Cache.log.info("Ignoring invalid Jws2 service url " + jwsservers);
+        jws2Discoverer.addInvalidServiceUrl(jwsserver);
+        Cache.log.info("Ignoring invalid Jws2 service url " + jwsserver);
       }
     } catch (Exception e)
     {
       e.printStackTrace();
       Cache.log.warn("Exception when discovering Jws2 services.", e);
-      jws2Discoverer.addInvalidServiceUrl(jwsservers);
+      jws2Discoverer.addInvalidServiceUrl(jwsserver);
     } catch (Error e)
     {
       Cache.log.error("Exception when discovering Jws2 services.", e);
-      jws2Discoverer.addInvalidServiceUrl(jwsservers);
+      jws2Discoverer.addInvalidServiceUrl(jwsserver);
     }
     running = false;
   }
 
+  /**
+   * Check if the URL is valid and responding.
+   * 
+   * @return
+   */
+  private boolean isValidUrl(String server)
+  {
+    // return Jws2Client.validURL(jwsserver); // checks syntax only
+    boolean result = false;
+    if (server != null) {
+      try {
+        URL url = new URL(server);
+        url.openStream().close();
+        result = true;
+      } catch (MalformedURLException e)
+      {
+        System.err.println("Invalid server URL: " + server);
+        result = false;
+      } catch (IOException e)
+      {
+        System.err.println("Error connecting to server: " + server + ": "
+                + e.toString());
+        result = false;
+      }
+    }
+    return result;
+  }
+
 }
index 910b749..a111d68 100644 (file)
@@ -34,6 +34,8 @@ import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -60,9 +62,48 @@ import compbio.ws.client.Services;
  */
 public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
 {
-  private java.beans.PropertyChangeSupport changeSupport = new java.beans.PropertyChangeSupport(
+  public static final String COMPBIO_JABAWS = "http://www.compbio.dundee.ac.uk/jabaws";
+
+  /*
+   * the .jalview_properties entry for JWS2 URLS
+   */
+  final static String JWS2HOSTURLS = "JWS2HOSTURLS";
+
+  /*
+   * Singleton instance
+   */
+  private static Jws2Discoverer discoverer;
+
+  /*
+   * Override for testing only
+   */
+  private static List<String> testUrls = null;
+
+  // preferred url has precedence over others
+  private String preferredUrl;
+
+  private PropertyChangeSupport changeSupport = new PropertyChangeSupport(
           this);
 
+  Vector<String> invalidServiceUrls = null, urlsWithoutServices = null,
+          validServiceUrls = null;
+
+  boolean running = false, aborted = false;
+
+  Thread oldthread = null;
+
+  /**
+   * holds list of services.
+   */
+  protected Vector<Jws2Instance> services;
+
+  /**
+   * Private constructor enforces use of singleton via getDiscoverer()
+   */
+  private Jws2Discoverer()
+  {
+  }
+
   /**
    * change listeners are notified of "services" property changes
    * 
@@ -87,8 +128,6 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     changeSupport.removePropertyChangeListener(listener);
   }
 
-  boolean running = false, aborted = false;
-
   /**
    * @return the aborted
    */
@@ -104,10 +143,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
   public void setAborted(boolean aborted)
   {
     this.aborted = aborted;
-  }
-
-  Thread oldthread = null;
 
+  }
   public void run()
   {
 
@@ -135,7 +172,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
 
     // first set up exclusion list if needed
     final Set<String> ignoredServices = new HashSet<String>();
-    for (String ignored : jalview.bin.Cache.getDefault(
+    for (String ignored : Cache.getDefault(
             "IGNORED_JABAWS_SERVICETYPES", "")
             .split("\\|"))
     {
@@ -176,9 +213,9 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     ArrayList<String> svctypes = new ArrayList<String>();
 
     List<JabaWsServerQuery> qrys = new ArrayList<JabaWsServerQuery>();
-    for (final String jwsservers : getServiceUrls())
+    for (final String jwsserver : getServiceUrls())
     {
-      JabaWsServerQuery squery = new JabaWsServerQuery(this, jwsservers);
+      JabaWsServerQuery squery = new JabaWsServerQuery(this, jwsserver);
       if (svctypes.size() == 0)
       {
         // TODO: remove this ugly hack to get Canonical JABA service ordering
@@ -233,7 +270,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
         Jws2Instance[] svcs = new Jws2Instance[services.size()];
         int[] spos = new int[services.size()];
         int ipos = 0;
-        Vector svcUrls = getServiceUrls();
+        List<String> svcUrls = getServiceUrls();
         for (Jws2Instance svc : services)
         {
           svcs[ipos] = svc;
@@ -290,11 +327,6 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
   }
 
   /**
-   * holds list of services.
-   */
-  protected Vector<Jws2Instance> services;
-
-  /**
    * attach all available web services to the appropriate submenu in the given
    * JMenu
    */
@@ -545,7 +577,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
   {
     if (args.length > 0)
     {
-      testUrls = new Vector<String>();
+      testUrls = new ArrayList<String>();
       for (String url : args)
       {
         testUrls.add(url);
@@ -592,8 +624,11 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     }
   }
 
-  private static Jws2Discoverer discoverer;
-
+  /**
+   * Returns the singleton instance of this class.
+   * 
+   * @return
+   */
   public static Jws2Discoverer getDiscoverer()
   {
     if (discoverer == null)
@@ -605,7 +640,6 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
 
   public boolean hasServices()
   {
-    // TODO Auto-generated method stub
     return !running && services != null && services.size() > 0;
   }
 
@@ -614,24 +648,19 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     return running;
   }
 
-  /**
-   * the jalview .properties entry for JWS2 URLS
-   */
-  final static String JWS2HOSTURLS = "JWS2HOSTURLS";
-
-  public static void setServiceUrls(Vector<String> urls)
+  public void setServiceUrls(List<String> wsUrls)
   {
-    if (urls != null)
+    if (wsUrls != null && !wsUrls.isEmpty())
     {
-      StringBuffer urlbuffer = new StringBuffer();
+      StringBuilder urls = new StringBuilder(128);
       String sep = "";
-      for (String url : urls)
+      for (String url : wsUrls)
       {
-        urlbuffer.append(sep);
-        urlbuffer.append(url);
+        urls.append(sep);
+        urls.append(url);
         sep = ",";
       }
-      Cache.setProperty(JWS2HOSTURLS, urlbuffer.toString());
+      Cache.setProperty(JWS2HOSTURLS, urls.toString());
     }
     else
     {
@@ -639,18 +668,27 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     }
   }
 
-  private static Vector<String> testUrls = null;
-
-  public static Vector<String> getServiceUrls()
+  /**
+   * Returns web service URLs, in the order in which they should be tried (or an
+   * empty list).
+   * 
+   * @return
+   */
+  public List<String> getServiceUrls()
   {
     if (testUrls != null)
     {
       // return test urls, if there are any, instead of touching cache
       return testUrls;
     }
-    String surls = Cache.getDefault(JWS2HOSTURLS,
-            "http://www.compbio.dundee.ac.uk/jabaws");
-    Vector<String> urls = new Vector<String>();
+    List<String> urls = new ArrayList<String>();
+
+    if (this.preferredUrl != null)
+    {
+      urls.add(preferredUrl);
+    }
+
+    String surls = Cache.getDefault(JWS2HOSTURLS, COMPBIO_JABAWS);
     try
     {
       StringTokenizer st = new StringTokenizer(surls, ",");
@@ -659,40 +697,37 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
         String url = null;
         try
         {
-          java.net.URL u = new java.net.URL(url = st.nextToken());
+          url = st.nextToken();
+          new URL(url);
           if (!urls.contains(url))
           {
             urls.add(url);
           }
           else
           {
-            jalview.bin.Cache.log.info("Ignoring duplicate url in "
+            Cache.log.info("Ignoring duplicate url " + url + " in "
                     + JWS2HOSTURLS + " list");
           }
-        } catch (Exception ex)
+        } catch (MalformedURLException ex)
         {
-          jalview.bin.Cache.log
+          Cache.log
                   .warn("Problem whilst trying to make a URL from '"
                           + ((url != null) ? url : "<null>") + "'");
-          jalview.bin.Cache.log
+          Cache.log
                   .warn("This was probably due to a malformed comma separated list"
                           + " in the "
                           + JWS2HOSTURLS
                           + " entry of $(HOME)/.jalview_properties)");
-          jalview.bin.Cache.log.debug("Exception was ", ex);
+          Cache.log.debug("Exception was ", ex);
         }
       }
     } catch (Exception ex)
     {
-      jalview.bin.Cache.log.warn(
+      Cache.log.warn(
               "Error parsing comma separated list of urls in "
                       + JWS2HOSTURLS + " preference.", ex);
     }
-    if (urls.size() >= 0)
-    {
-      return urls;
-    }
-    return null;
+    return urls;
   }
 
   public Vector<Jws2Instance> getServices()
@@ -750,9 +785,6 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     return thr;
   }
 
-  Vector<String> invalidServiceUrls = null, urlsWithoutServices = null,
-          validServiceUrls = null;
-
   /**
    * @return the invalidServiceUrls
    */
@@ -865,7 +897,9 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
       return 1;
     }
     if (urlsWithoutServices != null && urlsWithoutServices.contains(url))
+    {
       return 0;
+    }
     if (invalidServiceUrls != null && invalidServiceUrls.contains(url))
     {
       return -1;
@@ -979,4 +1013,21 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
   {
     setPreferredServiceFor(null, serviceType, serviceAction, selectedServer);
   }
+
+  /**
+   * Set a URL to try before any others. For use with command-line parameter to
+   * configure a local Jabaws installation without the need to add to property
+   * files.
+   * 
+   * @param value
+   * @throws MalformedURLException
+   */
+  public void setPreferredUrl(String value) throws MalformedURLException
+  {
+    if (value != null && value.trim().length() > 0)
+    {
+      new URL(value);
+      preferredUrl = value;
+    }
+  }
 }
index 9ddc69a..09a6d8d 100644 (file)
  */
 package jalview.ws.jws2;
 
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentView;
+import jalview.gui.AlignFrame;
+import jalview.gui.Desktop;
+import jalview.gui.JvSwingUtils;
+import jalview.util.MessageManager;
+import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.WsParamSetI;
+
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
 import java.util.List;
 
-import javax.swing.*;
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.ToolTipManager;
 
-import jalview.datamodel.*;
-import jalview.gui.*;
 import compbio.data.msa.MsaWS;
 import compbio.metadata.Argument;
-import jalview.util.MessageManager;
-import jalview.ws.jws2.jabaws2.Jws2Instance;
-import jalview.ws.params.WsParamSetI;
 
 /**
  * DOCUMENT ME!
@@ -98,20 +107,23 @@ public class MsaWSClient extends Jws2Client
     if (!(sh.service instanceof MsaWS))
     {
       // redundant at mo - but may change
-      JOptionPane
-              .showMessageDialog(
-                      Desktop.desktop,
-                      MessageManager.formatMessage("label.service_called_is_not_msa_service", new String[]{sh.serviceType}),
-                      MessageManager.getString("label.internal_jalview_error"), JOptionPane.WARNING_MESSAGE);
+      JOptionPane.showMessageDialog(Desktop.desktop, MessageManager
+              .formatMessage("label.service_called_is_not_msa_service",
+                      new String[]
+                      { sh.serviceType }), MessageManager
+              .getString("label.internal_jalview_error"),
+              JOptionPane.WARNING_MESSAGE);
 
       return;
     }
     server = (MsaWS) sh.service;
     if ((wsInfo = setWebService(sh, false)) == null)
     {
-      JOptionPane.showMessageDialog(Desktop.desktop,
-                 MessageManager.formatMessage("label.msa_service_is_unknown", new String[]{sh.serviceType}),
-                 MessageManager.getString("label.internal_jalview_error"), JOptionPane.WARNING_MESSAGE);
+      JOptionPane.showMessageDialog(Desktop.desktop, MessageManager
+              .formatMessage("label.msa_service_is_unknown", new String[]
+              { sh.serviceType }), MessageManager
+              .getString("label.internal_jalview_error"),
+              JOptionPane.WARNING_MESSAGE);
 
       return;
     }
@@ -273,13 +285,39 @@ public class MsaWSClient extends Jws2Client
                   "label.run_with_preset_params", new String[]
                   { calcName }));
 
+          final int showToolTipFor = ToolTipManager.sharedInstance()
+                  .getDismissDelay();
           for (final WsParamSetI preset : presets)
           {
             final JMenuItem methodR = new JMenuItem(preset.getName());
-            methodR.setToolTipText(JvSwingUtils.wrapTooltip(true, "<p><strong>"
-                            + (preset.isModifiable() ? MessageManager.getString("label.user_preset")
-                                    : MessageManager.getString("label.service_preset")) + "</strong><br/>"
-                            + preset.getDescription() + "</p>"));
+            final int QUICK_TOOLTIP = 1500;
+            // JAL-1582 shorten tooltip display time in these menu items as
+            // they can obscure other options
+            methodR.addMouseListener(new MouseAdapter()
+            {
+              @Override
+              public void mouseEntered(MouseEvent e)
+              {
+                ToolTipManager.sharedInstance().setDismissDelay(
+                        QUICK_TOOLTIP);
+              }
+
+              @Override
+              public void mouseExited(MouseEvent e)
+              {
+                ToolTipManager.sharedInstance().setDismissDelay(showToolTipFor);
+              }
+
+            });
+            methodR.setToolTipText(JvSwingUtils.wrapTooltip(
+                    true,
+                    "<p><strong>"
+                            + (preset.isModifiable() ? MessageManager
+                                    .getString("label.user_preset")
+                                    : MessageManager
+                                            .getString("label.service_preset"))
+                            + "</strong><br/>" + preset.getDescription()
+                            + "</p>"));
             methodR.addActionListener(new ActionListener()
             {
               public void actionPerformed(ActionEvent e)
diff --git a/test/jalview/commands/EditCommandTest.java b/test/jalview/commands/EditCommandTest.java
new file mode 100644 (file)
index 0000000..fc821b9
--- /dev/null
@@ -0,0 +1,232 @@
+package jalview.commands;
+
+import static org.junit.Assert.assertEquals;
+import jalview.commands.EditCommand.Action;
+import jalview.commands.EditCommand.Edit;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Unit tests for EditCommand
+ * 
+ * @author gmcarstairs
+ *
+ */
+public class EditCommandTest
+{
+
+  private EditCommand testee;
+
+  private SequenceI[] seqs;
+
+  private Alignment al;
+
+  @Before
+  public void setUp()
+  {
+    testee = new EditCommand();
+    seqs = new SequenceI[4];
+    seqs[0] = new Sequence("seq0", "abcdefghjk");
+    seqs[1] = new Sequence("seq1", "fghjklmnopq");
+    seqs[2] = new Sequence("seq2", "qrstuvwxyz");
+    seqs[3] = new Sequence("seq3", "1234567890");
+    al = new Alignment(seqs);
+    al.setGapCharacter('?');
+  }
+
+  /**
+   * Test inserting gap characters
+   */
+  @Test
+  public void testAppendEdit_insertGap()
+  {
+    // set a non-standard gap character to prove it is actually used
+    testee.appendEdit(Action.INSERT_GAP, seqs, 4, 3, al, true);
+    assertEquals("abcd???efghjk", seqs[0].getSequenceAsString());
+    assertEquals("fghj???klmnopq", seqs[1].getSequenceAsString());
+    assertEquals("qrst???uvwxyz", seqs[2].getSequenceAsString());
+    assertEquals("1234???567890", seqs[3].getSequenceAsString());
+
+    // todo: test for handling out of range positions?
+  }
+
+  /**
+   * Test deleting characters from sequences. Note the deleteGap() action does
+   * not check that only gap characters are being removed.
+   */
+  @Test
+  public void testAppendEdit_deleteGap()
+  {
+    testee.appendEdit(Action.DELETE_GAP, seqs, 4, 3, al, true);
+    assertEquals("abcdhjk", seqs[0].getSequenceAsString());
+    assertEquals("fghjnopq", seqs[1].getSequenceAsString());
+    assertEquals("qrstxyz", seqs[2].getSequenceAsString());
+    assertEquals("1234890", seqs[3].getSequenceAsString());
+  }
+
+  /**
+   * Test a cut action. The command should store the cut characters to support
+   * undo.
+   */
+  @Test
+  public void testCut()
+  {
+    Edit ec = testee.new Edit(Action.CUT, seqs, 4, 3, al);
+    testee.cut(ec, new AlignmentI[]
+    { al });
+    assertEquals("abcdhjk", seqs[0].getSequenceAsString());
+    assertEquals("fghjnopq", seqs[1].getSequenceAsString());
+    assertEquals("qrstxyz", seqs[2].getSequenceAsString());
+    assertEquals("1234890", seqs[3].getSequenceAsString());
+
+    assertEquals("efg", new String(ec.string[0]));
+    assertEquals("klm", new String(ec.string[1]));
+    assertEquals("uvw", new String(ec.string[2]));
+    assertEquals("567", new String(ec.string[3]));
+    // TODO: case where whole sequence is deleted as nothing left; etc
+  }
+
+  /**
+   * Test a Paste action, where this adds sequences to an alignment.
+   */
+  @Test
+  @Ignore
+  // TODO fix so it works
+  public void testPaste_addToAlignment()
+  {
+    SequenceI[] newSeqs = new SequenceI[2];
+    newSeqs[0] = new Sequence("newseq0", "ACEFKL");
+    newSeqs[1] = new Sequence("newseq1", "JWMPDH");
+
+    Edit ec = testee.new Edit(Action.PASTE, newSeqs, 0, al.getWidth(), al);
+    testee.paste(ec, new AlignmentI[]
+    { al });
+    assertEquals(6, al.getSequences().size());
+    assertEquals("1234567890", seqs[3].getSequenceAsString());
+    assertEquals("ACEFKL", seqs[4].getSequenceAsString());
+    assertEquals("JWMPDH", seqs[5].getSequenceAsString());
+  }
+
+  /**
+   * Test insertGap followed by undo command
+   */
+  @Test
+  public void testUndo_insertGap()
+  {
+    // Edit ec = testee.new Edit(Action.INSERT_GAP, seqs, 4, 3, '?');
+    testee.appendEdit(Action.INSERT_GAP, seqs, 4, 3, al, true);
+    // check something changed
+    assertEquals("abcd???efghjk", seqs[0].getSequenceAsString());
+    testee.undoCommand(new AlignmentI[]
+    { al });
+    assertEquals("abcdefghjk", seqs[0].getSequenceAsString());
+    assertEquals("fghjklmnopq", seqs[1].getSequenceAsString());
+    assertEquals("qrstuvwxyz", seqs[2].getSequenceAsString());
+    assertEquals("1234567890", seqs[3].getSequenceAsString());
+  }
+
+  /**
+   * Test deleteGap followed by undo command
+   */
+  @Test
+  public void testUndo_deleteGap()
+  {
+    testee.appendEdit(Action.DELETE_GAP, seqs, 4, 3, al, true);
+    // check something changed
+    assertEquals("abcdhjk", seqs[0].getSequenceAsString());
+    testee.undoCommand(new AlignmentI[]
+    { al });
+    // deleteGap doesn't 'remember' deleted characters, only gaps get put back
+    assertEquals("abcd???hjk", seqs[0].getSequenceAsString());
+    assertEquals("fghj???nopq", seqs[1].getSequenceAsString());
+    assertEquals("qrst???xyz", seqs[2].getSequenceAsString());
+    assertEquals("1234???890", seqs[3].getSequenceAsString());
+  }
+
+  /**
+   * Test several commands followed by an undo command
+   */
+  @Test
+  public void testUndo_multipleCommands()
+  {
+    // delete positions 3/4/5 (counting from 1)
+    testee.appendEdit(Action.DELETE_GAP, seqs, 2, 3, al, true);
+    assertEquals("abfghjk", seqs[0].getSequenceAsString());
+    assertEquals("1267890", seqs[3].getSequenceAsString());
+
+    // insert 2 gaps after the second residue
+    testee.appendEdit(Action.INSERT_GAP, seqs, 2, 2, al, true);
+    assertEquals("ab??fghjk", seqs[0].getSequenceAsString());
+    assertEquals("12??67890", seqs[3].getSequenceAsString());
+
+    // delete positions 4/5/6
+    testee.appendEdit(Action.DELETE_GAP, seqs, 3, 3, al, true);
+    assertEquals("ab?hjk", seqs[0].getSequenceAsString());
+    assertEquals("12?890", seqs[3].getSequenceAsString());
+
+    // undo edit commands
+    testee.undoCommand(new AlignmentI[]
+    { al });
+    assertEquals("ab?????hjk", seqs[0].getSequenceAsString());
+    assertEquals("12?????890", seqs[3].getSequenceAsString());
+  }
+
+  /**
+   * Unit test for JAL-1594 bug: click and drag sequence right to insert gaps -
+   * undo did not remove them all.
+   */
+  @Test
+  public void testUndo_multipleInsertGaps()
+  {
+    testee.appendEdit(Action.INSERT_GAP, seqs, 4, 1, al, true);
+    testee.appendEdit(Action.INSERT_GAP, seqs, 5, 1, al, true);
+    testee.appendEdit(Action.INSERT_GAP, seqs, 6, 1, al, true);
+
+    // undo edit commands
+    testee.undoCommand(new AlignmentI[]
+    { al });
+    assertEquals("abcdefghjk", seqs[0].getSequenceAsString());
+    assertEquals("1234567890", seqs[3].getSequenceAsString());
+
+  }
+
+  /**
+   * Test cut followed by undo command
+   */
+  @Test
+  public void testUndo_cut()
+  {
+    testee.appendEdit(Action.CUT, seqs, 4, 3, al, true);
+    // check something changed
+    assertEquals("abcdhjk", seqs[0].getSequenceAsString());
+    testee.undoCommand(new AlignmentI[]
+    { al });
+    assertEquals("abcdefghjk", seqs[0].getSequenceAsString());
+    assertEquals("fghjklmnopq", seqs[1].getSequenceAsString());
+    assertEquals("qrstuvwxyz", seqs[2].getSequenceAsString());
+    assertEquals("1234567890", seqs[3].getSequenceAsString());
+  }
+
+  /**
+   * Test the replace command (used to manually edit a sequence)
+   */
+  @Test
+  public void testReplace()
+  {
+    // seem to need a dataset sequence on the edited sequence here
+    seqs[1].setDatasetSequence(seqs[1]);
+    new EditCommand("", Action.REPLACE, "ZXY", new SequenceI[]
+    { seqs[1] }, 4, 8, al);
+    assertEquals("abcdefghjk", seqs[0].getSequenceAsString());
+    assertEquals("qrstuvwxyz", seqs[2].getSequenceAsString());
+    assertEquals("1234567890", seqs[3].getSequenceAsString());
+    seqs[1] = new Sequence("seq1", "fghjZXYnopq");
+
+  }
+}
diff --git a/test/jalview/gui/HelpTest.java b/test/jalview/gui/HelpTest.java
new file mode 100644 (file)
index 0000000..e4068d7
--- /dev/null
@@ -0,0 +1,32 @@
+package jalview.gui;
+
+import static org.junit.Assert.assertTrue;
+import jalview.gui.Help.HelpId;
+
+import java.net.URL;
+
+import javax.help.HelpSet;
+import javax.help.HelpSetException;
+import javax.help.Map;
+
+import org.junit.Test;
+
+public class HelpTest
+{
+  @Test
+  public void checkHelpTargets() throws HelpSetException
+  {
+    ClassLoader cl = Desktop.class.getClassLoader();
+    URL url = HelpSet.findHelpSet(cl, "help/help"); // $NON-NLS-$
+    HelpSet hs = new HelpSet(cl, url);
+    Map targets = hs.getLocalMap();
+
+    for (HelpId id : HelpId.values())
+    {
+      String target = id.toString();
+      assertTrue("Unmatched target enum: " + target,
+              targets.isValidID(target, hs));
+    }
+
+  }
+}
index 295c3bf..c206323 100644 (file)
@@ -20,7 +20,8 @@
  */
 package jalview.ws.jabaws;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import jalview.ws.jws2.Jws2Discoverer;
 
 import java.util.Vector;
@@ -73,7 +74,7 @@ public class JalviewJabawsTestUtils
         services.add(url);
       }
       ;
-      Jws2Discoverer.setServiceUrls(services);
+      Jws2Discoverer.getDiscoverer().setServiceUrls(services);
     }
     try
     {