Merge branch 'Release_2_8_2_Branch' into
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 8 Oct 2014 11:15:45 +0000 (12:15 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 8 Oct 2014 11:15:45 +0000 (12:15 +0100)
features/JAL-1264_showHideAnnotations

Conflicts:
resources/lang/Messages.properties
src/jalview/datamodel/Alignment.java

21 files changed:
resources/lang/Messages.properties
src/jalview/datamodel/Alignment.java
src/jalview/datamodel/AlignmentI.java
src/jalview/datamodel/AlignmentOrder.java
src/jalview/datamodel/AnnotatedCollectionI.java
src/jalview/datamodel/SequenceGroup.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AnnotationChooser.java [new file with mode: 0644]
src/jalview/gui/AnnotationColourChooser.java
src/jalview/gui/Desktop.java
src/jalview/gui/FeatureSettings.java
src/jalview/gui/Finder.java
src/jalview/gui/Help.java [new file with mode: 0644]
src/jalview/gui/IdPanel.java
src/jalview/gui/PopupMenu.java
src/jalview/jbgui/GAlignFrame.java
src/jalview/workers/ConsensusThread.java
src/jalview/workers/ConservationThread.java
src/jalview/workers/StrucConsensusThread.java
test/jalview/gui/AnnotationChooserTest.java [new file with mode: 0644]
test/jalview/ws/jabaws/MinJabawsClientTests.java

index cdbe0f3..b1962e0 100644 (file)
@@ -54,11 +54,12 @@ action.right_justify_alignment = Right Justify Alignment
 action.boxes = Boxes\r
 action.text = Text\r
 action.by_pairwise_id = by Pairwise Identity\r
+action.by_length = by Length\r
 action.by_id = by Id\r
 action.by_length = by Length\r
 action.by_group = by Group\r
 action.remove = Remove\r
-action.remove_redundancy = Remove Redundancy\r
+action.remove_redundancy = Remove Redundancy...\r
 action.pairwise_alignment = Pairwise Alignments...\r
 action.by_rna_helixes = by RNA Helices\r
 action.user_defined = User Defined...\r
@@ -128,10 +129,11 @@ action.deselect_all = Deselect all
 action.invert_selection = Invert selection\r
 action.using_jmol = Using Jmol\r
 action.link = Link\r
-action.group_link = Group Link\r
+action.group_link = Group Links\r
 action.show_chain = Show Chain\r
 action.show_group = Show Group\r
 action.fetch_db_references = Fetch DB References\r
+action.edit = Edit\r
 action.view_flanking_regions = Show flanking regions\r
 label.view_flanking_regions = Show sequence data either side of the subsequences involved in this alignment\r
 label.str = Str:\r
@@ -198,6 +200,9 @@ label.tcoffee_scores = T-Coffee Scores
 label.average_distance_bloslum62 = Average Distance Using BLOSUM62\r
 label.neighbour_blosum62 = Neighbour Joining Using BLOSUM62\r
 label.show_annotations = Show annotations\r
+label.hide_annotations = Hide annotations\r
+label.show_all_annotations = Show all annotations\r
+label.hide_all_annotations = Hide all annotations\r
 label.colour_text = Colour Text\r
 label.show_non_conversed = Show nonconserved\r
 label.overview_window = Overview Window\r
@@ -222,6 +227,7 @@ label.all_columns = All Columns
 label.all_sequences = All Sequences\r
 label.selected_columns = Selected Columns \r
 label.selected_sequences = Selected Sequences\r
+label.except_selected_sequences = All except selected sequences\r
 label.all_but_selected_region = All but Selected Region (Shift+Ctrl+H)\r
 label.selected_region = Selected Region\r
 label.all_sequences_columns = All Sequences and Columns\r
@@ -308,7 +314,7 @@ label.to_file = to File
 label.to_textbox = to Textbox\r
 label.jalview = Jalview\r
 label.csv_spreadsheet = CSV (Spreadsheet)\r
-label.status = Status\r
+label.status =  [Status]\r
 label.channels = Channels\r
 label.channel_title_item_count = {0} ({1})\r
 label.blog_item_published_on_date = {0} {1} \r
@@ -365,7 +371,7 @@ label.enter_label = Enter label
 label.enter_label_for_the_structure = Enter a label for the structure?\r
 label.pdb_entry_is_already_displayed = {0} is already displayed.\nDo you want to re-use this viewer ?\r
 label.map_sequences_to_visible_window = Map Sequences to Visible Window: {0}\r
-label.add_pdbentry_to_view = Do you want to add {0} to the view called\n{1}\n\r
+label.add_pdbentry_to_view = Do you want to add {0} to the view called\n'{1}'\n\r
 label.align_to_existing_structure_view = Align to existing structure view\r
 label.pdb_entries_couldnt_be_retrieved = The following pdb entries could not be retrieved from the PDB\:\n{0}\nPlease try downloading them manually.\r
 label.couldnt_load_file = Couldn't load file\r
@@ -378,7 +384,7 @@ label.you_can_only_edit_or_remove_local_das_sources = You can only edit or remov
 label.public_das_source = Public DAS source - not editable\r
 label.input_alignment_from_url = Input Alignment From URL\r
 label.input_alignment = Input Alignment\r
-label.couldnt_import_as_vamsas_session = Couldn't import {0} as a new vamsas session.\r
+label.couldnt_import_as_vamsas_session = Couldn't import '{0}' as a new vamsas session.\r
 label.vamsas_document_import_failed = Vamsas Document Import Failed\r
 label.couldnt_locate = Couldn't locate {0}\r
 label.url_not_found = URL not found\r
@@ -455,8 +461,8 @@ label.settings_for_type = Settings for {0}
 label.view_full_application = View in Full Application\r
 label.load_associated_tree = Load Associated Tree ...\r
 label.load_features_annotations = Load Features/Annotations ...\r
-label.export_features = Export Features\r
-label.export_annotations = Export Annotations\r
+label.export_features = Export Features ...\r
+label.export_annotations = Export Annotations ...\r
 label.jalview_copy = Copy (Jalview Only)\r
 label.jalview_cut = Cut (Jalview Only)\r
 label.to_upper_case = To Upper Case\r
@@ -464,7 +470,6 @@ label.to_lower_case = To Lower Case
 label.toggle_case = Toggle Case\r
 label.edit_name_description = Edit Name/Description ...\r
 label.create_sequence_feature = Create Sequence Feature ...\r
-label.edit_sequence = Edit Sequence\r
 label.edit_sequences = Edit Sequences\r
 label.sequence_details = Sequence Details\r
 label.jmol_help = Jmol Help\r
@@ -495,7 +500,7 @@ label.select_colour_maximum_value = Select Colour for Maximum Value
 label.open_new_jmol_view_with_all_structures_associated_current_selection_superimpose_using_alignment = Open a new Jmol view with all structures associated with the current selection and superimpose them using the alignment.\r
 label.open_url_param = Open URL {0}\r
 label.open_url_seqs_param = Open URL ({0}..) ({1} seqs)\r
-label.load_pdb_file_associate_with_sequence = Load a PDB file and associate it with sequence {0}\r
+label.load_pdb_file_associate_with_sequence = Load a PDB file and associate it with sequence '{0}'\r
 label.reveal_hidden_columns = Reveal Hidden Columns with Right Mouse Button\r
 label.dark_colour = Dark Colour\r
 label.light_colour = Light Colour\r
@@ -531,7 +536,6 @@ label.collect_garbage = Collect Garbage
 label.show_memory_usage = Show Memory Usage\r
 label.show_java_console = Show Java Console\r
 label.show_jalview_news = Show Jalview News\r
-label.take_snapshot = Take snapshot\r
 label.monospaced_fonts_faster_to_render = Monospaced fonts are faster to render\r
 label.anti_alias_fonts = Anti-alias Fonts (Slower to render)\r
 label.monospaced_font= Monospaced\r
@@ -728,399 +732,23 @@ label.invalid_font = Invalid Font
 label.separate_multiple_accession_ids = Separate multiple accession ids with semi colon ";"\r
 label.replace_commas_semicolons = Replace commas with semi-colons\r
 label.parsing_failed_syntax_errors_shown_below_param = Parsing failed. Syntax errors shown below {0}\r
-label.parsing_failed_unrecoverable_exception_thrown_param = \nParsing failed. An unrecoverable exception was thrown\:\n {0}\r
+label.parsing_failed_unrecoverable_exception_thrown_param = \nParsing failed. An unrecoverable exception was thrown:\n {0}\r
 label.example_query_param = Example query: {0}\r
 label.enter_value_increase_conservation_visibility = Enter value to increase conservation visibility\r
 label.enter_percentage_identity_above_which_colour_residues = Enter % identity above which to colour residues\r
-label.wswublast_client_credits = To display sequence features an exact Uniprot id with 100% sequence identity match must be entered.\nIn order to display these features, try changing the names of your sequences to the ids suggested below.\n\nRunning WSWUBlast at EBI.\nPlease quote Pillai S., Silventoinen V., Kallio K., Senger M., Sobhany S., Tate J., Velankar S., Golovin A., Henrick K., Rice P., Stoehr P., Lopez R.\nSOAP-based services provided by the European Bioinformatics Institute.\nNucleic Acids Res. 33(1)\:W25-W28 (2005));\r
+label.wswublast_client_credits = To display sequence features an exact Uniprot id with 100% sequence identity match must be entered.\nIn order to display these features, try changing the names of your sequences to the ids suggested below.\n\nRunning WSWUBlast at EBI.\nPlease quote Pillai S., Silventoinen V., Kallio K., Senger M., Sobhany S., Tate J., Velankar S., Golovin A., Henrick K., Rice P., Stoehr P., Lopez R.\nSOAP-based services provided by the European Bioinformatics Institute.\nNucleic Acids Res. 33(1):W25-W28 (2005));\r
 label.blasting_for_unidentified_sequence = BLASTing for unidentified sequences
 label.select_columns_containing = Select columns containing\r
 label.select_columns_not_containing = Select columns that do not contain\r
 option.trim_retrieved_seqs = Trim retrieved sequences\r
 label.trim_retrieved_sequences = When the reference sequence is longer than the sequence that you are working with, only keep the relevant subsequences.\r
-label.use_sequence_id_1 = Use $SEQUENCE_ID$ or $SEQUENCE_ID=/<regex>/=$\r
-label.use_sequence_id_2 = \nto embed sequence id in URL\r
-label.ws_parameters_for = Parameters for {0}\r
-label.switch_server = Switch server\r
-label.open_jabaws_web_page = Opens the JABAWS server's homepage in web browser\r
-label.choose_jabaws_server = Choose a server for running this service\r
-label.services_at = Services at {0}\r
-label.rest_client_submit = {0} using {1}\r
-label.fetch_retrieve_from =Retrieve from {0}</html>\r
-label.fetch_retrieve_from_all_sources = Retrieve from all {0} sources in {1}<br>First is :{2}<html> \r
-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>\r
-label.opt_and_params_further_details = see further details by right-clicking\r
-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> \r
-label.opt_and_params_show_brief_desc = <html>Click to show brief description<br></html>\r
-label.adjusts_width_generated_eps_png = <html>Adjusts the width of the generated EPS or PNG file to ensure even the longest sequence ID or annotation label is displayed</html>\r
-label.manually_specify_width_left_column = <html>Manually specify the width of the left hand column where sequence IDs and annotation labels will be rendered in exported alignment figures. This setting will be ignored if 'Automatically set ID width' is set</html>\r
-label.job_created_when_checked = <html>When checked, a job is created for every sequence in the current selection.</html>\r
-label.when_checked_job_visible_region_and_results = <html>When checked, a single job is created for the visible region and results mapped back onto their location in the alignment. Otherwise, a job would be created for every contiguous region visible in the alignment or current selection (e.g. a multiple alignment).</html>\r
-label.flat_file_representation = <html>Flat file representation of this rest service using the Really Simple Bioinformatics Service formalism</html>\r
-label.result_of_parsing_rsbs = <html>Results of parsing the RSBS representation</html>\r
-label.user_preset = User Preset\r
-label.service_preset = Service Preset\r
-label.run_with_preset = Run {0} with preset\r
-label.view_service_doc_url = <html>View <a href="{0}">{1}</a></html>\r
-label.submit_sequence = <html>Submit {0} {1} {2} {3} to<br/>{4}</html>\r
-action.by_title_param = by {0}\r
-label.alignment = Alignment\r
-label.secondary_structure_prediction = Secondary Structure Prediction\r
-label.sequence_database_search = Sequence Database Search\r
-label.analysis = Analysis\r
-label.protein_disorder = Protein Disorder \r
-label.source_from_db_source = Sources from {0}\r
-label.from_msname = from {0}\r
-label.superpose_with = Superpose with ...\r
-action.do = Do\r
-label.scale_label_to_column = Scale Label to Column\r
-label.add_new_row = Add New Row\r
-label.edit_label_description = Edit Label/Description\r
-label.hide_row = Hide This Row\r
-label.delete_row = Delete This Row\r
-label.show_all_hidden_rows = Show All Hidden Rows\r
-label.export_annotation = Export Annotation\r
-label.copy_consensus_sequence = Copy Consensus Sequence\r
-label.helix = Helix\r
-label.sheet = Sheet\r
-label.rna_helix = RNA Helix\r
-label.remove_annotation = Remove Annotation\r
-label.colour_by = Colour by...\r
-label.muscle_multiple_protein_sequence_alignment = Muscle Multiple Protein Sequence Alignment\r
-label.mafft_multiple_sequence_alignment = MAFFT Multiple Sequence Alignment\r
-label.clustalw_multiple_sequence_alignment = ClustalW Multiple Sequence Alignment\r
-label.jnet_secondary_structure_prediction = JNet Secondary Structure Prediction\r
-label.multiharmony = Multi-Harmony\r
-label.unable_start_web_service_analysis = Unable to start web service analysis\r
-label.job_couldnt_be_started_check_input = The Job couldn't be started. Please check your input, and the Jalview console for any warning messages.\r
-label.prompt_each_time = Prompt each time\r
-label.use_source = Use Source\r
-label.couldnt_save_project = Couldn't save project\r
-label.error_whilst_saving_current_state_to = Error whilst saving current state to {0}\r
-label.error_whilst_loading_project_from = Error whilst loading project from {0}\r
-label.couldnt_load_project = Couldn't load project\r
-label.pca_sequences_not_aligned = The sequences must be aligned before calculating PCA.\nTry using the Pad function in the edit menu,\nor one of the multiple sequence alignment web services.\r
-label.invalid_name_preset_exists = Invalid name - preset already exists.\r
-label.invalid_name = Invalid name\r
-label.set_proxy_settings = Please set up your proxy settings in the 'Connections' tab of the Preferences window\r
-label.proxy_authorization_failed = Proxy Authorization Failed\r
-label.internal_jalview_error = Internal Jalview Error\r
-label.secondary_structure_prediction_service_couldnt_be_located = The Secondary Structure Prediction Service named {0} at {1} couldn't be located.\r
-label.service_called_is_not_msa_service = The Service called \n{0}\nis not a \nMultiple Sequence Alignment Service\!\r
-label.msa_service_is_unknown = The Multiple Sequence Alignment Service named {0} is unknown\r
-label.service_called_is_not_seq_search_service = The Service called \n{0}\nis not a \nSequence Search Service\!\r
-label.seq_search_service_is_unknown = The Sequence Search Service named {0} is unknown\r
-label.feature_type = Feature Type\r
-label.display = Display\r
-label.service_url = Service URL\r
-label.copied_sequences = Copied sequences\r
-label.cut_sequences = Cut Sequences\r
-label.conservation_colour_increment = Conservation Colour Increment ({0})\r
-label.percentage_identity_thereshold = Percentage Identity Thereshold ({0})\r
-label.error_unsupported_owwner_user_colour_scheme = Unsupported owner for User Colour scheme dialog\r
-label.save_alignment_to_file = Save Alignment to file\r
-label.save_features_to_file = Save Features to File\r
-label.save_annotation_to_file = Save Annotation to File\r
-label.no_features_on_alignment = No features found on alignment\r
-label.save_pdb_file = Save PDB File\r
-label.save_text_to_file = Save Text to File\r
-label.save_state = Save State\r
-label.restore_state = Restore State\r
-label.saving_jalview_project = Saving jalview project {0}\r
-label.loading_jalview_project = Loading jalview project {0}\r
-label.save_vamsas_document_archive = Save Vamsas Document Archive\r
-label.saving_vamsas_doc = Saving VAMSAS Document to {0}\r
-label.load_feature_colours = Load Feature Colours\r
-label.save_feature_colours = Save Feature Colour Scheme\r
-label.dataset_for = {0} Dataset for {1}\r
-label.select_startup_file = Select startup file\r
-label.select_default_browser = Select default web browser\r
-label.save_tree_as_newick = Save tree as newick file\r
-label.create_eps_from_tree = Create EPS file from tree\r
-label.create_png_from_tree = Create PNG image from tree\r
-label.save_colour_scheme = Save colour scheme\r
-label.edit_params_for = Edit parameters for {0}\r
-label.choose_filename_for_param_file = Choose a filename for this parameter file\r
-label.save_as_html = Save as HTML\r
-label.recently_opened = Recently Opened\r
-label.blasting_for_unidentified_sequence_jobs_running = BLASTing for unidentified sequences - {0}  jobs running.\r
-label.tree_from = Tree from {0}\r
-label.webservice_job_title = {0} using {1}\r
-label.select_visible_region_of = selected {0} region of {1}\r
-label.visible = Visible\r
-label.select_unselect_visible_regions_from = select and unselected {0} regions from {1}\r
-label.visible_region_of = visible region of\r
-label.webservice_job_title_on = {0} using {1} on {2}\r
-label.updating_vamsas_session = Updating vamsas session\r
-label.loading_file = Loading File: {0}\r
-label.edit_params = Edit {0}\r
-error.not_implemented = Not implemented\r
-error.no_such_method_as_clone1_for = No such method as clone1 for {0}\r
-error.null_from_clone1 = Null from clone1!\r
-error.implementation_error_sortbyfeature = Implementation Error - sortByFeature method must be one of FEATURE_SCORE, FEATURE_LABEL or FEATURE_DENSITY.\r
-error.not_yet_implemented = Not yet implemented\r
-error.unknown_type_dna_or_pep = Unknown Type {0} - dna or pep are the only allowed values.\r
-error.implementation_error_dont_know_thereshold_annotationcolourgradient = Implementation error: don't know about threshold setting for current AnnotationColourGradient.\r
-error.implementation_error_embeddedpopup_not_null = Implementation error - embeddedPopup must be non-null\r
-error.invalid_colour_for_mycheckbox = Invalid color for MyCheckBox\r
-error.implementation_error_unrecognised_render_object_for_features_type = Implementation Error: Unrecognised render object {0} for features of type {1}\r
-error.implementation_error_unsupported_feature_colour_object = Implementation error: Unsupported feature colour object.\r
-error.invalid_separator_parameter = Invalid separator parameter - must be non-zero length\r
-error.alignment_cigararray_not_implemented = Alignment(CigarArray) not yet implemented\r
-error.weak_sequencei_equivalence_not_yet_implemented = Weak sequenceI equivalence not yet implemented.\r
-error.implementation_error_can_only_make_alignmnet_from_cigararray = Implementation Error - can only make an alignment view from a CigarArray of sequences.\r
-error.empty_view_cannot_be_updated = empty view cannot be updated.\r
-error.mismatch_between_number_of_sequences_in_block = Mismatch between number of sequences in block {0} ({1}) and the original view ({2})\r
-error.padding_not_yet_implemented = Padding not yet implemented\r
-error.mismatch_between_visible_blocks_to_update_and_number_of_contigs_in_view = Mismatch between visible blocks to update and number of contigs in view (contigs=0,blocks={0})\r
-error.unknown_seq_cigar_operation = Unknown SeqCigar operation {0}\r
-error.implementation_bug_parse_cigar_string = Implementation bug in parseCigarString\r
-error.implementation_error_invalid_operation_string = Implementation error. Invalid operation string.\r
-error.invalid_range_string = Invalid range string (must be zero or positive number)\r
-error.implementation_error_delete_range_out_of_bounds = Implementation Error: deleteRange out of bounds: start must be non-negative and less than end.\r
-error.implementation_error = Implementation error\r
-error.implementation_error_unknown_operation = Implementation Error! Unknown operation {0}\r
-error.implementation_error_unexpected_null_from_get_sequence_and_deletions = Implementation Error - unexpected null from getSequenceAndDeletions\r
-error.implementation_error_set_seq_null = Implementation Error - _setSeq(null,...)\r
-error.implementation_error_s = Implementation Error: _s= {0}\r
-error.implementation_error_seqcigar_possible = SeqCigar: Possible implementation error: sequence is longer than dataset sequence\r
-error.implmentation_bug_seq_null = Implementation Bug. Null seq\r
-error.implementation_bug_cigar_operation_list_range_list = Implementation Bug. Cigar Operation list!= range list\r
-error.not_yet_implemented_cigar_object_from_cigar_string = NOT YET Implemented: Constructing a Cigar object from a cigar string and a gapped sequence.\r
-error.implementation_bug_cigar_operation = Implementation Bug. Cigar Operation {0} {1} not one of {2}, {3}, or {4}.\r
-error.implementation_error_for_new_cigar = Implementation error for new Cigar(SequenceI)\r
-error.implementation_error_cigar_seq_no_operations = Implementation error: {0}th sequence Cigar has no operations.\r
-error.implementation_error_jmol_getting_data = Implementation error - Jmol seems to be still working on getting its data - report at http://issues.jalview.org/browse/JAL-1016\r
-error.implementation_error_no_pdbentry_from_index = Implementation error - no corresponding pdbentry (for index {0}) to add sequences mappings to\r
-error.jmol_version_not_compatible_with_jalview_version = Jmol version {0} is not compatible with this version of Jalview. Report this problem at issues.jalview.org\r
-error.not_implemented_remove = Remove: Not implemented\r
-error.not_implemented_clone = Clone: Not implemented\r
-error.implementation_error_chimera_getting_data = Implementation error - Chimera seems to be still working on getting its data - report at http://issues.jalview.org/browse/JAL-1016\r
-error.call_setprogressbar_before_registering_handler = call setProgressBar before registering the progress bar's handler.\r
-label.cancelled_params = Cancelled {0}\r
-error.implementation_error_cannot_show_view_alignment_frame = Implementation error: cannot show a view from another alignment in an AlignFrame.\r
-error.implementation_error_dont_know_about_thereshold_setting = Implementation error: don't know about threshold setting for current AnnotationColourGradient.\r
-error.eps_generation_not_implemented = EPS Generation not yet implemented\r
-error.png_generation_not_implemented = PNG Generation not yet implemented\r
-error.try_join_vamsas_session_another = Trying to join a vamsas session when another is already connected\r
-error.invalid_vamsas_session_id = Invalid vamsas session id\r
-error.implementation_error_cannot_create_groovyshell = Implementation Error. Cannot create groovyShell without Groovy on the classpath!\r
-label.groovy_support_failed = Jalview Groovy Support Failed\r
-label.couldnt_create_groovy_shell = Couldn't create the groovy Shell. Check the error log for the details of what went wrong.\r
-error.unsupported_version_calcIdparam = Unsupported Version for calcIdparam {0}\r
-error.implementation_error_cant_reorder_tree = Implementation Error: Can't reorder this tree. Not DefaultMutableTreeNode.\r
-error.invalid_value_for_option = Invalid value {0} for option {1}\r
-error.implementation_error_cannot_import_vamsas_doc = Implementation Error - cannot import existing vamsas document into an existing session, Yet!\r
-label.vamsas_doc_couldnt_be_opened_as_new_session = VAMSAS Document could not be opened as a new session - please choose another\r
-error.implementation_error_vamsas_operation_not_init = Impementation error! Vamsas Operations when client not initialised and connected\r
-error.jalview_no_connected_vamsas_session = Jalview not connected to Vamsas session\r
-error.implementation_error_cannot_recover_vamsas_object_mappings = IMPLEMENTATION ERROR: Cannot recover vamsas object mappings - no backup was made\r
-error.setstatus_called_non_existent_job_pane = setStatus called for non-existent job pane {0}\r
-error.implementation_error_cannot_find_marshaller_for_param_set =Implementation error: Can't find a marshaller for the parameter set\r
-error.implementation_error_old_jalview_object_not_bound =IMPLEMENTATION ERROR: old jalview object is not bound ! ({0})\r
-error.implementation_error_vamsas_doc_class_should_bind_to_type = Implementation Error: Vamsas Document Class {0} should bind to a {1} (found a {2})\r
-error.implementation_error_jalview_class_should_bind_to_type = Implementation Error: Jalview Class {0} should bind to a {1} (found a {2})\r
-error.invalid_vamsas_rangetype_cannot_resolve_lists = Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!\r
-error.implementation_error_maplist_is_null = Implementation error. MapList is null for initMapType.\r
-error.implementation_error_cannot_have_null_alignment = Implementation error: Cannot have null alignment property key\r
-error.implementation_error_null_fileparse = Implementation error. Null FileParse in copy constructor\r
-error.implementation_error_cannot_map_alignment_sequences = IMPLEMENTATION ERROR: Cannot map an alignment of sequences from different datasets into a single alignment in the vamsas document.\r
-error.implementation_error_cannot_duplicate_colour_scheme = Serious implementation error: cannot duplicate colourscheme {0}\r
-error.implementation_error_structure_selection_manager_null = Implementation error. Structure selection manager's context is 'null'\r
-exception.ssm_context_is_null = SSM context is null\r
-error.idstring_seqstrings_only_one_per_sequence = idstrings and seqstrings contain one string each per sequence\r
-error.cannot_have_mixed_length_replacement_vectors = Cannot have mixed length replacement vectors. Replacement vector for {0} is {1} strings long, and have already seen a {2} length vector.\r
-error.cannot_have_zero_length_vector_replacement_strings = Cannot have zero length vector of replacement strings - either 1 value or n values.\r
-error.implementation_error_multiple_single_sequence_prediction_jobs_not_supported = Implementation Error! Multiple single sequence prediction jobs are not yet supported\r
-error.implementation_error_invalid_msa_index_for_job =Implementation Error! Invalid msaIndex for JPredJob on parent MSA input object!\r
-error.implementation_error_startjob_called = Implementation error - StartJob(JpredJob) called on {0}\r
-error.multiple_jnet_subjob_merge_not_implemented = Multiple JNet subjob merging not yet implemented\r
-label.job_never_ran = Job never ran - input returned to user.\r
-error.implementation_error_minlen_must_be_greater_zero = Implementation error: minlen must be zero or more\r
-error.implementation_error_msawbjob_called = Implementation error - StartJob(MsaWSJob) called on a WSJobInstance {0}\r
-error.implementation_error_cannot_attach_ws_menu_entry = IMPLEMENTATION ERROR: cannot attach WS Menu Entry without service handle reference!\r
-error.parameter_migration_not_implemented_yet = Parameter migration not implemented yet\r
-error.implementation_error_cannot_set_jaba_option = Implementation error: cannot set Jaba Option to a value outside its allowed value range!\r
-error.implementation_error_valuetype_doesnt_support_jabaws_type = IMPLEMENTATION ERROR: jalview.ws.params.ValueConstrainI.ValueType does not support the JABAWS type : {0}\r
-error.cannot_create_jabaws_param_set = Cannot create a JabaWSParamSet from non-JabaWS parameters\r
-error.cannot_set_arguments_to_jabaws_param_set = Cannot set arguments to a JabaWSParamSet that are not JabaWS arguments\r
-error.implementation_error_runner_config_not_available = Implementation Error: Runner Config not available for a JABAWS service of type {0} ({1})\r
-error.implementation_error_cannot_handle_jaba_param = Implementation Error: Cannot handle Jaba parameter object {0}\r
-error.implementation_error_attempt_to_delete_service_preset = Implementation error: Attempt to delete a service preset!\r
-error.implementation_error_cannot_locate_oldname_presetname = Implementation error: Can't locate either oldname ({0}) or presetName ({1}in the datastore!"\r
-error.implementation_error_jabaws_param_set_only_handled_by = Implementation error: JabaWsParamSets can only be handled by JabaParamStore\r
-error.cannot_set_source_file_for = Cannot set source file for {0}\r
-error.mismatch_service_instance_preset = Probable mismatch between service instance and preset!\r
-error.cannot_set_params_for_ws_preset = Cannot set Parameters for a Jaba Web service's preset\r
-error.implementation_error_can_only_instantiate_jaba_param_sets = Implementation error: Can only instantiate Jaba parameter sets\r
-error.no_aacon_service_found = No AACon service found\r
-error.implementation_error_couldnt_copy_value_constraint = Implementation error: could not copy ValueConstrain!\r
-error.couldnt_encode_as_utf8 = Couldn't encode {0} as UTF-8.\r
-error.tree_inputtype_not_yet_implemented = Tree InputType not yet implemented\r
-error.implementation_error_need_to_have_httpresponse = Implementation Error: need to have an HttpResponse to process\r
-error.dbrefsource_implementation_exception =DBRefSource Implementation Exception\r
-error.implementation_error_dbinstance_must_implement_interface = Implmentation Error - getDbInstances must be given a class that implements jalview.ws.seqfetcher.DbSourceProxy (was given{0})\r
-error.implementation_error_must_init_dbsources =Implementation error. Must initialise dbSources\r
-label.view_controller_toggled_marked = {0} {1} columns {2} containing features of type {3}  across {4} sequence(s)\r
-label.toggled = Toggled\r
-label.marked = Marked\r
-label.not = not\r
-label.no_feature_of_type_found = No features of type {0} found.\r
-label.submission_params = Submission {0}\r
-label.empty_alignment_job = Empty Alignment Job\r
-label.add_new_sbrs_service = Add a new Simple Bioinformatics Rest Service\r
-label.edit_sbrs_entry = Edit Simple Bioinformatics Rest Service entry\r
-label.pca_recalculating = Recalculating PCA\r
-label.pca_calculating = Calculating PCA\r
-label.select_foreground_colour = Choose foreground colour\r
-label.select_colour_for_text = Select Colour for Text\r
-label.adjunst_foreground_text_colour_thereshold = Adjust Foreground Text Colour Threshold\r
-label.select_subtree_colour = Select Sub-Tree Colour\r
-label.create_new_sequence_features = Create New Sequence Feature(s)\r
-label.amend_delete_features = Amend/Delete Features for {0}\r
-exception.out_of_bounds_for_file = Out of bounds for file: i={0}, Final Buffer: i0={1} iend={2}\r
-exception.null_string_given_to_regex_search = Null String Given to Regex.search\r
-exception.null_string_like_given_to_regex_search = Null StringLike Given to Regex.search\r
-exception.null_string_given_to_regex_reverse_search = Null String Given to Regex.reverseSearch\r
-exception.null_string_like_given_to_regex_reverse_search = Null StringLike Given to Regex.reverseSearch\r
-exception.null_string_like_given_to_regex_search_from = Null String Given to Regex.searchFrom\r
-exception.null_string_like_given_to_regex_search_region = Null String Given to Regex.searchRegion\r
-exception.replace_null_regex_pointer = Replacer has null Regex pointer\r
-exception.bad_pattern_to_regex_perl_code = bad pattern to Regex.perlCode: {0}\r
-exception.no_stub_implementation_for_interface = There is no stub implementation for the interface: {0}\r
-exception.cannot_set_endpoint_address_unknown_port = Cannot set Endpoint Address for Unknown Port {0}\r
-exception.querying_matching_opening_parenthesis_for_non_closing_parenthesis = Querying matching opening parenthesis for non-closing parenthesis character {0}\r
-exception.mismatched_unseen_closing_char = Mismatched (unseen) closing character {0}\r
-exception.mismatched_closing_char = Mismatched closing character {0}\r
-exception.mismatched_opening_char = Mismatched opening character {0} at {1}\r
-exception.invalid_datasource_couldnt_obtain_reader = Invalid datasource. Could not obtain Reader\r
-exception.index_value_not_in_range = {0}: Index value {1} not in range [0..{2}]\r
-exception.unterminated_cigar_string = Unterminated cigar string\r
-exception.unexpected_operation_cigar_string_pos = Unexpected operation {0} in cigar string (position {1} in {2}\r
-exception.couldnt_parse_responde_from_annotated3d_server = Couldn't parse response from Annotate3d server\r
-exception.application_test_npe = Application test: throwing an NullPointerException It should arrive at the console\r
-exception.overwriting_vamsas_id_binding = Overwriting vamsas id binding\r
-exception.overwriting_jalview_id_binding = Overwriting jalview id binding\r
-error.implementation_error_unknown_file_format_string = Implementation error: Unknown file format string\r
-exception.failed_to_resolve_gzip_stream = Failed to resolve GZIP stream\r
-exception.problem_opening_file_also_tried = Problem opening {0} (also tried {1}) : {2}\r
-exception.problem_opening_file = Problem opening {0} : {1}\r
-exception.failed_to_read_data_from_source = Failed to read data from source: {0}\r
-exception.no_init_source_stream = Unitialised Source Stream\r
-exception.invalid_source_stream = Invalid Source Stream: {0}\r
-error.implementation_error_reset_called_for_invalid_source = Implementation Error: Reset called for invalid source.\r
-exception.number_of_residues_in_query_sequence_differ_from_prediction = Number of residues in {0} supposed query sequence ({1}\n{2})\ndiffer from number of prediction sites in prediction ({3})\r
-label.mapped = mapped\r
-exception.jpredconcide_entry_has_unexpected_number_of_columns = JPredConcise: Entry ({0}) has an unexpected number of columns\r
-exception.couldnt_parse_concise_annotation_for_prediction = Couldn't parse concise annotation for prediction profile.\n{0}\r
-exception.newfile = NewickFile\: {0}\n\r
-label.no_tree_read_in = No Tree read in\r
-exception.rnaml_couldnt_access_datasource = Couldn't access datasource ({0})\r
-exception.ranml_couldnt_process_data = Couldn't process data as RNAML file ({0})\r
-exception.ranml_invalid_file = Invalid RNAML file ({0})\r
-exception.ranml_problem_parsing_data = Problem parsing data as RNAML ({0})\r
-exception.pfam_no_sequences_found = No sequences found (PFAM input)\r
-exception.stockholm_invalid_format = This file is not in valid STOCKHOLM format: First line does not contain '# STOCKHOLM'\r
-exception.couldnt_parse_sequence_line = Could not parse sequence line: {0}\r
-exception.error_parsing_line = Error parsing {0}\r
-exception.unknown_annotation_detected = Unknown annotation detected: {0} {1}\r
-exception.couldnt_store_sequence_mappings = Couldn't store sequence mappings for {0}\r
-exception.matrix_too_many_iteration = Too many iterations in {0} (max is {1})\r
-exception.browser_not_found = Exception in finding browser: {0}\r
-exception.browser_unable_to_locate = Unable to locate browser: {0}\r
-exception.invocation_target_exception_creating_aedesc = InvocationTargetException while creating AEDesc: {0}\r
-exception.illegal_access_building_apple_evt= IllegalAccessException while building AppleEvent: {0}\r
-exception.instantiation_creating_aedesc = InstantiationException while creating AEDesc: {0}\r
-exception.unable_to_launch_url = Unable to launch URL: {0}\r
-exception.unable_to_create_internet_config = Unable to create an Internet Config instance: {0}\r
-exception.invocation_target_calling_url = InvocationTargetException while calling openURL: {0}\r
-exception.illegal_access_calling_url = IllegalAccessException while calling openURL: {0}\r
-exception.interrupted_launching_browser = InterruptedException while launching browser: {0}\r
-exception.das_source_doesnt_support_sequence_command = Source {0} does not support the sequence command.\r
-exception.invalid_das_source = Invalid das source: {0}\r
-exception.ebiembl_retrieval_failed_on = EBI EMBL XML retrieval failed on {0}:{1}\r
-label.no_embl_record_found = # No EMBL record retrieved for {0}:{1}\r
-label.embl_successfully_parsed = # Successfully parsed the {0} queries into an Alignment\r
-exception.no_pdb_records_for_chain = No PDB Records for {0} chain {1}\r
-exception.unexpected_handling_rnaml_translation_for_pdb = Unexpected exception when handling RNAML translation of PDB data\r
-exception.couldnt_recover_sequence_properties_for_alignment = Couldn't recover sequence properties for alignment\r
-exception.unknown_format_for_file = Unknown format {0} for file \: \n{1}\r
-label.remove_gaps = Remove Gaps\r
-exception.couldnt_recover_sequence_props_for_jnet_query = Couldn't recover sequence properties for JNet Query sequence!\r
-exception.server_timeout_try_later = Server timed out - try again later\n\r
-exception.web_service_returned_null_try_later= Server at {0} returned null object, it probably cannot be contacted. Try again later.\r
-exception.cannot_contact_service_endpoint_at = Cannot contact service endpoint at {0}\r
-error.implementation_error_cannot_find_service_url_in_given_set = Implementation error: Cannot find service url in the given url set!\r
-error.implementation_error_cannot_find_service_url_in_given_set_param_store = Implementation error: Cannot find service url in the given url set for this service parameter store ({0}}\r
-exception.jobsubmission_invalid_params_set = Invalid parameter set. Check Jalview implementation\r
-exception.notvaliddata_group_contains_less_than_min_seqs = Group contains less than {0} sequences.\r
-exception.outofmemory_loading_pdb_file = Out of memory loading PDB File\r
-exception.eps_coudnt_write_output_file = Could not write to the output file: {0}\r
-exception.eps_method_not_supported = Method not currently supported by EpsGraphics2D version {0}\r
-exception.eps_unable_to_get_inverse_matrix = Unable to get inverse of matrix: {0}\r
-warn.job_cannot_be_cancelled_close_window = This job cannot be cancelled.\nJust close the window.\r
-warn.service_not_supported = Service not supported!\r
-warn.input_is_too_big = Input is too big!\r
-warn.invalid_job_param_set = Invalid job parameter set!\r
-info.job_couldnt_be_run_server_doesnt_support_program = Job could not be run because the server doesn't support this program.\n{0}\r
-info.job_couldnt_be_run_exceeded_hard_limit = Job could not be run because it exceeded a hard limit on the server.\n{0}\r
-info.job_couldnt_be_run_incorrect_param_setting = Job could not be run because some of the parameter settings are not supported by the server.\n{0}\nPlease check to make sure you have used the correct parameter set for this service\!\n\r
-info.no_jobs_ran = No jobs ran\r
-info.failed_to_submit_prediction = Failed to submit the prediction\:\n{0} {1}\r
-info.invalid_jnet_job_result_data ={0}\n{1}\nInvalid JNet job result data\!\n{2}\r
-info.failed_to_submit_sequences_for_alignment = Failed to submit sequences for alignment.\nIt is most likely that there is a problem with the server.\nJust close the window\n\r
-info.alignment_object_method_notes = \nAlignment Object Method Notes\n\r
-info.server_exception = \n{0} Server exception\!\n{1}\r
-status.processing_commandline_args = Processing commandline arguments...\r
-status.das_features_being_retrived = DAS features being retrieved...\r
-status.searching_for_sequences_from = Searching for sequences from {0}\r
-status.finished_searching_for_sequences_from = Finished searching for sequences from {0}\r
-label.eps_file = EPS file\r
-label.png_image = PNG image\r
-status.saving_file = Saving {0}\r
-status.export_complete = Export complete.\r
-status.fetching_pdb = Fetching PDB {0}\r
-status.refreshing_news = Refreshing news\r
-status.importing_vamsas_session_from = Importing VAMSAS session from {0}\r
-status.opening_params = Opening {0}\r
-status.waiting_sequence_database_fetchers_init = Waiting for Sequence Database Fetchers to initialise\r
-status.init_sequence_database_fetchers = Initialising Sequence Database Fetchers\r
-status.fetching_sequence_queries_from = Fetching {0} sequence queries from {1}\r
-status.finshed_querying = Finished querying\r
-status.parsing_results = Parsing results.\r
-status.processing = Processing...\r
-status.refreshing_web_service_menus = Refreshing Web Service Menus\r
-status.collecting_job_results = Collecting job results.\r
-status.fetching_das_sequence_features = Fetching DAS Sequence Features\r
-status.no_das_sources_active = No DAS Sources Active\r
-status.das_feature_fetching_cancelled = DAS Feature Fetching Cancelled\r
-status.das_feature_fetching_complete = DAS Feature Fetching Complete\r
-status.fetching_db_refs = Fetching db refs\r
-label.font_doesnt_have_letters_defined = Font doesn't have letters defined\nso cannot be used\nwith alignment data\r
-label.error_loading_file_params = Error loading file {0}\r
-label.error_loading_jalview_file = Error loading Jalview file\r
-warn.out_of_memory_when_action = Out of memory when {0}\!\!\nSee help files for increasing Java Virtual Machine memory.\r
-warn.out_of_memory_loading_file = Out of memory loading file {0}\!\!\nSee help files for increasing Java Virtual Machine memory.\r
-label.out_of_memory = Out of memory\r
-label.invalid_id_column_width = Invalid ID Column width\r
-warn.user_defined_width_requirements = The user defined width for the\nannotation and sequence ID columns\nin exported figures must be\nat least 12 pixels wide.\r
-label.couldnt_create_sequence_fetcher = Couldn't create SequenceFetcher\r
-warn.couldnt_create_sequence_fetcher_client = Could not create the sequence fetcher client. Check error logs for details.\r
-warn.server_didnt_pass_validation = Service did not pass validation.\nCheck the Jalview Console for more details.\r
-warn.url_must_contain = Sequence URL must contain $SEQUENCE_ID$ or a regex $SEQUENCE_ID=/<regex>/=$\r
-info.validate_jabaws_server = Validate JabaWS Server ?\n(Look in console output for results)\r
-label.test_server = Test Server?\r
-info.you_want_jalview_to_find_uniprot_accessions = Do you want Jalview to find\nUniprot Accession ids for given sequence names?\r
-label.find_uniprot_accession_ids = Find Uniprot Accession Ids\r
-label.new_sequence_fetcher = New Sequence Fetcher\r
-label.additional_sequence_fetcher = Additional Sequence Fetcher\r
-label.select_database_retrieval_source = Select Database Retrieval Source\r
-label.overwrite_existing_file = Overwrite existing file?\r
-label.file_already_exists = File exists\r
-label.edit_jabaws_url = Edit JABAWS URL\r
-label.add_jabaws_url = Add new JABAWS URL\r
-label.news_from_jalview = News from http://www.jalview.org\r
-label.cut_paste_alignmen_file = Cut & Paste Alignment File\r
-label.enter_redundancy_thereshold = Enter the redundancy thereshold\r
-label.select_dark_light_set_thereshold = <html><i>Select a dark and light text colour, then set the threshold to<br>switch between colours, based on background colour</i></html>\r
-label.select_feature_colour = Select Feature Colour
\ No newline at end of file
+label.choose_annotations = Choose annotations to show or hide\r
+label.show_selected_annotations = Show selected annotation types\r
+label.hide_selected_annotations = Hide selected annotation types\r
+label.add_reference_annotations = Add reference annotations\r
+label.find = Find\r
+error.invalid_regex = Invalid regular expression\r
+label.invalid_search = Search string invalid\r
+label.find_tip = <html>Search alignment, selection or sequence ids for a subsequence (ignoring gaps).<br>Accepts regular expressions - search Help for 'regex' for details.\r
+label.delete_all = Delete all sequences\r
+warn.delete_all = <html>Deleting all sequences will close the alignment window.<br>Confirm deletion or Cancel.\r
index 5e75725..bfe6406 100755 (executable)
@@ -22,7 +22,12 @@ package jalview.datamodel;
 
 import jalview.util.MessageManager;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
 
 /**
  * Data structure to hold and manipulate a multiple sequence alignment
@@ -1523,4 +1528,32 @@ public class Alignment implements AlignmentI
   {
     return dataset;
   }
+
+  /**
+   * Returns an iterable collection of annotations on this alignment which match
+   * the given criteria.
+   */
+  @Override
+  public Iterable<AlignmentAnnotation> findAnnotation(SequenceI datasequence,
+          String calcId, String label)
+  {
+    List<AlignmentAnnotation> result = new ArrayList<AlignmentAnnotation>();
+    for (AlignmentAnnotation ann : annotations)
+    {
+      // only sequence-linked annotations can qualify (have a datasequence)
+      if (ann.sequenceRef == null)
+      {
+        continue;
+      }
+      boolean matchDatasequence = (ann.sequenceRef.getDatasetSequence() == datasequence);
+      final String annCalcId = ann.getCalcId();
+      boolean matchCalcId = (annCalcId != null && annCalcId.equals(calcId));
+      boolean matchLabel = (ann.label != null && ann.label.equals(label));
+      if (matchDatasequence && matchCalcId && matchLabel)
+      {
+        result.add(ann);
+      }
+    }
+    return result;
+  }
 }
index d141697..c7e30a4 100755 (executable)
@@ -20,7 +20,9 @@
  */
 package jalview.datamodel;
 
-import java.util.*;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
 
 /**
  * Data structure to hold and manipulate a multiple sequence alignment
index a17881e..c0f9ab4 100755 (executable)
@@ -20,8 +20,6 @@
  */
 package jalview.datamodel;
 
-import jalview.util.MessageManager;
-
 import java.util.*;
 
 public class AlignmentOrder
@@ -219,7 +217,7 @@ public class AlignmentOrder
       {
         if (!identity)
         {
-          throw new Error(MessageManager.getString("error.weak_sequencei_equivalence_not_yet_implemented"));
+          throw new Error("Weak sequenceI equivalence not yet implemented.");
         }
         else
         {
@@ -286,7 +284,7 @@ public class AlignmentOrder
         }
         if (!identity)
         {
-          throw new Error(MessageManager.getString("error.weak_sequencei_equivalence_not_yet_implemented"));
+          throw new Error("Weak sequenceI equivalence not yet implemented.");
         }
         else
         {
index 0b4c117..6bd4ab9 100644 (file)
@@ -40,4 +40,21 @@ public interface AnnotatedCollectionI extends SequenceCollectionI
    *         alignment, parent group).
    */
   AnnotatedCollectionI getContext();
+
+  /**
+   * Return an iterable set of any annotations in the collection that match the
+   * provided criteria, i.e.
+   * <ul>
+   * <li>reference the same sequence datasequence</li>
+   * <li>have the same calcId (source of annotation)</li>
+   * <li>have the same label (type of annotation)</li>
+   * </ul>
+   * 
+   * @param datasequence
+   * @param calcId
+   * @param label
+   * @return
+   */
+  Iterable<AlignmentAnnotation> findAnnotation(SequenceI datasequence,
+          String calcId, String label);
 }
index b4cb3b1..f8fd3ee 100755 (executable)
  */
 package jalview.datamodel;
 
-import java.util.*;
+import jalview.analysis.AAFrequency;
+import jalview.analysis.Conservation;
+import jalview.schemes.ColourSchemeI;
+import jalview.schemes.ResidueProperties;
+
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
 import java.util.List;
-
-import java.awt.*;
-
-import jalview.analysis.*;
-import jalview.schemes.*;
+import java.util.Map;
+import java.util.Vector;
 
 /**
  * Collects a set contiguous ranges on a set of sequences
@@ -289,11 +294,13 @@ public class SequenceGroup implements AnnotatedCollectionI
     return eres;
   }
 
+  @Override
   public List<SequenceI> getSequences()
   {
     return sequences;
   }
 
+  @Override
   public List<SequenceI> getSequences(
           Map<SequenceI, SequenceCollectionI> hiddenReps)
   {
@@ -307,7 +314,7 @@ public class SequenceGroup implements AnnotatedCollectionI
       SequenceI seq;
       for (int i = 0; i < sequences.size(); i++)
       {
-        seq = (SequenceI) sequences.elementAt(i);
+        seq = sequences.elementAt(i);
         allSequences.addElement(seq);
         if (hiddenReps.containsKey(seq))
         {
@@ -635,6 +642,7 @@ public class SequenceGroup implements AnnotatedCollectionI
    * 
    * @return the first column selected by this group. Runs from 0<=i<N_cols
    */
+  @Override
   public int getStartRes()
   {
     return startRes;
@@ -644,6 +652,7 @@ public class SequenceGroup implements AnnotatedCollectionI
    * 
    * @return the groups last selected column. Runs from 0<=i<N_cols
    */
+  @Override
   public int getEndRes()
   {
     return endRes;
@@ -689,7 +698,7 @@ public class SequenceGroup implements AnnotatedCollectionI
    */
   public SequenceI getSequenceAt(int i)
   {
-    return (SequenceI) sequences.elementAt(i);
+    return sequences.elementAt(i);
   }
 
   /**
@@ -760,17 +769,18 @@ public class SequenceGroup implements AnnotatedCollectionI
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public int getWidth()
   {
     // MC This needs to get reset when characters are inserted and deleted
     if (sequences.size() > 0)
     {
-      width = ((SequenceI) sequences.elementAt(0)).getLength();
+      width = sequences.elementAt(0).getLength();
     }
 
     for (int i = 1; i < sequences.size(); i++)
     {
-      SequenceI seq = (SequenceI) sequences.elementAt(i);
+      SequenceI seq = sequences.elementAt(i);
 
       if (seq.getLength() > width)
       {
@@ -1211,7 +1221,7 @@ public class SequenceGroup implements AnnotatedCollectionI
     // TODO add in other methods like 'getAlignmentAnnotation(String label),
     // etc'
     ArrayList<AlignmentAnnotation> annot = new ArrayList<AlignmentAnnotation>();
-    for (SequenceI seq : (Vector<SequenceI>) sequences)
+    for (SequenceI seq : sequences)
     {
       AlignmentAnnotation[] aa = seq.getAnnotation();
       if (aa != null)
@@ -1250,6 +1260,27 @@ public class SequenceGroup implements AnnotatedCollectionI
     return aa;
   }
 
+  /**
+   * Answer true if any annotation matches the calcId passed in (if not null).
+   * 
+   * @param calcId
+   * @return
+   */
+  public boolean hasAnnotation(String calcId)
+  {
+    if (calcId != null && !"".equals(calcId))
+    {
+      for (AlignmentAnnotation a : getAlignmentAnnotation())
+      {
+        if (a.getCalcId() == calcId)
+        {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
   public void clear()
   {
     sequences.clear();
@@ -1277,4 +1308,28 @@ public class SequenceGroup implements AnnotatedCollectionI
   {
     return context;
   }
+
+  @Override
+  public Iterable<AlignmentAnnotation> findAnnotation(
+          SequenceI datasequence, String calcId, String label)
+  {
+    List<AlignmentAnnotation> result = new ArrayList<AlignmentAnnotation>();
+    for (AlignmentAnnotation ann : getAlignmentAnnotation())
+    {
+      // only sequence-linked annotations can qualify (have a datasequence)
+      if (ann.sequenceRef == null)
+      {
+        continue;
+      }
+      boolean matchDatasequence = (ann.sequenceRef.getDatasetSequence() == datasequence);
+      final String annCalcId = ann.getCalcId();
+      boolean matchCalcId = (annCalcId != null && annCalcId.equals(calcId));
+      boolean matchLabel = (ann.label != null && ann.label.equals(label));
+      if (matchDatasequence && matchCalcId && matchLabel)
+      {
+        result.add(ann);
+      }
+    }
+    return result;
+  }
 }
index c3d80d1..2f94019 100644 (file)
@@ -334,6 +334,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     setMenusFromViewport(viewport);
     buildSortByAnnotationScoresMenu();
     buildTreeMenu();
+    
     if (viewport.wrapAlignment)
     {
       wrapMenuItem_actionPerformed(null);
@@ -505,14 +506,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         case KeyEvent.VK_F1:
           try
           {
-            ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
-            java.net.URL url = javax.help.HelpSet.findHelpSet(cl,
-                    "help/help");
-            javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
-
-            javax.help.HelpBroker hb = hs.createHelpBroker();
-            hb.setCurrentID("home");
-            hb.setDisplayed(true);
+            Help.showHelpWindow();
           } catch (Exception ex)
           {
             ex.printStackTrace();
@@ -729,6 +723,11 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     scaleLeft.setVisible(av.wrapAlignment);
     scaleRight.setVisible(av.wrapAlignment);
     annotationPanelMenuItem.setState(av.showAnnotation);
+    /*
+     * Show/hide all annotations only enabled if annotation panel is shown
+     */
+    showAllAnnotations.setEnabled(annotationPanelMenuItem.getState());
+    hideAllAnnotations.setEnabled(annotationPanelMenuItem.getState());
     viewBoxesMenuItem.setSelected(av.showBoxes);
     viewTextMenuItem.setSelected(av.showText);
     showNonconservedMenuItem.setSelected(av.getShowUnconserved());
@@ -2178,17 +2177,27 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       return;
     }
 
-    Vector seqs = new Vector();
+    List<SequenceI> seqs = new ArrayList<SequenceI>(sg.getSize());
     SequenceI seq;
     for (int i = 0; i < sg.getSize(); i++)
     {
       seq = sg.getSequenceAt(i);
-      seqs.addElement(seq);
+      seqs.add(seq);
     }
 
-    // If the cut affects all sequences, remove highlighted columns
+    // If the cut affects all sequences, warn, remove highlighted columns
     if (sg.getSize() == viewport.getAlignment().getHeight())
     {
+      int confirm = JOptionPane.showConfirmDialog(this,
+              MessageManager.getString("warn.delete_all"), // $NON-NLS-1$
+              MessageManager.getString("label.delete_all"), // $NON-NLS-1$
+              JOptionPane.OK_CANCEL_OPTION);
+
+      if (confirm == JOptionPane.CANCEL_OPTION
+              || confirm == JOptionPane.CLOSED_OPTION)
+      {
+        return;
+      }
       viewport.getColumnSelection().removeElements(sg.getStartRes(),
               sg.getEndRes() + 1);
     }
@@ -2196,7 +2205,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     SequenceI[] cut = new SequenceI[seqs.size()];
     for (int i = 0; i < seqs.size(); i++)
     {
-      cut[i] = (SequenceI) seqs.elementAt(i);
+      cut[i] = seqs.get(i);
     }
 
     /*
@@ -3033,16 +3042,22 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   }
 
   /**
-   * DOCUMENT ME!
+   * Action on toggle of the 'Show annotations' menu item. This shows or hides
+   * the annotations panel as a whole.
+   * 
+   * The options to show/hide all annotations should be enabled when the panel
+   * is shown, and disabled when the panel is hidden.
    * 
    * @param e
-   *          DOCUMENT ME!
    */
   @Override
   public void annotationPanelMenuItem_actionPerformed(ActionEvent e)
   {
-    viewport.setShowAnnotation(annotationPanelMenuItem.isSelected());
-    alignPanel.setAnnotationVisible(annotationPanelMenuItem.isSelected());
+    final boolean setVisible = annotationPanelMenuItem.isSelected();
+    viewport.setShowAnnotation(setVisible);
+    alignPanel.setAnnotationVisible(setVisible);
+    this.showAllAnnotations.setEnabled(setVisible);
+    this.hideAllAnnotations.setEnabled(setVisible);
   }
 
   @Override
@@ -4021,6 +4036,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           tm.setText(title);//
           tm.addActionListener(new java.awt.event.ActionListener()
           {
+            @Override
             public void actionPerformed(ActionEvent e)
             {
               NewTreePanel(type, (String) pwtype, title);
@@ -5308,6 +5324,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     trimrs.setSelected(Cache.getDefault("TRIM_FETCHED_DATASET_SEQS", true));
     trimrs.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         trimrs.setSelected(trimrs.isSelected());
@@ -5690,6 +5707,22 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       tabbedPane.setSelectedIndex(alignPanels.indexOf(alignmentPanel));
     }
   }
+
+  /**
+   * Action on selection of menu option to Show or Hide all annotations.
+   * 
+   * @param visibile
+   */
+  @Override
+  protected void setAllAnnotationsVisibility(boolean visible)
+  {
+    for (AlignmentAnnotation aa : alignPanel.getAlignment()
+            .getAlignmentAnnotation())
+    {
+      aa.visible = visible;
+    }
+    this.alignPanel.paintAlignment(true);
+  }
 }
 
 class PrintThread extends Thread
diff --git a/src/jalview/gui/AnnotationChooser.java b/src/jalview/gui/AnnotationChooser.java
new file mode 100644 (file)
index 0000000..33c4992
--- /dev/null
@@ -0,0 +1,634 @@
+package jalview.gui;
+
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceGroup;
+import jalview.util.MessageManager;
+
+import java.awt.BorderLayout;
+import java.awt.Checkbox;
+import java.awt.CheckboxGroup;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.swing.JButton;
+import javax.swing.JInternalFrame;
+import javax.swing.JLayeredPane;
+import javax.swing.JPanel;
+
+/**
+ * A panel that allows the user to select which sequence-associated annotation
+ * rows to show or hide.
+ * 
+ * @author gmcarstairs
+ *
+ */
+@SuppressWarnings("serial")
+public class AnnotationChooser extends JPanel
+{
+
+  private static final Font CHECKBOX_FONT = new Font("Serif", Font.BOLD, 12);
+
+  private static final int MY_FRAME_WIDTH = 600;
+
+  private static final int MY_FRAME_HEIGHT = 250;
+
+  private JInternalFrame frame;
+
+  private AlignmentPanel ap;
+
+  private SequenceGroup sg;
+
+  // all annotation rows' original visible state
+  private boolean[] resetState = null;
+
+  // is 'Show' selected?
+  private boolean showSelected;
+
+  // apply settings to selected (or all) sequences?
+  private boolean applyToSelectedSequences;
+
+  // apply settings to unselected (or all) sequences?
+  private boolean applyToUnselectedSequences;
+
+  // currently selected 'annotation type' checkboxes
+  private Map<String, String> selectedTypes = new HashMap<String, String>();
+  
+  /**
+   * Constructor.
+   * 
+   * @param alignPane
+   */
+  public AnnotationChooser(AlignmentPanel alignPane)
+  {
+    super();
+    this.ap = alignPane;
+    this.sg = alignPane.av.getSelectionGroup();
+    saveResetState(alignPane.getAlignment());
+
+    try
+    {
+      jbInit();
+    } catch (Exception ex)
+    {
+      ex.printStackTrace();
+    }
+    showFrame();
+  }
+
+  /**
+   * Save the initial show/hide state of all annotations to allow a Cancel
+   * operation.
+   * 
+   * @param alignment
+   */
+  protected void saveResetState(AlignmentI alignment)
+  {
+    AlignmentAnnotation[] annotations = alignment.getAlignmentAnnotation();
+    final int count = annotations.length;
+    this.resetState = new boolean[count];
+    for (int i = 0; i < count; i++)
+    {
+      this.resetState[i] = annotations[i].visible;
+    }
+  }
+
+  /**
+   * Populate this frame with:
+   * <p>
+   * checkboxes for the types of annotation to show or hide (i.e. any annotation
+   * type shown for any sequence in the whole alignment)
+   * <p>
+   * option to show or hide selected types
+   * <p>
+   * option to show/hide for the currently selected group, or its inverse
+   * <p>
+   * OK and Cancel (reset) buttons
+   */
+  protected void jbInit()
+  {
+    setLayout(new GridLayout(3, 1));
+    add(buildAnnotationTypesPanel());
+    add(buildShowHideOptionsPanel());
+    add(buildActionButtonsPanel());
+    validate();
+  }
+
+  /**
+   * Construct the panel with checkboxes for annotation types.
+   * 
+   * @return
+   */
+  protected JPanel buildAnnotationTypesPanel()
+  {
+    JPanel jp = new JPanel(new FlowLayout(FlowLayout.LEFT));
+
+    List<String> annotationTypes = getAnnotationTypes(
+            this.ap.getAlignment(), true);
+
+    for (final String type : annotationTypes)
+    {
+      final Checkbox check = new Checkbox(type);
+      check.setFont(CHECKBOX_FONT);
+      check.addItemListener(new ItemListener()
+      {
+        @Override
+        public void itemStateChanged(ItemEvent evt)
+        {
+          if (evt.getStateChange() == ItemEvent.SELECTED)
+          {
+            AnnotationChooser.this.selectedTypes.put(type, type);
+          }
+          else
+          {
+            AnnotationChooser.this.selectedTypes.remove(type);
+          }
+          changeTypeSelected_actionPerformed(type);
+        }
+      });
+      jp.add(check);
+    }
+    return jp;
+  }
+
+  /**
+   * Update display when scope (All/Selected sequences/Unselected) is changed.
+   * <p>
+   * Set annotations (with one of the selected types) to the selected Show/Hide
+   * visibility, if they are in the new application scope. Set to the opposite
+   * if outside the scope.
+   * <p>
+   * Note this only affects sequence-specific annotations, others are left
+   * unchanged.
+   */
+  protected void changeApplyTo_actionPerformed()
+  {
+    setAnnotationVisibility(true);
+
+    // copied from AnnotationLabel.actionPerformed (after show/hide row)...
+    // TODO should drive this functionality into AlignmentPanel
+    ap.updateAnnotation();
+    // this.ap.annotationPanel.adjustPanelHeight();
+    // this.ap.alabels.setSize(this.ap.alabels.getSize().width,
+    // this.ap.annotationPanel.getSize().height);
+    // this.ap.validate();
+    this.ap.paintAlignment(true);
+  }
+
+  /**
+   * Update display when an annotation type is selected or deselected.
+   * <p>
+   * If the type is selected, set visibility of annotations of that type which
+   * are in the application scope (all, selected or unselected sequences).
+   * <p>
+   * If the type is unselected, set visibility to the opposite value. That is,
+   * treat select/deselect as a 'toggle' operation.
+   * 
+   * @param type
+   */
+  protected void changeTypeSelected_actionPerformed(String type)
+  {
+    boolean typeSelected = this.selectedTypes.containsKey(type);
+    for (AlignmentAnnotation aa : this.ap.getAlignment()
+            .getAlignmentAnnotation())
+    {
+      if (aa.sequenceRef != null && type.equals(aa.label)
+              && isInActionScope(aa))
+      {
+        aa.visible = typeSelected ? this.showSelected : !this.showSelected;
+      }
+    }
+    ap.updateAnnotation();
+    // // this.ap.annotationPanel.adjustPanelHeight();
+    // this.ap.alabels.setSize(this.ap.alabels.getSize().width,
+    // this.ap.annotationPanel.getSize().height);
+    // this.ap.validate();
+    this.ap.paintAlignment(true);
+  }
+
+  /**
+   * Update display on change of choice of Show or Hide
+   * <p>
+   * For annotations of any selected type, set visibility of annotations of that
+   * type which are in the application scope (all, selected or unselected
+   * sequences).
+   * 
+   * @param type
+   */
+  protected void changeShowHide_actionPerformed()
+  {
+    setAnnotationVisibility(false);
+
+    this.ap.updateAnnotation();
+    // this.ap.annotationPanel.adjustPanelHeight();
+    this.ap.paintAlignment(true);
+  }
+
+  /**
+   * Update visibility flags on annotation rows as per the current user choices.
+   * 
+   * @param updateAllRows
+   */
+  protected void setAnnotationVisibility(boolean updateAllRows)
+  {
+    for (AlignmentAnnotation aa : this.ap.getAlignment()
+            .getAlignmentAnnotation())
+    {
+      if (aa.sequenceRef != null)
+      {
+        setAnnotationVisibility(aa, updateAllRows);
+      }
+    }
+  }
+
+  /**
+   * Determine and set the visibility of the given annotation from the currently
+   * selected options.
+   * <p>
+   * Only update annotations whose type is one of the selected types.
+   * <p>
+   * If its sequence is in the selected application scope
+   * (all/selected/unselected sequences), then we set its visibility according
+   * to the current choice of Show or Hide.
+   * <p>
+   * If force update of all rows is wanted, then set rows not in the sequence
+   * selection scope to the opposite visibility to those in scope.
+   * 
+   * @param aa
+   * @param updateAllRows
+   */
+  protected void setAnnotationVisibility(AlignmentAnnotation aa,
+          boolean updateAllRows)
+  {
+    if (this.selectedTypes.containsKey(aa.label))
+    {
+      if (isInActionScope(aa))
+      {
+        aa.visible = this.showSelected;
+      }
+      else if (updateAllRows)
+      {
+        aa.visible = !this.showSelected;
+      }
+    }
+    // TODO force not visible if associated sequence is hidden?
+    // currently hiding a sequence does not hide its annotation rows
+  }
+
+  /**
+   * Answers true if the annotation falls in the current selection criteria for
+   * show/hide.
+   * <p>
+   * It must be in the sequence selection group (for 'Apply to selection'), or
+   * not in it (for 'Apply except to selection'). No check needed for 'Apply to
+   * all'.
+   * 
+   * @param aa
+   * @return
+   */
+  protected boolean isInActionScope(AlignmentAnnotation aa)
+  {
+    boolean result = false;
+    if (this.applyToSelectedSequences && this.applyToUnselectedSequences)
+    {
+      // we don't care if the annotation's sequence is selected or not
+      result = true;
+    }
+    else if (this.sg == null)
+    {
+      // shouldn't happen - defensive programming
+      result = true;
+    }
+    else if (this.sg.getSequences().contains(aa.sequenceRef))
+    {
+      // annotation is for a member of the selection group
+      result = this.applyToSelectedSequences ? true : false;
+    }
+    else
+    {
+      // annotation is not associated with the selection group
+      result = this.applyToUnselectedSequences ? true : false;
+    }
+    return result;
+  }
+
+  /**
+   * Get annotation 'types' for an alignment, optionally restricted to
+   * sequence-specific annotations only. The label is currently used for 'type'.
+   * 
+   * TODO refactor to helper class. See
+   * AnnotationColourChooser.getAnnotationItems() for another client
+   * 
+   * @param alignment
+   * @param sequenceSpecific
+   * @return
+   */
+  public static List<String> getAnnotationTypes(AlignmentI alignment,
+          boolean sequenceSpecificOnly)
+  {
+    List<String> result = new ArrayList<String>();
+    for (AlignmentAnnotation aa : alignment.getAlignmentAnnotation())
+    {
+      if (!sequenceSpecificOnly || aa.sequenceRef != null)
+      {
+        String label = aa.label;
+        if (!result.contains(label))
+        {
+          result.add(label);
+        }
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Construct the panel with options to:
+   * <p>
+   * show or hide the selected annotation types
+   * <p>
+   * do this for the current selection group or its inverse
+   * 
+   * @return
+   */
+  protected JPanel buildShowHideOptionsPanel()
+  {
+    JPanel jp = new JPanel();
+    jp.setLayout(new BorderLayout());
+
+    JPanel showHideOptions = buildShowHidePanel();
+    jp.add(showHideOptions, BorderLayout.CENTER);
+
+    JPanel applyToOptions = buildApplyToOptionsPanel();
+    jp.add(applyToOptions, BorderLayout.SOUTH);
+
+    return jp;
+  }
+
+  /**
+   * Build a panel with radio buttons options for sequences to apply show/hide
+   * to. Options are all, current selection, all except current selection.
+   * Initial state has 'current selection' selected.
+   * <p>
+   * If the sequence group is null, then we are acting on the whole alignment,
+   * and only 'all sequences' is enabled (and selected).
+   * 
+   * @return
+   */
+  protected JPanel buildApplyToOptionsPanel()
+  {
+    final boolean wholeAlignment = this.sg == null;
+    JPanel applyToOptions = new JPanel(new FlowLayout(FlowLayout.LEFT));
+    CheckboxGroup actingOn = new CheckboxGroup();
+    
+    String forAll = MessageManager.getString("label.all_sequences");
+    final Checkbox allSequences = new Checkbox(forAll, actingOn,
+            wholeAlignment);
+    allSequences.addItemListener(new ItemListener()
+    {
+      @Override
+      public void itemStateChanged(ItemEvent evt)
+      {
+        if (evt.getStateChange() == ItemEvent.SELECTED) {
+          AnnotationChooser.this.setApplyToSelectedSequences(true);
+          AnnotationChooser.this.setApplyToUnselectedSequences(true);
+          AnnotationChooser.this.changeApplyTo_actionPerformed();
+        }
+      }
+    });
+    applyToOptions.add(allSequences);
+    
+    String forSelected = MessageManager
+            .getString("label.selected_sequences");
+    final Checkbox selectedSequences = new Checkbox(forSelected, actingOn,
+            !wholeAlignment);
+    selectedSequences.setEnabled(!wholeAlignment);
+    selectedSequences.addItemListener(new ItemListener()
+    {
+      @Override
+      public void itemStateChanged(ItemEvent evt)
+      {
+        if (evt.getStateChange() == ItemEvent.SELECTED)
+        {
+          AnnotationChooser.this.setApplyToSelectedSequences(true);
+          AnnotationChooser.this.setApplyToUnselectedSequences(false);
+          AnnotationChooser.this.changeApplyTo_actionPerformed();
+        }
+      }
+    });
+    applyToOptions.add(selectedSequences);
+    
+    String exceptSelected = MessageManager
+            .getString("label.except_selected_sequences");
+    final Checkbox unselectedSequences = new Checkbox(exceptSelected, actingOn, false);
+    unselectedSequences.setEnabled(!wholeAlignment);
+    unselectedSequences.addItemListener(new ItemListener()
+    {
+      @Override
+      public void itemStateChanged(ItemEvent evt)
+      {
+        if (evt.getStateChange() == ItemEvent.SELECTED)
+        {
+          AnnotationChooser.this.setApplyToSelectedSequences(false);
+          AnnotationChooser.this.setApplyToUnselectedSequences(true);
+          AnnotationChooser.this.changeApplyTo_actionPerformed();
+        }
+      }
+    });
+    applyToOptions.add(unselectedSequences);
+    
+    // set member variables to match the initial selection state
+    this.applyToSelectedSequences = selectedSequences.getState()
+            || allSequences.getState();
+    this.applyToUnselectedSequences = unselectedSequences.getState()
+            || allSequences.getState();
+
+    return applyToOptions;
+  }
+
+  /**
+   * Build a panel with radio button options to show or hide selected
+   * annotations.
+   * 
+   * @return
+   */
+  protected JPanel buildShowHidePanel()
+  {
+    JPanel showHideOptions = new JPanel(new FlowLayout(FlowLayout.LEFT));
+    CheckboxGroup showOrHide = new CheckboxGroup();
+
+    /*
+     * Radio button 'Show selected annotations' - initially unselected
+     */
+    String showLabel = MessageManager
+            .getString("label.show_selected_annotations");
+    final Checkbox showOption = new Checkbox(showLabel, showOrHide, false);
+    showOption.addItemListener(new ItemListener()
+    {
+      @Override
+      public void itemStateChanged(ItemEvent evt)
+      {
+        if (evt.getStateChange() == ItemEvent.SELECTED) {
+          AnnotationChooser.this.setShowSelected(true);
+          AnnotationChooser.this.changeShowHide_actionPerformed();
+        }
+      }
+    });
+    showHideOptions.add(showOption);
+
+    /*
+     * Radio button 'hide selected annotations'- initially selected
+     */
+    String hideLabel = MessageManager
+            .getString("label.hide_selected_annotations");
+    final Checkbox hideOption = new Checkbox(hideLabel, showOrHide, true);
+    hideOption.addItemListener(new ItemListener()
+    {
+      @Override
+      public void itemStateChanged(ItemEvent evt)
+      {
+        if (evt.getStateChange() == ItemEvent.SELECTED)
+        {
+          AnnotationChooser.this.setShowSelected(false);
+          AnnotationChooser.this.changeShowHide_actionPerformed();
+        }
+      }
+    });
+    showHideOptions.add(hideOption);
+
+    /*
+     * Set member variable to match initial selection state
+     */
+    this.showSelected = showOption.getState();
+
+    return showHideOptions;
+  }
+
+  /**
+   * Construct the panel with OK and Cancel buttons.
+   * 
+   * @return
+   */
+  protected JPanel buildActionButtonsPanel()
+  {
+    JPanel jp = new JPanel();
+    final Font labelFont = JvSwingUtils.getLabelFont();
+    
+    JButton ok = new JButton(MessageManager.getString("action.ok"));
+    ok.setFont(labelFont);
+    ok.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        close_actionPerformed();
+      }
+    });
+    jp.add(ok);
+    
+    JButton cancel = new JButton(MessageManager.getString("action.cancel"));
+    cancel.setFont(labelFont);
+    cancel.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        cancel_actionPerformed();
+      }
+    });
+    jp.add(cancel);
+
+    return jp;
+  }
+
+  /**
+   * On 'Cancel' button, undo any changes.
+   */
+  protected void cancel_actionPerformed()
+  {
+    resetOriginalState();
+    this.ap.repaint();
+    close_actionPerformed();
+  }
+
+  /**
+   * Restore annotation visibility to their state on entry here, and repaint
+   * alignment.
+   */
+  protected void resetOriginalState()
+  {
+    int i = 0;
+    for (AlignmentAnnotation aa : this.ap.getAlignment()
+            .getAlignmentAnnotation())
+    {
+      aa.visible = this.resetState[i++];
+    }
+  }
+
+  /**
+   * On 'Close' button, close the dialog.
+   */
+  protected void close_actionPerformed()
+  {
+    try
+    {
+      this.frame.setClosed(true);
+    } catch (Exception exe)
+    {
+    }
+  }
+
+  /**
+   * Render a frame containing this panel.
+   */
+  private void showFrame()
+  {
+    frame = new JInternalFrame();
+    frame.setContentPane(this);
+    frame.setLayer(JLayeredPane.PALETTE_LAYER);
+    Desktop.addInternalFrame(frame,
+            MessageManager.getString("label.choose_annotations"),
+            MY_FRAME_WIDTH, MY_FRAME_HEIGHT, true);
+  }
+
+  protected void setShowSelected(boolean showSelected)
+  {
+    this.showSelected = showSelected;
+  }
+
+  protected void setApplyToSelectedSequences(
+          boolean applyToSelectedSequences)
+  {
+    this.applyToSelectedSequences = applyToSelectedSequences;
+  }
+
+  protected void setApplyToUnselectedSequences(
+          boolean applyToUnselectedSequences)
+  {
+    this.applyToUnselectedSequences = applyToUnselectedSequences;
+  }
+
+  protected boolean isShowSelected()
+  {
+    return showSelected;
+  }
+
+  protected boolean isApplyToSelectedSequences()
+  {
+    return applyToSelectedSequences;
+  }
+
+  protected boolean isApplyToUnselectedSequences()
+  {
+    return applyToUnselectedSequences;
+  }
+
+}
index 7226eb0..3c552a4 100644 (file)
  */
 package jalview.gui;
 
-import java.util.*;
-
-import java.awt.*;
-import java.awt.event.*;
-
-import javax.swing.*;
-import javax.swing.event.*;
-
-import net.miginfocom.swing.MigLayout;
-
 import jalview.bin.Cache;
-import jalview.datamodel.*;
-import jalview.schemes.*;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.SequenceGroup;
+import jalview.schemes.AnnotationColourGradient;
+import jalview.schemes.ColourSchemeI;
 import jalview.util.MessageManager;
 
+import java.awt.BorderLayout;
+import java.awt.Color;
 import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JColorChooser;
+import javax.swing.JComboBox;
+import javax.swing.JInternalFrame;
+import javax.swing.JLayeredPane;
+import javax.swing.JPanel;
+import javax.swing.JSlider;
+import javax.swing.JTextField;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import net.miginfocom.swing.MigLayout;
 
 public class AnnotationColourChooser extends JPanel
 {
@@ -84,11 +100,12 @@ public class AnnotationColourChooser extends JPanel
 
     slider.addChangeListener(new ChangeListener()
     {
+      @Override
       public void stateChanged(ChangeEvent evt)
       {
         if (!adjusting)
         {
-          thresholdValue.setText(((float) slider.getValue() / 1000f) + "");
+          thresholdValue.setText((slider.getValue() / 1000f) + "");
           valueChanged(!sliderDragging);
         }
       }
@@ -109,6 +126,7 @@ public class AnnotationColourChooser extends JPanel
         super.mouseDragged(e);
       }
 
+      @Override
       public void mouseReleased(MouseEvent evt)
       {
         if (sliderDragging)
@@ -212,7 +230,7 @@ public class AnnotationColourChooser extends JPanel
       if (!list.contains(label))
       {
         anmap[list.size()] = i;
-        list.addElement(label);
+        list.add(label);
 
       }
       else
@@ -220,13 +238,13 @@ public class AnnotationColourChooser extends JPanel
         if (!isSeqAssociated)
         {
           anmap[list.size()] = i;
-          list.addElement(label + "_" + (index++));
+          list.add(label + "_" + (index++));
         }
       }
     }
     seqAssociated.setEnabled(enableSeqAss);
-    annmap = new int[list.size()];
-    System.arraycopy(anmap, 0, annmap, 0, annmap.length);
+    this.annmap = new int[list.size()];
+    System.arraycopy(anmap, 0, this.annmap, 0, this.annmap.length);
     return list;
   }
 
@@ -257,6 +275,7 @@ public class AnnotationColourChooser extends JPanel
     minColour.setToolTipText(MessageManager.getString("label.min_colour"));
     minColour.addMouseListener(new MouseAdapter()
     {
+      @Override
       public void mousePressed(MouseEvent e)
       {
         if (minColour.isEnabled())
@@ -271,6 +290,7 @@ public class AnnotationColourChooser extends JPanel
     maxColour.setToolTipText(MessageManager.getString("label.max_colour"));
     maxColour.addMouseListener(new MouseAdapter()
     {
+      @Override
       public void mousePressed(MouseEvent e)
       {
         if (maxColour.isEnabled())
@@ -283,6 +303,7 @@ public class AnnotationColourChooser extends JPanel
     ok.setText(MessageManager.getString("action.ok"));
     ok.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         ok_actionPerformed(e);
@@ -292,6 +313,7 @@ public class AnnotationColourChooser extends JPanel
     cancel.setText(MessageManager.getString("action.cancel"));
     cancel.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         cancel_actionPerformed(e);
@@ -313,6 +335,7 @@ public class AnnotationColourChooser extends JPanel
 
     annotations.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         annotations_actionPerformed(e);
@@ -320,6 +343,7 @@ public class AnnotationColourChooser extends JPanel
     });
     threshold.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         threshold_actionPerformed(e);
@@ -327,6 +351,7 @@ public class AnnotationColourChooser extends JPanel
     });
     thresholdValue.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         thresholdValue_actionPerformed(e);
@@ -346,6 +371,7 @@ public class AnnotationColourChooser extends JPanel
             .getString("label.use_original_colours"));
     currentColours.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         currentColours_actionPerformed(e);
@@ -357,6 +383,7 @@ public class AnnotationColourChooser extends JPanel
             .getString("label.threshold_minmax"));
     thresholdIsMin.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent actionEvent)
       {
         thresholdIsMin_actionPerformed(actionEvent);
@@ -678,7 +705,7 @@ public class AnnotationColourChooser extends JPanel
     {
       changeColour();
     }
-    currentAnnotation.threshold.value = (float) slider.getValue() / 1000f;
+    currentAnnotation.threshold.value = slider.getValue() / 1000f;
     propagateSeqAssociatedThreshold(updateAllAnnotation);
     ap.paintAlignment(false);
   }
index 123aed2..63f0caa 100644 (file)
@@ -89,9 +89,9 @@ import javax.swing.JPopupMenu;
 import javax.swing.JProgressBar;
 import javax.swing.SwingUtilities;
 import javax.swing.event.HyperlinkEvent;
+import javax.swing.event.HyperlinkEvent.EventType;
 import javax.swing.event.MenuEvent;
 import javax.swing.event.MenuListener;
-import javax.swing.event.HyperlinkEvent.EventType;
 
 /**
  * Jalview Desktop
@@ -317,8 +317,8 @@ public class Desktop extends jalview.jbgui.GDesktop implements
     else
     {
       Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
-      setBounds((int) (screenSize.width - 900) / 2,
-              (int) (screenSize.height - 650) / 2, 900, 650);
+      setBounds((screenSize.width - 900) / 2,
+              (screenSize.height - 650) / 2, 900, 650);
     }
     jconsole = new Console(this, showjconsole);
     // add essential build information
@@ -1183,13 +1183,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
   {
     try
     {
-      ClassLoader cl = jalview.gui.Desktop.class.getClassLoader();
-      java.net.URL url = javax.help.HelpSet.findHelpSet(cl, "help/help");
-      javax.help.HelpSet hs = new javax.help.HelpSet(cl, url);
-
-      javax.help.HelpBroker hb = hs.createHelpBroker();
-      hb.setCurrentID("home");
-      hb.setDisplayed(true);
+      Help.showHelpWindow();
     } catch (Exception ex)
     {
     }
@@ -2364,7 +2358,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements
       throw new Error(MessageManager.getString("error.call_setprogressbar_before_registering_handler"));
     }
     progressBarHandlers.put(new Long(id), handler);
-    final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
+    final JPanel progressPanel = progressBars.get(new Long(id));
     if (handler.canCancel())
     {
       JButton cancel = new JButton(
index 304d352..908eac5 100644 (file)
  */
 package jalview.gui;
 
-import java.io.*;
-import java.util.*;
-import java.util.List;
-import java.awt.*;
-import java.awt.event.*;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-
-import javax.swing.*;
-import javax.swing.event.*;
-import javax.swing.table.*;
-
 import jalview.analysis.AlignmentSorter;
 import jalview.bin.Cache;
 import jalview.commands.OrderCommand;
-import jalview.datamodel.*;
-import jalview.io.*;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.io.JalviewFileChooser;
 import jalview.schemes.AnnotationColourGradient;
 import jalview.schemes.GraduatedColor;
 import jalview.util.MessageManager;
 import jalview.ws.dbsources.das.api.jalviewSourceI;
 
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.GridLayout;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionAdapter;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import javax.swing.AbstractCellEditor;
+import javax.swing.BorderFactory;
+import javax.swing.Icon;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JColorChooser;
+import javax.swing.JDialog;
+import javax.swing.JInternalFrame;
+import javax.swing.JLabel;
+import javax.swing.JLayeredPane;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JScrollPane;
+import javax.swing.JSlider;
+import javax.swing.JTabbedPane;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.SwingConstants;
+import javax.swing.SwingUtilities;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableCellRenderer;
+
 public class FeatureSettings extends JPanel
 {
   DasSourceBrowser dassourceBrowser;
@@ -115,6 +162,19 @@ public class FeatureSettings extends JPanel
                   (String) table.getValueAt(selectedRow, 0));
         }
       }
+
+      // isPopupTrigger fires on mouseReleased on Mac
+      @Override
+      public void mouseReleased(MouseEvent evt)
+      {
+        selectedRow = table.rowAtPoint(evt.getPoint());
+        if (evt.isPopupTrigger())
+        {
+          popupSort(selectedRow, (String) table.getValueAt(selectedRow, 0),
+                  table.getValueAt(selectedRow, 1), fr.minmax, evt.getX(),
+                  evt.getY());
+        }
+      }
     });
 
     table.addMouseMotionListener(new MouseMotionAdapter()
@@ -661,7 +721,7 @@ public class FeatureSettings extends JPanel
                 file), "UTF-8");
 
         jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
-        jucs = (jalview.schemabinding.version2.JalviewUserColours) jucs
+        jucs = jucs
                 .unmarshal(in);
 
         for (int i = jucs.getColourCount() - 1; i >= 0; i--)
@@ -1028,7 +1088,7 @@ public class FeatureSettings extends JPanel
     {
       public void stateChanged(ChangeEvent evt)
       {
-        fr.setTransparency((float) (100 - transparency.getValue()) / 100f);
+        fr.setTransparency((100 - transparency.getValue()) / 100f);
         af.alignPanel.paintAlignment(true);
       }
     });
index bc5f823..8eddc06 100755 (executable)
  */
 package jalview.gui;
 
-import java.util.*;
-import java.awt.event.*;
+import jalview.datamodel.SearchResults;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceI;
+import jalview.jbgui.GFinder;
+import jalview.util.MessageManager;
 
-import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.util.Vector;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
 
-import jalview.datamodel.*;
-import jalview.jbgui.*;
-import jalview.util.MessageManager;
+import javax.swing.JInternalFrame;
+import javax.swing.JLayeredPane;
+import javax.swing.JOptionPane;
 
 /**
- * DOCUMENT ME!
+ * Performs the menu option for searching the alignment, for the next or all
+ * matches. If matches are found, they are highlighted, and the user has the
+ * option to create a new feature on the alignment for the matched positions.
+ * 
+ * Searches can be for a simple base sequence, or may use a regular expression.
+ * Any gaps are ignored.
  * 
  * @author $author$
  * @version $Revision$
  */
 public class Finder extends GFinder
 {
+  private static final int HEIGHT = 110;
+
+  private static final int WIDTH = 340;
+
   AlignViewport av;
 
   AlignmentPanel ap;
@@ -50,14 +65,7 @@ public class Finder extends GFinder
   SearchResults searchResults;
 
   /**
-   * Creates a new Finder object.
-   * 
-   * @param av
-   *          DOCUMENT ME!
-   * @param ap
-   *          DOCUMENT ME!
-   * @param f
-   *          DOCUMENT ME!
+   * Creates a new Finder object with no associated viewport or panel.
    */
   public Finder()
   {
@@ -65,6 +73,13 @@ public class Finder extends GFinder
     focusfixed = false;
   }
 
+  /**
+   * Constructor given an associated viewport and alignment panel. Constructs
+   * and displays an internal frame where the user can enter a search string.
+   * 
+   * @param viewport
+   * @param alignPanel
+   */
   public Finder(AlignViewport viewport, AlignmentPanel alignPanel)
   {
     av = viewport;
@@ -73,16 +88,16 @@ public class Finder extends GFinder
     frame = new JInternalFrame();
     frame.setContentPane(this);
     frame.setLayer(JLayeredPane.PALETTE_LAYER);
-    Desktop.addInternalFrame(frame, "Find", 340, 110);
+    Desktop.addInternalFrame(frame, MessageManager.getString("label.find"),
+            WIDTH, HEIGHT);
 
     textfield.requestFocus();
   }
 
   /**
-   * DOCUMENT ME!
+   * Performs the 'Find Next' action.
    * 
    * @param e
-   *          DOCUMENT ME!
    */
   public void findNext_actionPerformed(ActionEvent e)
   {
@@ -93,10 +108,9 @@ public class Finder extends GFinder
   }
 
   /**
-   * DOCUMENT ME!
+   * Performs the 'Find All' action.
    * 
    * @param e
-   *          DOCUMENT ME!
    */
   public void findAll_actionPerformed(ActionEvent e)
   {
@@ -178,10 +192,10 @@ public class Finder extends GFinder
   }
 
   /**
-   * incrementally search the alignment
+   * Search the alignment for the next or all matches. If 'all matches', a
+   * dialog is shown with the number of sequence ids and subsequences matched.
    * 
    * @param findAll
-   *          true means find all results and raise a dialog box
    */
   void doSearch(boolean findAll)
   {
@@ -189,7 +203,7 @@ public class Finder extends GFinder
 
     String searchString = textfield.getText().trim();
 
-    if (searchString.length() < 1)
+    if (isInvalidSearchString(searchString))
     {
       return;
     }
@@ -269,4 +283,54 @@ public class Finder extends GFinder
     }
 
   }
+
+  /**
+   * Displays an error dialog, and answers false, if the search string is
+   * invalid, else answers true.
+   * 
+   * @param searchString
+   * @return
+   */
+  protected boolean isInvalidSearchString(String searchString)
+  {
+    String error = getSearchValidationError(searchString);
+    if (error == null)
+    {
+      return false;
+    }
+    JOptionPane.showInternalMessageDialog(this, error,
+            MessageManager.getString("label.invalid_search"), // $NON-NLS-1$
+            JOptionPane.ERROR_MESSAGE);
+    return true;
+  }
+
+  /**
+   * Returns an error message string if the search string is invalid, else
+   * returns null.
+   * 
+   * Currently validation is limited to checking the string is not empty, and is
+   * a valid regular expression (simple searches for base sub-sequences will
+   * pass this test). Additional validations may be added in future if the
+   * search syntax is expanded.
+   * 
+   * @param searchString
+   * @return
+   */
+  protected String getSearchValidationError(String searchString)
+  {
+    String error = null;
+    if (searchString == null || searchString.length() == 0)
+    {
+      error = MessageManager.getString("label.invalid_search");
+    }
+    try
+    {
+      Pattern.compile(searchString);
+    } catch (PatternSyntaxException e)
+    {
+      error = MessageManager.getString("error.invalid_regex") + ": "
+              + e.getDescription();
+    }
+    return error;
+  }
 }
diff --git a/src/jalview/gui/Help.java b/src/jalview/gui/Help.java
new file mode 100644 (file)
index 0000000..dac17c0
--- /dev/null
@@ -0,0 +1,55 @@
+package jalview.gui;
+
+import java.net.URL;
+
+import javax.help.HelpBroker;
+import javax.help.HelpSet;
+import javax.help.HelpSetException;
+
+/**
+ * Utility class to show the help documentation window.
+ * 
+ * @author gmcarstairs
+ *
+ */
+public class Help
+{
+
+  private static final long HALF_A_MO = 500; // half a second
+
+  private static long lastOpenedTime = 0L;
+
+  /**
+   * Not instantiable
+   */
+  private Help()
+  {
+
+  }
+
+  /**
+   * Show help text in a new window. But do nothing if within half a second of
+   * the last invocation.
+   * 
+   * This is a workaround for issue JAL-914 - both Desktop and AlignFrame
+   * responding to F1 key, resulting in duplicate help windows opened.
+   * 
+   * @throws HelpSetException
+   */
+  public static void showHelpWindow() throws HelpSetException
+  {
+    long timeNow = System.currentTimeMillis();
+
+    if (timeNow - lastOpenedTime > HALF_A_MO)
+    {
+      lastOpenedTime = timeNow;
+      ClassLoader cl = Desktop.class.getClassLoader();
+      URL url = HelpSet.findHelpSet(cl, "help/help"); // $NON-NLS-$
+      HelpSet hs = new HelpSet(cl, url);
+
+      HelpBroker hb = hs.createHelpBroker();
+      hb.setCurrentID("home");
+      hb.setDisplayed(true);
+    }
+  }
+}
index 39afd2c..6b1109a 100755 (executable)
  */
 package jalview.gui;
 
-import java.awt.*;
-import java.awt.event.*;
-import java.util.List;
-import java.util.Vector;
-
-import javax.swing.*;
-
-import jalview.datamodel.*;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
 import jalview.io.SequenceAnnotationReport;
 import jalview.util.MessageManager;
 import jalview.util.UrlLink;
 
+import java.awt.BorderLayout;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.util.List;
+import java.util.Vector;
+
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+import javax.swing.ToolTipManager;
+
 /**
- * DOCUMENT ME!
+ * This panel hosts alignment sequence ids and responds to mouse clicks on them,
+ * as well as highlighting ids matched by a search from the Find menu.
  * 
  * @author $author$
  * @version $Revision$
@@ -64,9 +75,7 @@ public class IdPanel extends JPanel implements MouseListener,
    * Creates a new IdPanel object.
    * 
    * @param av
-   *          DOCUMENT ME!
    * @param parent
-   *          DOCUMENT ME!
    */
   public IdPanel(AlignViewport av, AlignmentPanel parent)
   {
@@ -84,7 +93,8 @@ public class IdPanel extends JPanel implements MouseListener,
   }
 
   /**
-   * DOCUMENT ME!
+   * Respond to mouse movement by constructing tooltip text for the sequence id
+   * under the mouse.
    * 
    * @param e
    *          DOCUMENT ME!
@@ -97,7 +107,7 @@ public class IdPanel extends JPanel implements MouseListener,
     if (seq > -1 && seq < av.getAlignment().getHeight())
     {
       SequenceI sequence = av.getAlignment().getSequenceAt(seq);
-      StringBuffer tip = new StringBuffer();
+      StringBuffer tip = new StringBuffer(64);
       seqAnnotReport
               .createSequenceAnnotationReport(tip, sequence,
                       av.isShowDbRefs(), av.isShowNpFeats(),
@@ -108,10 +118,10 @@ public class IdPanel extends JPanel implements MouseListener,
   }
 
   /**
-   * DOCUMENT ME!
+   * Responds to a mouse drag by selecting the sequences under the dragged
+   * region.
    * 
    * @param e
-   *          DOCUMENT ME!
    */
   @Override
   public void mouseDragged(MouseEvent e)
@@ -133,6 +143,9 @@ public class IdPanel extends JPanel implements MouseListener,
     alignPanel.paintAlignment(true);
   }
 
+  /**
+   * Response to the mouse wheel by scrolling the alignment panel.
+   */
   @Override
   public void mouseWheelMoved(MouseWheelEvent e)
   {
@@ -142,7 +155,6 @@ public class IdPanel extends JPanel implements MouseListener,
       if (e.isShiftDown())
       {
         alignPanel.scrollRight(true);
-
       }
       else
       {
@@ -163,20 +175,28 @@ public class IdPanel extends JPanel implements MouseListener,
   }
 
   /**
-   * DOCUMENT ME!
+   * Handle a mouse click event. Currently only responds to a double-click. The
+   * action is to try to open a browser window at a URL that searches for the
+   * selected sequence id. The search URL is configured in Preferences |
+   * Connections | URL link from Sequence ID. For example:
+   * 
+   * http://www.ebi.ac.uk/ebisearch/search.ebi?db=allebi&query=$SEQUENCE_ID$
    * 
    * @param e
-   *          DOCUMENT ME!
    */
   @Override
   public void mouseClicked(MouseEvent e)
   {
-    if (e.getClickCount() < 2)
+    /*
+     * Ignore single click. Ignore 'left' click followed by 'right' click (user
+     * selects a row then its pop-up menu).
+     */
+    if (e.getClickCount() < 2 || SwingUtilities.isRightMouseButton(e))
     {
       return;
     }
 
-    java.util.Vector links = Preferences.sequenceURLLinks;
+    Vector links = Preferences.sequenceURLLinks;
     if (links == null || links.size() < 1)
     {
       return;
@@ -231,7 +251,6 @@ public class IdPanel extends JPanel implements MouseListener,
                       MessageManager.getString("label.web_browser_not_found"), JOptionPane.WARNING_MESSAGE);
       ex.printStackTrace();
     }
-
   }
 
   /**
@@ -276,22 +295,29 @@ public class IdPanel extends JPanel implements MouseListener,
   }
 
   /**
-   * DOCUMENT ME!
+   * Respond to a mouse press. Does nothing for (left) double-click as this is
+   * handled by mouseClicked().
+   * 
+   * Right mouse down - construct and show context menu.
+   * 
+   * Ctrl-down or Shift-down - add to or expand current selection group if there
+   * is one.
+   * 
+   * Mouse down - select this sequence.
    * 
    * @param e
-   *          DOCUMENT ME!
    */
   @Override
   public void mousePressed(MouseEvent e)
   {
-    if (e.getClickCount() == 2)
+    if (e.getClickCount() == 2 && SwingUtilities.isLeftMouseButton(e))
     {
       return;
     }
 
     int seq = alignPanel.seqPanel.findSeq(e);
 
-    if (javax.swing.SwingUtilities.isRightMouseButton(e))
+    if (SwingUtilities.isRightMouseButton(e))
     {
       Sequence sq = (Sequence) av.getAlignment().getSequenceAt(seq);
       // build a new links menu based on the current links + any non-positional
@@ -341,10 +367,9 @@ public class IdPanel extends JPanel implements MouseListener,
   }
 
   /**
-   * DOCUMENT ME!
+   * Toggle whether the sequence is part of the current selection group.
    * 
    * @param seq
-   *          DOCUMENT ME!
    */
   void selectSeq(int seq)
   {
@@ -355,12 +380,11 @@ public class IdPanel extends JPanel implements MouseListener,
   }
 
   /**
-   * DOCUMENT ME!
+   * Add contiguous rows of the alignment to the current selection group. Does
+   * nothing if there is no selection group.
    * 
    * @param start
-   *          DOCUMENT ME!
    * @param end
-   *          DOCUMENT ME!
    */
   void selectSeqs(int start, int end)
   {
@@ -392,10 +416,10 @@ public class IdPanel extends JPanel implements MouseListener,
   }
 
   /**
-   * DOCUMENT ME!
+   * Respond to mouse released. Refreshes the display and triggers broadcast of
+   * the new selection group to any listeners.
    * 
    * @param e
-   *          DOCUMENT ME!
    */
   @Override
   public void mouseReleased(MouseEvent e)
@@ -412,10 +436,10 @@ public class IdPanel extends JPanel implements MouseListener,
   }
 
   /**
-   * DOCUMENT ME!
+   * Highlight sequence ids that match the given list, and if necessary scroll
+   * to the start sequence of the list.
    * 
    * @param list
-   *          DOCUMENT ME!
    */
   public void highlightSearchResults(List<SequenceI> list)
   {
index 0957d28..5f6c556 100644 (file)
@@ -25,8 +25,6 @@ import jalview.analysis.Conservation;
 import jalview.commands.ChangeCaseCommand;
 import jalview.commands.EditCommand;
 import jalview.datamodel.AlignmentAnnotation;
-import jalview.datamodel.AlignmentI;
-import jalview.datamodel.AlignmentView;
 import jalview.datamodel.Annotation;
 import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.PDBEntry;
@@ -36,6 +34,7 @@ import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.io.FormatAdapter;
 import jalview.io.SequenceAnnotationReport;
+import jalview.renderer.AnnotationRenderer;
 import jalview.schemes.AnnotationColourGradient;
 import jalview.schemes.Blosum62ColourScheme;
 import jalview.schemes.BuriedColourScheme;
@@ -59,8 +58,14 @@ import jalview.util.UrlLink;
 import java.awt.Color;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Collection;
 import java.util.Hashtable;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Vector;
 
 import javax.swing.ButtonGroup;
@@ -80,6 +85,10 @@ import javax.swing.JRadioButtonMenuItem;
  */
 public class PopupMenu extends JPopupMenu
 {
+  private static final String ALL_ANNOTATIONS = "All";
+
+  private static final String COMMA = ",";
+
   JMenu groupMenu = new JMenu();
 
   JMenuItem groupName = new JMenuItem();
@@ -129,6 +138,8 @@ public class PopupMenu extends JPopupMenu
 
   JMenuItem sequenceSelDetails = new JMenuItem();
 
+  JMenuItem chooseAnnotations = new JMenuItem();
+
   SequenceI sequence;
 
   JMenuItem createGroupMenuItem = new JMenuItem();
@@ -177,6 +188,12 @@ public class PopupMenu extends JPopupMenu
 
   JMenu outputMenu = new JMenu();
 
+  JMenu showAnnotationsMenu = new JMenu();
+
+  JMenu hideAnnotationsMenu = new JMenu();
+
+  JMenuItem addDatasequenceAnnotations = new JMenuItem();
+
   JMenuItem sequenceFeature = new JMenuItem();
 
   JMenuItem textColour = new JMenuItem();
@@ -251,6 +268,7 @@ public class PopupMenu extends JPopupMenu
 
       item.addActionListener(new java.awt.event.ActionListener()
       {
+        @Override
         public void actionPerformed(ActionEvent e)
         {
           outputText_actionPerformed(e);
@@ -260,6 +278,11 @@ public class PopupMenu extends JPopupMenu
       outputMenu.add(item);
     }
 
+    /*
+     * Build menus for annotation types that may be shown or hidden.
+     */
+    buildAnnotationTypesMenus();
+
     try
     {
       jbInit();
@@ -298,7 +321,6 @@ public class PopupMenu extends JPopupMenu
                               ap.av.collateForPDB(new PDBEntry[]
                               { pdb })[0], null, ap);
             }
-
           });
           viewStructureMenu.add(menuItem);
 
@@ -337,6 +359,7 @@ public class PopupMenu extends JPopupMenu
             menuItem.addActionListener(new java.awt.event.ActionListener()
 
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 // System.out.println("1:"+structureLine);
@@ -377,6 +400,7 @@ public class PopupMenu extends JPopupMenu
                       { seq.getName() }));
               menuItem.addActionListener(new java.awt.event.ActionListener()
               {
+                @Override
                 public void actionPerformed(ActionEvent e)
                 {
                   // TODO: VARNA does'nt print gaps in the sequence
@@ -397,6 +421,7 @@ public class PopupMenu extends JPopupMenu
               MessageManager.getString("action.hide_sequences"));
       menuItem.addActionListener(new java.awt.event.ActionListener()
       {
+        @Override
         public void actionPerformed(ActionEvent e)
         {
           hideSequences(false);
@@ -412,6 +437,7 @@ public class PopupMenu extends JPopupMenu
                 { seq.getName() }));
         menuItem.addActionListener(new java.awt.event.ActionListener()
         {
+          @Override
           public void actionPerformed(ActionEvent e)
           {
             hideSequences(true);
@@ -431,6 +457,7 @@ public class PopupMenu extends JPopupMenu
                   MessageManager.getString("action.reveal_sequences"));
           menuItem.addActionListener(new ActionListener()
           {
+            @Override
             public void actionPerformed(ActionEvent e)
             {
               ap.av.showSequence(index);
@@ -452,6 +479,7 @@ public class PopupMenu extends JPopupMenu
                 MessageManager.getString("action.reveal_all"));
         menuItem.addActionListener(new ActionListener()
         {
+          @Override
           public void actionPerformed(ActionEvent e)
           {
             ap.av.showAllHiddenSeqs();
@@ -555,8 +583,7 @@ public class PopupMenu extends JPopupMenu
       SequenceI sqass = null;
       for (SequenceI sq : ap.av.getSequenceSelection())
       {
-        Vector<PDBEntry> pes = (Vector<PDBEntry>) sq.getDatasetSequence()
-                .getPDBId();
+        Vector<PDBEntry> pes = sq.getDatasetSequence().getPDBId();
         if (pes != null && pes.size() > 0)
         {
           reppdb.put(pes.get(0).getId(), pes.get(0));
@@ -770,6 +797,237 @@ public class PopupMenu extends JPopupMenu
     }
   }
 
+  /**
+   * Add annotation types to a 'Show annotations' or 'Hide annotations' menu.
+   * "All" is added first, followed by a separator. Then add any annotation
+   * types associated with the current selection.
+   * <p>
+   * Some annotation rows are always rendered together - these can be identified
+   * by a common graphGroup property > -1. Only one of each group will be marked
+   * as visible (to avoid duplication of the display). For such groups we add a
+   * composite type name, e.g.
+   * <p>
+   * IUPredWS (Long), IUPredWS (Short)
+   */
+  protected void buildAnnotationTypesMenus()
+  {
+    showAnnotationsMenu.removeAll();
+    hideAnnotationsMenu.removeAll();
+    final List<String> all = Arrays.asList(ALL_ANNOTATIONS);
+    addAnnotationTypeToShowHide(showAnnotationsMenu, all, true, true);
+    addAnnotationTypeToShowHide(hideAnnotationsMenu, all, true, false);
+    showAnnotationsMenu.addSeparator();
+    hideAnnotationsMenu.addSeparator();
+
+    final AlignmentAnnotation[] annotations = ap.getAlignment()
+            .getAlignmentAnnotation();
+    BitSet visibleGraphGroups = PopupMenu
+            .getVisibleLineGraphGroups(annotations);
+
+    List<List<String>> shownTypes = new ArrayList<List<String>>();
+    List<List<String>> hiddenTypes = new ArrayList<List<String>>();
+    PopupMenu.getAnnotationTypesForShowHide(shownTypes, hiddenTypes,
+            visibleGraphGroups, annotations, ap.av.getSelectionGroup());
+
+    for (List<String> types : hiddenTypes)
+    {
+      addAnnotationTypeToShowHide(showAnnotationsMenu, types, false, true);
+    }
+
+    for (List<String> types : shownTypes)
+    {
+      addAnnotationTypeToShowHide(hideAnnotationsMenu, types, false, false);
+    }
+  }
+
+  /**
+   * Helper method to populate lists of annotation types for the Show/Hide
+   * Annotations menus. If sequenceGroup is not null, this is restricted to
+   * annotations which are associated with sequences in the selection group.
+   * <p/>
+   * If an annotation row is currently visible, its type (label) is added (once
+   * only per type), to the shownTypes list. If it is currently hidden, it is
+   * added to the hiddenTypesList.
+   * <p/>
+   * For rows that belong to a line graph group, so are always rendered
+   * together:
+   * <ul>
+   * <li>Treat all rows in the group as visible, if at least one of them is</li>
+   * <li>Build a comma-separated label with all the types that belong to the
+   * group</li>
+   * </ul>
+   * 
+   * @param shownTypes
+   * @param hiddenTypes
+   * @param visibleGraphGroups
+   * @param annotations
+   * @param sequenceGroup
+   */
+  public static void getAnnotationTypesForShowHide(
+          List<List<String>> shownTypes, List<List<String>> hiddenTypes,
+          BitSet visibleGraphGroups, AlignmentAnnotation[] annotations,
+          SequenceGroup sequenceGroup)
+  {
+    // lookup table, key = graph group, value = list of types in the group
+    Map<Integer, List<String>> groupLabels = new LinkedHashMap<Integer, List<String>>();
+
+    List<String> addedToShown = new ArrayList<String>();
+    List<String> addedToHidden = new ArrayList<String>();
+
+    for (AlignmentAnnotation aa : annotations)
+    {
+
+      if (sequenceGroup == null
+              || (aa.sequenceRef != null && sequenceGroup.getSequences()
+                      .contains(aa.sequenceRef)))
+      {
+        /*
+         * Build a 'composite label' for types in line graph groups.
+         */
+        final List<String> labelAsList = new ArrayList<String>();
+        labelAsList.add(aa.label);
+        if (aa.graph == AlignmentAnnotation.LINE_GRAPH
+                && aa.graphGroup > -1)
+        {
+          if (groupLabels.containsKey(aa.graphGroup))
+          {
+            if (!groupLabels.get(aa.graphGroup).contains(aa.label))
+            {
+              groupLabels.get(aa.graphGroup).add(aa.label);
+            }
+          }
+          else
+          {
+            groupLabels.put(aa.graphGroup, labelAsList);
+          }
+        }
+        else if (aa.visible && !addedToShown.contains(aa.label))
+        {
+          shownTypes.add(labelAsList);
+          addedToShown.add(aa.label);
+        }
+        else
+        {
+          if (!aa.visible && !addedToHidden.contains(aa.label))
+          {
+            hiddenTypes.add(labelAsList);
+            addedToHidden.add(aa.label);
+          }
+        }
+      }
+    }
+    /*
+     * finally add the 'composite group labels' to the appropriate lists,
+     * depending on whether the group is identified as visible or hidden
+     */
+    for (int group : groupLabels.keySet())
+    {
+      final List<String> groupLabel = groupLabels.get(group);
+      if (visibleGraphGroups.get(group))
+      {
+        if (!shownTypes.contains(groupLabel))
+        {
+          shownTypes.add(groupLabel);
+        }
+      }
+      else if (!hiddenTypes.contains(groupLabel))
+      {
+        hiddenTypes.add(groupLabel);
+      }
+    }
+  }
+
+  /**
+   * Returns a BitSet (possibly empty) of those graphGroups for line graph
+   * annotations, which have at least one member annotation row marked visible.
+   * The logic is that only one row in the group is marked visible, but when it
+   * is drawn, so are all the other rows in the same group.
+   * <p/>
+   * This lookup set allows us to check whether rows marked not visible are in
+   * fact shown.
+   * 
+   * @see AnnotationRenderer#drawComponent
+   * @param annotations
+   * @return
+   */
+  public static BitSet getVisibleLineGraphGroups(
+          AlignmentAnnotation[] annotations)
+  {
+    // todo move to a utility class
+    BitSet result = new BitSet();
+    for (AlignmentAnnotation ann : annotations)
+    {
+      if (ann.graph == AlignmentAnnotation.LINE_GRAPH && ann.visible)
+      {
+        int gg = ann.graphGroup;
+        if (gg > -1)
+        {
+          result.set(gg);
+        }
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Add one annotation type to the 'Show Annotations' or 'Hide Annotations'
+   * menus.
+   * 
+   * @param showOrHideMenu
+   *          the menu to add to
+   * @param types
+   *          the label to add
+   * @param allTypes
+   *          if true this is a special label meaning 'All'
+   * @param actionIsShow
+   *          if true, the select menu item action is to show the annotation
+   *          type, else hide
+   */
+  protected void addAnnotationTypeToShowHide(JMenu showOrHideMenu,
+          final Collection<String> types, final boolean allTypes,
+          final boolean actionIsShow)
+  {
+    String label = types.toString(); // [a, b, c]
+    label = label.substring(1, label.length() - 1);
+    final JMenuItem item = new JMenuItem(label);
+    item.addActionListener(new java.awt.event.ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        showHideAnnotation_actionPerformed(types, allTypes, actionIsShow);
+      }
+    });
+    showOrHideMenu.add(item);
+  }
+
+  /**
+   * Action on selecting a list of annotation type (or the 'all types' values)
+   * to show or hide for the selection.
+   * 
+   * @param types
+   * @param anyType
+   * @param doShow
+   */
+  protected void showHideAnnotation_actionPerformed(
+          Collection<String> types, boolean anyType, boolean doShow)
+  {
+    for (AlignmentAnnotation aa : ap.getAlignment()
+            .getAlignmentAnnotation())
+    {
+      if (anyType || types.contains(aa.label))
+      {
+        if ((aa.sequenceRef != null)
+                && ap.av.getSelectionGroup().getSequences()
+                        .contains(aa.sequenceRef))
+        {
+          aa.visible = doShow;
+        }
+      }
+    }
+    refresh();
+  }
+
   private void buildGroupURLMenu(SequenceGroup sg, Vector groupLinks)
   {
 
@@ -942,11 +1200,13 @@ public class PopupMenu extends JPopupMenu
             { url }));
     item.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         new Thread(new Runnable()
         {
 
+          @Override
           public void run()
           {
             showLink(url);
@@ -982,11 +1242,13 @@ public class PopupMenu extends JPopupMenu
     // TODO: put in info about what is being sent.
     item.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         new Thread(new Runnable()
         {
 
+          @Override
           public void run()
           {
             try
@@ -1017,6 +1279,7 @@ public class PopupMenu extends JPopupMenu
     groupName.setText(MessageManager.getString("label.name"));
     groupName.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         groupName_actionPerformed();
@@ -1027,15 +1290,27 @@ public class PopupMenu extends JPopupMenu
             .getString("label.edit_name_description"));
     sequenceName.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         sequenceName_actionPerformed();
       }
     });
+    chooseAnnotations.setText(MessageManager
+            .getString("label.choose_annotations") + "...");
+    chooseAnnotations.addActionListener(new java.awt.event.ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        chooseAnnotations_actionPerformed(e);
+      }
+    });
     sequenceDetails.setText(MessageManager
             .getString("label.sequence_details") + "...");
     sequenceDetails.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         sequenceDetails_actionPerformed();
@@ -1046,6 +1321,7 @@ public class PopupMenu extends JPopupMenu
     sequenceSelDetails
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 sequenceSelectionDetails_actionPerformed();
@@ -1056,6 +1332,7 @@ public class PopupMenu extends JPopupMenu
             .setText(MessageManager.getString("action.remove_group"));
     unGroupMenuItem.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         unGroupMenuItem_actionPerformed();
@@ -1066,6 +1343,7 @@ public class PopupMenu extends JPopupMenu
     createGroupMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 createGroupMenuItem_actionPerformed();
@@ -1075,6 +1353,7 @@ public class PopupMenu extends JPopupMenu
     outline.setText(MessageManager.getString("action.border_colour"));
     outline.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         outline_actionPerformed();
@@ -1084,6 +1363,7 @@ public class PopupMenu extends JPopupMenu
             .setText(MessageManager.getString("label.nucleotide"));
     nucleotideMenuItem.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         nucleotideMenuItem_actionPerformed();
@@ -1094,6 +1374,7 @@ public class PopupMenu extends JPopupMenu
     showBoxes.setState(true);
     showBoxes.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showBoxes_actionPerformed();
@@ -1103,6 +1384,7 @@ public class PopupMenu extends JPopupMenu
     showText.setState(true);
     showText.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showText_actionPerformed();
@@ -1111,6 +1393,7 @@ public class PopupMenu extends JPopupMenu
     showColourText.setText(MessageManager.getString("label.colour_text"));
     showColourText.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showColourText_actionPerformed();
@@ -1121,6 +1404,7 @@ public class PopupMenu extends JPopupMenu
     displayNonconserved.setState(true);
     displayNonconserved.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showNonconserved_actionPerformed();
@@ -1130,6 +1414,7 @@ public class PopupMenu extends JPopupMenu
     cut.setText(MessageManager.getString("action.cut"));
     cut.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         cut_actionPerformed();
@@ -1138,6 +1423,7 @@ public class PopupMenu extends JPopupMenu
     upperCase.setText(MessageManager.getString("label.to_upper_case"));
     upperCase.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         changeCase(e);
@@ -1146,6 +1432,7 @@ public class PopupMenu extends JPopupMenu
     copy.setText(MessageManager.getString("action.copy"));
     copy.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         copy_actionPerformed();
@@ -1154,6 +1441,7 @@ public class PopupMenu extends JPopupMenu
     lowerCase.setText(MessageManager.getString("label.to_lower_case"));
     lowerCase.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         changeCase(e);
@@ -1162,6 +1450,7 @@ public class PopupMenu extends JPopupMenu
     toggle.setText(MessageManager.getString("label.toggle_case"));
     toggle.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         changeCase(e);
@@ -1172,6 +1461,7 @@ public class PopupMenu extends JPopupMenu
     pdbFromFile.setText(MessageManager.getString("label.from_file"));
     pdbFromFile.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         pdbFromFile_actionPerformed();
@@ -1206,6 +1496,7 @@ public class PopupMenu extends JPopupMenu
     enterPDB.setText(MessageManager.getString("label.enter_pdb_id"));
     enterPDB.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         enterPDB_actionPerformed();
@@ -1214,6 +1505,7 @@ public class PopupMenu extends JPopupMenu
     discoverPDB.setText(MessageManager.getString("label.discover_pdb_ids"));
     discoverPDB.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         discoverPDB_actionPerformed();
@@ -1221,10 +1513,28 @@ public class PopupMenu extends JPopupMenu
     });
     outputMenu.setText(MessageManager.getString("label.out_to_textbox")
             + "...");
+    showAnnotationsMenu.setText(MessageManager
+            .getString("label.show_annotations"));
+    hideAnnotationsMenu.setText(MessageManager
+            .getString("label.hide_annotations"));
+    final List<AlignmentAnnotation> referenceAnns = getDatasequenceAnnotationsNotOnAlignment(ap.av
+            .getSelectionGroup());
+    addDatasequenceAnnotations.setText(MessageManager
+            .getString("label.add_reference_annotations"));
+    addDatasequenceAnnotations.setEnabled(!referenceAnns.isEmpty());
+    addDatasequenceAnnotations.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        addReferenceAnnotations_actionPerformed(referenceAnns);
+      }
+    });
     sequenceFeature.setText(MessageManager
             .getString("label.create_sequence_feature"));
     sequenceFeature.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         sequenceFeature_actionPerformed();
@@ -1233,6 +1543,7 @@ public class PopupMenu extends JPopupMenu
     textColour.setText(MessageManager.getString("label.text_colour"));
     textColour.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         textColour_actionPerformed();
@@ -1247,6 +1558,7 @@ public class PopupMenu extends JPopupMenu
             + "...");
     editSequence.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent actionEvent)
       {
         editSequence_actionPerformed(actionEvent);
@@ -1263,6 +1575,10 @@ public class PopupMenu extends JPopupMenu
     add(groupMenu);
     add(sequenceMenu);
     this.add(structureMenu);
+    // groupMenu.add(chooseAnnotations);
+    groupMenu.add(showAnnotationsMenu);
+    groupMenu.add(hideAnnotationsMenu);
+    groupMenu.add(addDatasequenceAnnotations);
     groupMenu.add(editMenu);
     groupMenu.add(outputMenu);
     groupMenu.add(sequenceFeature);
@@ -1303,6 +1619,7 @@ public class PopupMenu extends JPopupMenu
         JMenuItem item = new JMenuItem(userColours.nextElement().toString());
         item.addActionListener(new ActionListener()
         {
+          @Override
           public void actionPerformed(ActionEvent evt)
           {
             userDefinedColour_actionPerformed(evt);
@@ -1342,6 +1659,7 @@ public class PopupMenu extends JPopupMenu
     noColourmenuItem.setText(MessageManager.getString("label.none"));
     noColourmenuItem.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         noColourmenuItem_actionPerformed();
@@ -1352,6 +1670,7 @@ public class PopupMenu extends JPopupMenu
             .getString("label.clustalx_colours"));
     clustalColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         clustalColour_actionPerformed();
@@ -1360,6 +1679,7 @@ public class PopupMenu extends JPopupMenu
     zappoColour.setText(MessageManager.getString("label.zappo"));
     zappoColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         zappoColour_actionPerformed();
@@ -1368,6 +1688,7 @@ public class PopupMenu extends JPopupMenu
     taylorColour.setText(MessageManager.getString("label.taylor"));
     taylorColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         taylorColour_actionPerformed();
@@ -1378,6 +1699,7 @@ public class PopupMenu extends JPopupMenu
     hydrophobicityColour
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 hydrophobicityColour_actionPerformed();
@@ -1386,6 +1708,7 @@ public class PopupMenu extends JPopupMenu
     helixColour.setText(MessageManager.getString("label.helix_propensity"));
     helixColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         helixColour_actionPerformed();
@@ -1395,6 +1718,7 @@ public class PopupMenu extends JPopupMenu
             .getString("label.strand_propensity"));
     strandColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         strandColour_actionPerformed();
@@ -1403,6 +1727,7 @@ public class PopupMenu extends JPopupMenu
     turnColour.setText(MessageManager.getString("label.turn_propensity"));
     turnColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         turnColour_actionPerformed();
@@ -1411,6 +1736,7 @@ public class PopupMenu extends JPopupMenu
     buriedColour.setText(MessageManager.getString("label.buried_index"));
     buriedColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         buriedColour_actionPerformed();
@@ -1420,6 +1746,7 @@ public class PopupMenu extends JPopupMenu
             .getString("label.above_identity_percentage"));
     abovePIDColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         abovePIDColour_actionPerformed();
@@ -1429,6 +1756,7 @@ public class PopupMenu extends JPopupMenu
             .getString("action.user_defined"));
     userDefinedColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         userDefinedColour_actionPerformed(e);
@@ -1438,6 +1766,7 @@ public class PopupMenu extends JPopupMenu
             .setText(MessageManager.getString("label.percentage_identity"));
     PIDColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         PIDColour_actionPerformed();
@@ -1446,6 +1775,7 @@ public class PopupMenu extends JPopupMenu
     BLOSUM62Colour.setText(MessageManager.getString("label.blosum62"));
     BLOSUM62Colour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         BLOSUM62Colour_actionPerformed();
@@ -1456,6 +1786,7 @@ public class PopupMenu extends JPopupMenu
     purinePyrimidineColour
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 purinePyrimidineColour_actionPerformed();
@@ -1473,6 +1804,7 @@ public class PopupMenu extends JPopupMenu
     conservationMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 conservationMenuItem_actionPerformed();
@@ -1480,6 +1812,59 @@ public class PopupMenu extends JPopupMenu
             });
   }
 
+  /**
+   * Get a list of any annotations on the dataset sequences in the current
+   * selection group that are not also on the alignment.
+   * <p/>
+   * The criteria for 'on the alignment' is finding an annotation that matches
+   * on sequenceRef.datasetSequence, calcId and label.
+   * 
+   * @return
+   */
+  protected List<AlignmentAnnotation> getDatasequenceAnnotationsNotOnAlignment(
+          SequenceGroup sg)
+  {
+    List<AlignmentAnnotation> result = new ArrayList<AlignmentAnnotation>();
+    
+    for (SequenceI seq : sg.getSequences())
+    {
+      SequenceI dataset = seq.getDatasetSequence();
+      AlignmentAnnotation[] datasetAnnotations = dataset.getAnnotation();
+      if (datasetAnnotations != null)
+      {
+        for (AlignmentAnnotation dsann : datasetAnnotations)
+        {
+          /*
+           * If the alignment has no annotation that matches this one...
+           */
+          if (!ap.getAlignment()
+                  .findAnnotation(dataset, dsann.getCalcId(), dsann.label)
+                  .iterator().hasNext())
+          {
+            /*
+             * ...then add it to the result list
+             */
+            result.add(dsann);
+          }
+        }
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Add any annotations on the sequence dataset to the alignment (that are not
+   * already copied to it).
+   */
+  protected void addReferenceAnnotations_actionPerformed(
+          List<AlignmentAnnotation> anns)
+  {
+    for (AlignmentAnnotation ann : anns)
+    {
+      // todo: copy, add, adjust...
+    }
+  }
+
   protected void sequenceSelectionDetails_actionPerformed()
   {
     createSequenceDetailsReport(ap.av.getSequenceSelection());
@@ -1721,6 +2106,18 @@ public class PopupMenu extends JPopupMenu
   }
 
   /**
+   * Open a panel where the user can choose which types of sequence annotation
+   * to show or hide.
+   * 
+   * @param e
+   */
+  protected void chooseAnnotations_actionPerformed(ActionEvent e)
+  {
+    // todo correct way to guard against opening a duplicate panel?
+    new AnnotationChooser(ap);
+  }
+
+  /**
    * DOCUMENT ME!
    * 
    * @param e
@@ -2109,7 +2506,8 @@ public class PopupMenu extends JPopupMenu
     // or we simply trust the user wants
     // wysiwig behaviour
 
-    cap.setText(new FormatAdapter().formatSequences(e.getActionCommand(), ap.av, true));
+    cap.setText(new FormatAdapter().formatSequences(e.getActionCommand(),
+            ap.av, true));
   }
 
   public void pdbFromFile_actionPerformed()
@@ -2171,6 +2569,7 @@ public class PopupMenu extends JPopupMenu
             : ap.av.getSequenceSelection());
     Thread discpdb = new Thread(new Runnable()
     {
+      @Override
       public void run()
       {
 
@@ -2255,7 +2654,7 @@ public class PopupMenu extends JPopupMenu
     if (sg != null)
     {
       if (sequence == null)
-        sequence = (Sequence) sg.getSequenceAt(0);
+        sequence = sg.getSequenceAt(0);
 
       EditNameDialog dialog = new EditNameDialog(
               sequence.getSequenceAsString(sg.getStartRes(),
index e122f21..f073ce3 100755 (executable)
@@ -20,6 +20,7 @@
  */
 package jalview.jbgui;
 
+import jalview.bin.Cache;
 import jalview.schemes.ColourSchemeProperty;
 import jalview.util.MessageManager;
 
@@ -302,6 +303,10 @@ public class GAlignFrame extends JInternalFrame
 
   JMenuItem showAllhidden = new JMenuItem();
 
+  protected JMenuItem showAllAnnotations = new JMenuItem();
+
+  protected JMenuItem hideAllAnnotations = new JMenuItem();
+
   protected JCheckBoxMenuItem hiddenMarkers = new JCheckBoxMenuItem();
 
   JMenuItem invertColSel = new JMenuItem();
@@ -371,6 +376,7 @@ public class GAlignFrame extends JInternalFrame
 
         item.addActionListener(new java.awt.event.ActionListener()
         {
+          @Override
           public void actionPerformed(ActionEvent e)
           {
             outputText_actionPerformed(e);
@@ -381,6 +387,7 @@ public class GAlignFrame extends JInternalFrame
       }
     } catch (Exception e)
     {
+      System.err.println(e.toString());
     }
 
     if (!new jalview.util.Platform().isAMac())
@@ -407,6 +414,7 @@ public class GAlignFrame extends JInternalFrame
         radioItem.setName("USER_DEFINED");
         radioItem.addMouseListener(new MouseAdapter()
         {
+          @Override
           public void mousePressed(MouseEvent evt)
           {
             if (evt.isControlDown()
@@ -431,6 +439,7 @@ public class GAlignFrame extends JInternalFrame
               {
                 radioItem.addActionListener(new ActionListener()
                 {
+                  @Override
                   public void actionPerformed(ActionEvent evt)
                   {
                     userDefinedColour_actionPerformed(evt);
@@ -442,6 +451,7 @@ public class GAlignFrame extends JInternalFrame
         });
         radioItem.addActionListener(new ActionListener()
         {
+          @Override
           public void actionPerformed(ActionEvent evt)
           {
             userDefinedColour_actionPerformed(evt);
@@ -580,6 +590,7 @@ public class GAlignFrame extends JInternalFrame
                     | java.awt.event.KeyEvent.SHIFT_MASK, false));
     saveAs.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         saveAs_actionPerformed(e);
@@ -591,6 +602,7 @@ public class GAlignFrame extends JInternalFrame
                     .getMenuShortcutKeyMask(), false));
     closeMenuItem.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         closeMenuItem_actionPerformed(false);
@@ -609,6 +621,7 @@ public class GAlignFrame extends JInternalFrame
     selectAllSequenceMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 selectAllSequenceMenuItem_actionPerformed(e);
@@ -621,6 +634,7 @@ public class GAlignFrame extends JInternalFrame
     deselectAllSequenceMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 deselectAllSequenceMenuItem_actionPerformed(e);
@@ -634,6 +648,7 @@ public class GAlignFrame extends JInternalFrame
     invertSequenceMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 invertSequenceMenuItem_actionPerformed(e);
@@ -643,6 +658,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("action.make_groups_selection"));
     grpsFromSelection.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         makeGrpsFromSelection_actionPerformed(e);
@@ -668,6 +684,7 @@ public class GAlignFrame extends JInternalFrame
     remove2LeftMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 remove2LeftMenuItem_actionPerformed(e);
@@ -681,6 +698,7 @@ public class GAlignFrame extends JInternalFrame
     remove2RightMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 remove2RightMenuItem_actionPerformed(e);
@@ -694,6 +712,7 @@ public class GAlignFrame extends JInternalFrame
     removeGappedColumnMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 removeGappedColumnMenuItem_actionPerformed(e);
@@ -708,6 +727,7 @@ public class GAlignFrame extends JInternalFrame
     removeAllGapsMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 removeAllGapsMenuItem_actionPerformed(e);
@@ -718,6 +738,7 @@ public class GAlignFrame extends JInternalFrame
     justifyLeftMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 justifyLeftMenuItem_actionPerformed(e);
@@ -728,6 +749,7 @@ public class GAlignFrame extends JInternalFrame
     justifyRightMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 justifyRightMenuItem_actionPerformed(e);
@@ -737,6 +759,7 @@ public class GAlignFrame extends JInternalFrame
     viewBoxesMenuItem.setState(true);
     viewBoxesMenuItem.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         viewBoxesMenuItem_actionPerformed(e);
@@ -746,6 +769,7 @@ public class GAlignFrame extends JInternalFrame
     viewTextMenuItem.setState(true);
     viewTextMenuItem.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         viewTextMenuItem_actionPerformed(e);
@@ -757,6 +781,7 @@ public class GAlignFrame extends JInternalFrame
     showNonconservedMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 showUnconservedMenuItem_actionPerformed(e);
@@ -767,6 +792,7 @@ public class GAlignFrame extends JInternalFrame
     sortPairwiseMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 sortPairwiseMenuItem_actionPerformed(e);
@@ -775,6 +801,7 @@ public class GAlignFrame extends JInternalFrame
     sortIDMenuItem.setText(MessageManager.getString("action.by_id"));
     sortIDMenuItem.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         sortIDMenuItem_actionPerformed(e);
@@ -785,6 +812,7 @@ public class GAlignFrame extends JInternalFrame
     sortLengthMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 sortLengthMenuItem_actionPerformed(e);
@@ -793,6 +821,7 @@ public class GAlignFrame extends JInternalFrame
     sortGroupMenuItem.setText(MessageManager.getString("action.by_group"));
     sortGroupMenuItem.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         sortGroupMenuItem_actionPerformed(e);
@@ -806,6 +835,7 @@ public class GAlignFrame extends JInternalFrame
     removeRedundancyMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 removeRedundancyMenuItem_actionPerformed(e);
@@ -816,6 +846,7 @@ public class GAlignFrame extends JInternalFrame
     pairwiseAlignmentMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 pairwiseAlignmentMenuItem_actionPerformed(e);
@@ -825,6 +856,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.principal_component_analysis"));
     PCAMenuItem.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         PCAMenuItem_actionPerformed(e);
@@ -835,6 +867,7 @@ public class GAlignFrame extends JInternalFrame
     averageDistanceTreeMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 averageDistanceTreeMenuItem_actionPerformed(e);
@@ -845,6 +878,7 @@ public class GAlignFrame extends JInternalFrame
     neighbourTreeMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 neighbourTreeMenuItem_actionPerformed(e);
@@ -862,6 +896,7 @@ public class GAlignFrame extends JInternalFrame
 
     clustalColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         clustalColour_actionPerformed(e);
@@ -870,6 +905,7 @@ public class GAlignFrame extends JInternalFrame
     zappoColour.setText(MessageManager.getString("label.zappo"));
     zappoColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         zappoColour_actionPerformed(e);
@@ -878,6 +914,7 @@ public class GAlignFrame extends JInternalFrame
     taylorColour.setText(MessageManager.getString("label.taylor"));
     taylorColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         taylorColour_actionPerformed(e);
@@ -888,6 +925,7 @@ public class GAlignFrame extends JInternalFrame
     hydrophobicityColour
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 hydrophobicityColour_actionPerformed(e);
@@ -896,6 +934,7 @@ public class GAlignFrame extends JInternalFrame
     helixColour.setText(MessageManager.getString("label.helix_propensity"));
     helixColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         helixColour_actionPerformed(e);
@@ -905,6 +944,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.strand_propensity"));
     strandColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         strandColour_actionPerformed(e);
@@ -913,6 +953,7 @@ public class GAlignFrame extends JInternalFrame
     turnColour.setText(MessageManager.getString("label.turn_propensity"));
     turnColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         turnColour_actionPerformed(e);
@@ -921,6 +962,7 @@ public class GAlignFrame extends JInternalFrame
     buriedColour.setText(MessageManager.getString("label.buried_index"));
     buriedColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         buriedColour_actionPerformed(e);
@@ -930,6 +972,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("action.user_defined"));
     userDefinedColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         userDefinedColour_actionPerformed(e);
@@ -939,6 +982,7 @@ public class GAlignFrame extends JInternalFrame
             .setText(MessageManager.getString("label.percentage_identity"));
     PIDColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         PIDColour_actionPerformed(e);
@@ -948,6 +992,7 @@ public class GAlignFrame extends JInternalFrame
             .setText(MessageManager.getString("label.blosum62_score"));
     BLOSUM62Colour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         BLOSUM62Colour_actionPerformed(e);
@@ -956,6 +1001,7 @@ public class GAlignFrame extends JInternalFrame
     nucleotideColour.setText(MessageManager.getString("label.nucleotide"));
     nucleotideColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         nucleotideColour_actionPerformed(e);
@@ -967,6 +1013,7 @@ public class GAlignFrame extends JInternalFrame
     purinePyrimidineColour
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 purinePyrimidineColour_actionPerformed(e);
@@ -977,6 +1024,7 @@ public class GAlignFrame extends JInternalFrame
     RNAInteractionColour
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 RNAInteractionColour_actionPerformed(e);
@@ -994,6 +1042,7 @@ public class GAlignFrame extends JInternalFrame
     avDistanceTreeBlosumMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 avTreeBlosumMenuItem_actionPerformed(e);
@@ -1004,6 +1053,7 @@ public class GAlignFrame extends JInternalFrame
     njTreeBlosumMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 njTreeBlosumMenuItem_actionPerformed(e);
@@ -1012,21 +1062,47 @@ public class GAlignFrame extends JInternalFrame
     annotationPanelMenuItem.setActionCommand("");
     annotationPanelMenuItem.setText(MessageManager
             .getString("label.show_annotations"));
-    annotationPanelMenuItem.setState(jalview.bin.Cache.getDefault(
-            "SHOW_ANNOTATIONS", true));
-    annotationPanelMenuItem
-            .addActionListener(new java.awt.event.ActionListener()
-            {
-              public void actionPerformed(ActionEvent e)
-              {
-                annotationPanelMenuItem_actionPerformed(e);
-              }
-            });
+    annotationPanelMenuItem.setState(Cache.getDefault("SHOW_ANNOTATIONS",
+            true));
+    annotationPanelMenuItem.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        annotationPanelMenuItem_actionPerformed(e);
+      }
+    });
+    /*
+     * Show/hide all annotations only enabled if annotation panel is shown
+     */
+    showAllAnnotations.setText(MessageManager
+            .getString("label.show_all_annotations"));
+    showAllAnnotations.setEnabled(annotationPanelMenuItem.getState());
+    showAllAnnotations.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        showAllAnnotations_actionPerformed();
+      }
+    });
+    hideAllAnnotations.setText(MessageManager
+            .getString("label.hide_all_annotations"));
+    hideAllAnnotations.setEnabled(annotationPanelMenuItem.getState());
+    hideAllAnnotations.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        hideAllAnnotations_actionPerformed();
+      }
+    });
     colourTextMenuItem.setText(MessageManager
             .getString("label.colour_text"));
     colourTextMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 colourTextMenuItem_actionPerformed(e);
@@ -1035,6 +1111,7 @@ public class GAlignFrame extends JInternalFrame
     htmlMenuItem.setText(MessageManager.getString("label.html"));
     htmlMenuItem.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         htmlMenuItem_actionPerformed(e);
@@ -1044,6 +1121,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.overview_window"));
     overviewMenuItem.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         overviewMenuItem_actionPerformed(e);
@@ -1056,6 +1134,7 @@ public class GAlignFrame extends JInternalFrame
                     .getMenuShortcutKeyMask(), false));
     undoMenuItem.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         undoMenuItem_actionPerformed(e);
@@ -1068,6 +1147,7 @@ public class GAlignFrame extends JInternalFrame
                     .getMenuShortcutKeyMask(), false));
     redoMenuItem.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         redoMenuItem_actionPerformed(e);
@@ -1078,6 +1158,7 @@ public class GAlignFrame extends JInternalFrame
     conservationMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 conservationMenuItem_actionPerformed(e);
@@ -1086,6 +1167,7 @@ public class GAlignFrame extends JInternalFrame
     noColourmenuItem.setText(MessageManager.getString("label.none"));
     noColourmenuItem.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         noColourmenuItem_actionPerformed(e);
@@ -1094,6 +1176,7 @@ public class GAlignFrame extends JInternalFrame
     wrapMenuItem.setText(MessageManager.getString("label.wrap"));
     wrapMenuItem.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         wrapMenuItem_actionPerformed(e);
@@ -1105,6 +1188,7 @@ public class GAlignFrame extends JInternalFrame
                     .getMenuShortcutKeyMask(), false));
     printMenuItem.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         printMenuItem_actionPerformed(e);
@@ -1116,6 +1200,7 @@ public class GAlignFrame extends JInternalFrame
     renderGapsMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 renderGapsMenuItem_actionPerformed(e);
@@ -1125,8 +1210,10 @@ public class GAlignFrame extends JInternalFrame
     findMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(
             java.awt.event.KeyEvent.VK_F, Toolkit.getDefaultToolkit()
                     .getMenuShortcutKeyMask(), false));
+    findMenuItem.setToolTipText(MessageManager.getString("label.find_tip"));
     findMenuItem.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         findMenuItem_actionPerformed(e);
@@ -1136,6 +1223,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.above_identity_threshold"));
     abovePIDThreshold.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         abovePIDThreshold_actionPerformed(e);
@@ -1145,6 +1233,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.show_sequence_features"));
     showSeqFeatures.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent actionEvent)
       {
         showSeqFeatures_actionPerformed(actionEvent);
@@ -1161,6 +1250,7 @@ public class GAlignFrame extends JInternalFrame
     showDbRefsMenuitem.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showDbRefs_actionPerformed(e);
@@ -1172,6 +1262,7 @@ public class GAlignFrame extends JInternalFrame
     showNpFeatsMenuitem.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showNpFeats_actionPerformed(e);
@@ -1183,6 +1274,7 @@ public class GAlignFrame extends JInternalFrame
     showGroupConservation.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showGroupConservation_actionPerformed(e);
@@ -1195,6 +1287,7 @@ public class GAlignFrame extends JInternalFrame
     showGroupConsensus.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showGroupConsensus_actionPerformed(e);
@@ -1206,6 +1299,7 @@ public class GAlignFrame extends JInternalFrame
     showConsensusHistogram.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showConsensusHistogram_actionPerformed(e);
@@ -1217,6 +1311,7 @@ public class GAlignFrame extends JInternalFrame
     showSequenceLogo.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showSequenceLogo_actionPerformed(e);
@@ -1228,6 +1323,7 @@ public class GAlignFrame extends JInternalFrame
     normaliseSequenceLogo.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         normaliseSequenceLogo_actionPerformed(e);
@@ -1241,6 +1337,7 @@ public class GAlignFrame extends JInternalFrame
     applyAutoAnnotationSettings.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         applyAutoAnnotationSettings_actionPerformed(e);
@@ -1251,6 +1348,7 @@ public class GAlignFrame extends JInternalFrame
     nucleotideColour.setText(MessageManager.getString("label.nucleotide"));
     nucleotideColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         nucleotideColour_actionPerformed(e);
@@ -1276,6 +1374,7 @@ public class GAlignFrame extends JInternalFrame
                     .getMenuShortcutKeyMask(), false));
     deleteGroups.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         deleteGroups_actionPerformed(e);
@@ -1287,6 +1386,7 @@ public class GAlignFrame extends JInternalFrame
                     .getMenuShortcutKeyMask(), false));
     createGroup.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         createGroup_actionPerformed(e);
@@ -1299,6 +1399,7 @@ public class GAlignFrame extends JInternalFrame
                     | java.awt.event.KeyEvent.SHIFT_MASK, false));
     unGroup.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         unGroup_actionPerformed(e);
@@ -1311,6 +1412,7 @@ public class GAlignFrame extends JInternalFrame
 
     copy.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         copy_actionPerformed(e);
@@ -1322,16 +1424,16 @@ public class GAlignFrame extends JInternalFrame
                     .getMenuShortcutKeyMask(), false));
     cut.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         cut_actionPerformed(e);
       }
     });
     delete.setText(MessageManager.getString("action.delete"));
-    delete.setAccelerator(javax.swing.KeyStroke.getKeyStroke(
-            java.awt.event.KeyEvent.VK_BACK_SPACE, 0, false));
     delete.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         delete_actionPerformed(e);
@@ -1345,6 +1447,7 @@ public class GAlignFrame extends JInternalFrame
                     | java.awt.event.KeyEvent.SHIFT_MASK, false));
     pasteNew.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         pasteNew_actionPerformed(e);
@@ -1356,6 +1459,7 @@ public class GAlignFrame extends JInternalFrame
                     .getMenuShortcutKeyMask(), false));
     pasteThis.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         pasteThis_actionPerformed(e);
@@ -1365,6 +1469,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.apply_colour_to_all_groups"));
     applyToAllGroups.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         applyToAllGroups_actionPerformed(e);
@@ -1372,6 +1477,7 @@ public class GAlignFrame extends JInternalFrame
     });
     createPNG.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         createPNG(null);
@@ -1383,6 +1489,7 @@ public class GAlignFrame extends JInternalFrame
     font.setText(MessageManager.getString("action.font"));
     font.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         font_actionPerformed(e);
@@ -1394,6 +1501,7 @@ public class GAlignFrame extends JInternalFrame
     seqLimits.setState(jalview.bin.Cache.getDefault("SHOW_JVSUFFIX", true));
     seqLimits.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         seqLimit_actionPerformed(e);
@@ -1402,6 +1510,7 @@ public class GAlignFrame extends JInternalFrame
     epsFile.setText("EPS");
     epsFile.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         createEPS(null);
@@ -1413,6 +1522,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.load_associated_tree"));
     LoadtreeMenuItem.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         LoadtreeMenuItem_actionPerformed(e);
@@ -1423,6 +1533,7 @@ public class GAlignFrame extends JInternalFrame
     scaleAbove.setText(MessageManager.getString("action.scale_above"));
     scaleAbove.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         scaleAbove_actionPerformed(e);
@@ -1433,6 +1544,7 @@ public class GAlignFrame extends JInternalFrame
     scaleLeft.setText(MessageManager.getString("action.scale_left"));
     scaleLeft.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         scaleLeft_actionPerformed(e);
@@ -1443,6 +1555,7 @@ public class GAlignFrame extends JInternalFrame
     scaleRight.setText(MessageManager.getString("action.scale_right"));
     scaleRight.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         scaleRight_actionPerformed(e);
@@ -1455,6 +1568,7 @@ public class GAlignFrame extends JInternalFrame
     centreColumnLabelsMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 centreColumnLabels_actionPerformed(e);
@@ -1467,6 +1581,7 @@ public class GAlignFrame extends JInternalFrame
     followHighlightMenuItem.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         followHighlight_actionPerformed();
@@ -1478,6 +1593,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.modify_identity_thereshold"));
     modifyPID.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         modifyPID_actionPerformed(e);
@@ -1488,6 +1604,7 @@ public class GAlignFrame extends JInternalFrame
     modifyConservation
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 modifyConservation_actionPerformed(e);
@@ -1498,15 +1615,18 @@ public class GAlignFrame extends JInternalFrame
     sort.setText(MessageManager.getString("action.sort"));
     sort.addMenuListener(new MenuListener()
     {
+      @Override
       public void menuSelected(MenuEvent e)
       {
         buildTreeMenu();
       }
 
+      @Override
       public void menuDeselected(MenuEvent e)
       {
       }
 
+      @Override
       public void menuCanceled(MenuEvent e)
       {
       }
@@ -1517,14 +1637,17 @@ public class GAlignFrame extends JInternalFrame
     sortByAnnotScore.addMenuListener(new javax.swing.event.MenuListener()
     {
 
+      @Override
       public void menuCanceled(MenuEvent e)
       {
       }
 
+      @Override
       public void menuDeselected(MenuEvent e)
       {
       }
 
+      @Override
       public void menuSelected(MenuEvent e)
       {
         buildSortByAnnotationScoresMenu();
@@ -1541,6 +1664,7 @@ public class GAlignFrame extends JInternalFrame
             .getDefault("PAD_GAPS", false));
     padGapsMenuitem.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         padGapsMenuitem_actionPerformed(e);
@@ -1550,6 +1674,7 @@ public class GAlignFrame extends JInternalFrame
     vamsasStore.setText(MessageManager.getString("label.vamsas_store"));
     vamsasStore.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         vamsasStore_actionPerformed(e);
@@ -1559,6 +1684,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.translate_cDNA"));
     showTranslation.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showTranslation_actionPerformed(e);
@@ -1568,6 +1694,7 @@ public class GAlignFrame extends JInternalFrame
             + "...");
     extractScores.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         extractScores_actionPerformed(e);
@@ -1586,6 +1713,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.feature_settings"));
     openFeatureSettings.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         featureSettings_actionPerformed(e);
@@ -1595,6 +1723,7 @@ public class GAlignFrame extends JInternalFrame
             .setText(MessageManager.getString("label.fetch_sequences"));
     fetchSequence.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         fetchSequence_actionPerformed(e);
@@ -1605,6 +1734,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("action.by_annotation"));
     annotationColour.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         annotationColour_actionPerformed(e);
@@ -1615,6 +1745,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("action.by_rna_helixes"));
     rnahelicesColour.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         rnahelicesColour_actionPerformed(e);
@@ -1625,6 +1756,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.load_features_annotations"));
     associatedData.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         associatedData_actionPerformed(e);
@@ -1636,6 +1768,7 @@ public class GAlignFrame extends JInternalFrame
             "AUTO_CALC_CONSENSUS", true));
     autoCalculate.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         autoCalculate_actionPerformed(e);
@@ -1651,6 +1784,7 @@ public class GAlignFrame extends JInternalFrame
             .setState(jalview.bin.Cache.getDefault("SORT_BY_TREE", false));
     sortByTree.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         sortByTreeOption_actionPerformed(e);
@@ -1666,6 +1800,7 @@ public class GAlignFrame extends JInternalFrame
     listenToViewSelections.setState(false);
     listenToViewSelections.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         listenToViewSelections_actionPerformed(e);
@@ -1677,6 +1812,7 @@ public class GAlignFrame extends JInternalFrame
     addFromFile.setText(MessageManager.getString("label.from_file"));
     addFromFile.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         addFromFile_actionPerformed(e);
@@ -1685,6 +1821,7 @@ public class GAlignFrame extends JInternalFrame
     addFromText.setText(MessageManager.getString("label.from_textbox"));
     addFromText.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         addFromText_actionPerformed(e);
@@ -1693,6 +1830,7 @@ public class GAlignFrame extends JInternalFrame
     addFromURL.setText(MessageManager.getString("label.from_url"));
     addFromURL.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         addFromURL_actionPerformed(e);
@@ -1702,6 +1840,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.export_features"));
     exportFeatures.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         exportFeatures_actionPerformed(e);
@@ -1711,6 +1850,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.export_annotations"));
     exportAnnotations.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         exportAnnotations_actionPerformed(e);
@@ -1723,6 +1863,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.toggle_sequence_visibility"));
     showAllSeqs.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showAllSeqs_actionPerformed(e);
@@ -1733,6 +1874,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.toggle_columns_visibility"));
     showAllColumns.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showAllColumns_actionPerformed(e);
@@ -1745,6 +1887,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.toggle_sequence_visibility"));
     hideSelSequences.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         hideSelSequences_actionPerformed(e);
@@ -1756,6 +1899,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.toggle_columns_visibility"));
     hideSelColumns.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         hideSelColumns_actionPerformed(e);
@@ -1765,6 +1909,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.selected_region"));
     hideAllSelection.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         hideAllSelection_actionPerformed(e);
@@ -1775,6 +1920,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.all_but_selected_region"));
     hideAllButSelection.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         hideAllButSelection_actionPerformed(e);
@@ -1786,16 +1932,17 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.toggles_visibility_hidden_selected_regions"));
     showAllhidden.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showAllhidden_actionPerformed(e);
       }
     });
-
     hiddenMarkers.setText(MessageManager
             .getString("action.show_hidden_markers"));
     hiddenMarkers.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         hiddenMarkers_actionPerformed(e);
@@ -1809,6 +1956,7 @@ public class GAlignFrame extends JInternalFrame
                     | java.awt.event.KeyEvent.ALT_MASK, false));
     invertColSel.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         invertColSel_actionPerformed(e);
@@ -1816,6 +1964,7 @@ public class GAlignFrame extends JInternalFrame
     });
     tabbedPane.addChangeListener(new javax.swing.event.ChangeListener()
     {
+      @Override
       public void stateChanged(ChangeEvent evt)
       {
         JTabbedPane pane = (JTabbedPane) evt.getSource();
@@ -1825,6 +1974,7 @@ public class GAlignFrame extends JInternalFrame
     });
     tabbedPane.addMouseListener(new MouseAdapter()
     {
+      @Override
       public void mousePressed(MouseEvent e)
       {
         tabbedPane_mousePressed(e);
@@ -1832,6 +1982,7 @@ public class GAlignFrame extends JInternalFrame
     });
     tabbedPane.addFocusListener(new FocusAdapter()
     {
+      @Override
       public void focusGained(FocusEvent e)
       {
         tabbedPane_focusGained(e);
@@ -1843,6 +1994,7 @@ public class GAlignFrame extends JInternalFrame
                     .getMenuShortcutKeyMask(), false));
     save.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         save_actionPerformed(e);
@@ -1852,6 +2004,7 @@ public class GAlignFrame extends JInternalFrame
     reload.setText(MessageManager.getString("action.reload"));
     reload.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         reload_actionPerformed(e);
@@ -1863,6 +2016,7 @@ public class GAlignFrame extends JInternalFrame
                     .getMenuShortcutKeyMask(), false));
     newView.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         newView_actionPerformed(e);
@@ -1875,6 +2029,7 @@ public class GAlignFrame extends JInternalFrame
             + "...");
     textColour.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         textColour_actionPerformed(e);
@@ -1886,6 +2041,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.right_align_sequence_id"));
     idRightAlign.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         idRightAlign_actionPerformed(e);
@@ -1897,6 +2053,7 @@ public class GAlignFrame extends JInternalFrame
             java.awt.event.KeyEvent.VK_G, 0, false));
     gatherViews.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         gatherViews_actionPerformed(e);
@@ -1908,6 +2065,7 @@ public class GAlignFrame extends JInternalFrame
             java.awt.event.KeyEvent.VK_X, 0, false));
     expandViews.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         expandViews_actionPerformed(e);
@@ -1917,6 +2075,7 @@ public class GAlignFrame extends JInternalFrame
             .setText(MessageManager.getString("action.page_setup") + "...");
     pageSetup.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         pageSetup_actionPerformed(e);
@@ -1926,6 +2085,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.alignment_props") + "...");
     alignmentProperties.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent actionEvent)
       {
         alignmentProperties();
@@ -1989,6 +2149,8 @@ public class GAlignFrame extends JInternalFrame
     viewMenu.addSeparator();
     viewMenu.add(followHighlightMenuItem);
     viewMenu.add(annotationPanelMenuItem);
+    viewMenu.add(showAllAnnotations);
+    viewMenu.add(hideAllAnnotations);
     autoAnnMenu.add(applyAutoAnnotationSettings);
     autoAnnMenu.add(showConsensusHistogram);
     autoAnnMenu.add(showSequenceLogo);
@@ -2107,6 +2269,32 @@ public class GAlignFrame extends JInternalFrame
     // selectMenu.add(listenToViewSelections);
   }
 
+  /**
+   * Action on clicking Show all annotations.
+   */
+  protected void showAllAnnotations_actionPerformed()
+  {
+    setAllAnnotationsVisibility(true);
+  }
+
+  /**
+   * Action on clicking Hide all annotations.
+   */
+  protected void hideAllAnnotations_actionPerformed()
+  {
+    setAllAnnotationsVisibility(false);
+  }
+
+  /**
+   * Set the visibility of all annotations to true or false.
+   * 
+   * @param visible
+   */
+  protected void setAllAnnotationsVisibility(boolean visible)
+  {
+
+  }
+
   protected void normaliseSequenceLogo_actionPerformed(ActionEvent e)
   {
     // TODO Auto-generated method stub
index 69bdd24..c754ee3 100644 (file)
@@ -79,6 +79,7 @@ public class ConsensusThread extends AlignCalcWorker implements
       if (alignViewport.isClosed())
       {
         abortAndDestroy();
+        return;
       }
       AlignmentI alignment = alignViewport.getAlignment();
 
index 7ed50d8..a7180a0 100644 (file)
  */
 package jalview.workers;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import jalview.analysis.Conservation;
 import jalview.api.AlignCalcWorkerI;
-import jalview.api.AlignmentViewPanel;
 import jalview.api.AlignViewportI;
+import jalview.api.AlignmentViewPanel;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 
+import java.util.ArrayList;
+import java.util.List;
+
 public class ConservationThread extends AlignCalcWorker implements
         AlignCalcWorkerI
 {
@@ -74,6 +74,7 @@ public class ConservationThread extends AlignCalcWorker implements
       if (alignViewport.isClosed())
       {
         abortAndDestroy();
+        return;
       }
       List<AlignmentAnnotation> ourAnnot = new ArrayList<AlignmentAnnotation>();
       AlignmentI alignment = alignViewport.getAlignment();
index 72d26ff..3230a36 100644 (file)
@@ -20,8 +20,6 @@
  */
 package jalview.workers;
 
-import java.util.Hashtable;
-
 import jalview.analysis.StructureFrequency;
 import jalview.api.AlignCalcWorkerI;
 import jalview.api.AlignViewportI;
@@ -31,6 +29,8 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Annotation;
 import jalview.datamodel.SequenceI;
 
+import java.util.Hashtable;
+
 public class StrucConsensusThread extends AlignCalcWorker implements
         AlignCalcWorkerI
 {
@@ -74,6 +74,7 @@ public class StrucConsensusThread extends AlignCalcWorker implements
       if (alignViewport.isClosed())
       {
         abortAndDestroy();
+        return;
       }
       AlignmentI alignment = alignViewport.getAlignment();
 
diff --git a/test/jalview/gui/AnnotationChooserTest.java b/test/jalview/gui/AnnotationChooserTest.java
new file mode 100644 (file)
index 0000000..944ab9c
--- /dev/null
@@ -0,0 +1,754 @@
+package jalview.gui;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.io.AppletFormatAdapter;
+import jalview.util.MessageManager;
+
+import java.awt.BorderLayout;
+import java.awt.Checkbox;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.FlowLayout;
+import java.awt.event.ItemEvent;
+import java.io.IOException;
+import java.util.List;
+
+import javax.swing.JButton;
+import javax.swing.JPanel;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Unit tests for AnnotationChooser
+ * 
+ * @author gmcarstairs
+ *
+ */
+public class AnnotationChooserTest
+{
+  // 4 sequences x 13 positions
+  final static String TEST_DATA = ">FER_CAPAA Ferredoxin\n"
+          + "TIETHKEAELVG-\n"
+          + ">FER_CAPAN Ferredoxin, chloroplast precursor\n"
+          + "TIETHKEAELVG-\n"
+          + ">FER1_SOLLC Ferredoxin-1, chloroplast precursor\n"
+          + "TIETHKEEELTA-\n" + ">Q93XJ9_SOLTU Ferredoxin I precursor\n"
+          + "TIETHKEEELTA-\n";
+
+  AnnotationChooser testee;
+
+  AlignmentPanel parentPanel;
+
+  AlignFrame af;
+
+  @Before
+  public void setUp() throws IOException
+  {
+    AlignmentI al = new jalview.io.FormatAdapter().readFile(TEST_DATA,
+            AppletFormatAdapter.PASTE, "FASTA");
+    af = new AlignFrame(al, 700, 500);
+    parentPanel = new AlignmentPanel(af, af.getViewport());
+    addAnnotations();
+  }
+
+  /**
+   * Add 4 annotations, 3 of them sequence-specific.
+   * 
+   * <PRE>
+   * ann1 - for sequence 0 - label 'IUPRED' 
+   * ann2 - not sequence related - label 'Beauty' 
+   * ann3 - for sequence 3 - label 'JMol'
+   * ann4 - for sequence 2 - label 'IUPRED'
+   * ann5 - for sequence 1 - label 'JMol'
+   */
+  private void addAnnotations()
+  {
+    Annotation an = new Annotation(2f);
+    Annotation[] anns = new Annotation[]
+    { an, an, an };
+    AlignmentAnnotation ann0 = new AlignmentAnnotation("IUPRED", "", anns);
+    AlignmentAnnotation ann1 = new AlignmentAnnotation("Beauty", "", anns);
+    AlignmentAnnotation ann2 = new AlignmentAnnotation("JMol", "", anns);
+    AlignmentAnnotation ann3 = new AlignmentAnnotation("IUPRED", "", anns);
+    AlignmentAnnotation ann4 = new AlignmentAnnotation("JMol", "", anns);
+    SequenceI[] seqs = parentPanel.getAlignment().getSequencesArray();
+    ann0.setSequenceRef(seqs[0]);
+    ann2.setSequenceRef(seqs[3]);
+    ann3.setSequenceRef(seqs[2]);
+    ann4.setSequenceRef(seqs[1]);
+    parentPanel.getAlignment().addAnnotation(ann0);
+    parentPanel.getAlignment().addAnnotation(ann1);
+    parentPanel.getAlignment().addAnnotation(ann2);
+    parentPanel.getAlignment().addAnnotation(ann3);
+    parentPanel.getAlignment().addAnnotation(ann4);
+  }
+
+  /**
+   * Test creation of panel with OK and Cancel buttons
+   */
+  @Test
+  public void testBuildActionButtonsPanel()
+  {
+    testee = new AnnotationChooser(parentPanel);
+    JPanel jp = testee.buildActionButtonsPanel();
+    assertTrue("Wrong layout", jp.getLayout() instanceof FlowLayout);
+
+    Component[] comps = jp.getComponents();
+    assertEquals("Not 2 action buttons", 2, comps.length);
+
+    final Component jb1 = comps[0];
+    final Component jb2 = comps[1];
+
+    assertEquals("Not 'OK' button", MessageManager.getString("action.ok"),
+            ((JButton) jb1).getText());
+    assertEquals("Wrong button font", JvSwingUtils.getLabelFont(),
+            jb1.getFont());
+
+    assertEquals("Not 'Cancel' button",
+            MessageManager.getString("action.cancel"),
+            ((JButton) jb2).getText());
+    assertEquals("Wrong button font", JvSwingUtils.getLabelFont(),
+            jb2.getFont());
+  }
+
+  /**
+   * Test 'Apply to' has 3 radio buttons enabled, 'Selected Sequences' selected,
+   * when there is a current selection group.
+   */
+  @Test
+  public void testBuildApplyToOptionsPanel_withSelectionGroup()
+  {
+    selectSequences(0, 2, 3);
+    testee = new AnnotationChooser(parentPanel);
+
+    JPanel jp = testee.buildApplyToOptionsPanel();
+    Component[] comps = jp.getComponents();
+    assertEquals("Not 3 radio buttons", 3, comps.length);
+
+    final Checkbox cb1 = (Checkbox) comps[0];
+    final Checkbox cb2 = (Checkbox) comps[1];
+    final Checkbox cb3 = (Checkbox) comps[2];
+
+    assertTrue("Not enabled", cb1.isEnabled());
+    assertTrue("Not enabled", cb2.isEnabled());
+    assertTrue("Not enabled", cb3.isEnabled());
+    assertEquals("Option not selected", cb2, cb2.getCheckboxGroup()
+            .getSelectedCheckbox());
+
+    // check state variables match checkbox selection
+    assertTrue(testee.isApplyToSelectedSequences());
+    assertFalse(testee.isApplyToUnselectedSequences());
+  }
+
+  /**
+   * Add a sequence group to the alignment with the specified sequences (base 0)
+   * in it
+   * 
+   * @param i
+   * @param more
+   */
+  private void selectSequences(int... selected)
+  {
+    SequenceI[] seqs = parentPanel.getAlignment().getSequencesArray();
+    SequenceGroup sg = new SequenceGroup();
+    for (int i : selected)
+    {
+      sg.addSequence(seqs[i], false);
+    }
+    parentPanel.av.setSelectionGroup(sg);
+  }
+
+  /**
+   * Test 'Apply to' has 1 radio button enabled, 'All Sequences' selected, when
+   * there is no current selection group.
+   */
+  @Test
+  public void testBuildApplyToOptionsPanel_noSelectionGroup()
+  {
+    testee = new AnnotationChooser(parentPanel);
+    JPanel jp = testee.buildApplyToOptionsPanel();
+    verifyApplyToOptionsPanel_noSelectionGroup(jp);
+  }
+
+  protected void verifyApplyToOptionsPanel_noSelectionGroup(JPanel jp)
+  {
+    assertTrue("Wrong layout", jp.getLayout() instanceof FlowLayout);
+    Component[] comps = jp.getComponents();
+    assertEquals("Not 3 radio buttons", 3, comps.length);
+
+    final Checkbox cb1 = (Checkbox) comps[0];
+    final Checkbox cb2 = (Checkbox) comps[1];
+    final Checkbox cb3 = (Checkbox) comps[2];
+
+    assertTrue("Not enabled", cb1.isEnabled());
+    assertFalse("Enabled", cb2.isEnabled());
+    assertFalse("Enabled", cb3.isEnabled());
+    assertEquals("Not selected", cb1, cb1.getCheckboxGroup()
+            .getSelectedCheckbox());
+
+    // check state variables match checkbox selection
+    assertTrue(testee.isApplyToSelectedSequences());
+    assertTrue(testee.isApplyToUnselectedSequences());
+
+    assertEquals("Wrong text",
+            MessageManager.getString("label.all_sequences"), cb1.getLabel());
+    assertEquals("Wrong text",
+            MessageManager.getString("label.selected_sequences"),
+            cb2.getLabel());
+    assertEquals("Wrong text",
+            MessageManager.getString("label.except_selected_sequences"),
+            cb3.getLabel());
+  }
+
+  /**
+   * Test Show and Hide radio buttons created, with Hide initially selected.
+   */
+  @Test
+  public void testBuildShowHidePanel()
+  {
+    testee = new AnnotationChooser(parentPanel);
+    JPanel jp = testee.buildShowHidePanel();
+    verifyShowHidePanel(jp);
+
+  }
+
+  protected void verifyShowHidePanel(JPanel jp)
+  {
+    assertTrue("Wrong layout", jp.getLayout() instanceof FlowLayout);
+    Component[] comps = jp.getComponents();
+    assertEquals("Not 2 radio buttons", 2, comps.length);
+
+    final Checkbox cb1 = (Checkbox) comps[0];
+    final Checkbox cb2 = (Checkbox) comps[1];
+
+    assertTrue("Show not enabled", cb1.isEnabled());
+    assertTrue("Hide not enabled", cb2.isEnabled());
+
+    // Hide (button 2) selected; note this may change to none (null)
+    assertEquals("Not selected", cb2, cb2.getCheckboxGroup()
+            .getSelectedCheckbox());
+
+    assertTrue("Show is flagged", !testee.isShowSelected());
+
+    assertEquals("Wrong text",
+            MessageManager.getString("label.show_selected_annotations"),
+            cb1.getLabel());
+    assertEquals("Wrong text",
+            MessageManager.getString("label.hide_selected_annotations"),
+            cb2.getLabel());
+  }
+
+  /**
+   * Test construction of panel containing two sub-panels
+   */
+  @Test
+  public void testBuildShowHideOptionsPanel()
+  {
+    testee = new AnnotationChooser(parentPanel);
+    JPanel jp = testee.buildShowHideOptionsPanel();
+    assertTrue("Wrong layout", jp.getLayout() instanceof BorderLayout);
+    Component[] comps = jp.getComponents();
+    assertEquals("Not 2 sub-panels", 2, comps.length);
+
+    verifyShowHidePanel((JPanel) comps[0]);
+    verifyApplyToOptionsPanel_noSelectionGroup((JPanel) comps[1]);
+  }
+
+  /**
+   * Test that annotation types are (uniquely) identified.
+   * 
+   */
+  @Test
+  public void testGetAnnotationTypes()
+  {
+    selectSequences(1);
+    testee = new AnnotationChooser(parentPanel);
+    // selection group should make no difference to the result
+    // as all annotation types for the alignment are considered
+
+    List<String> types = AnnotationChooser.getAnnotationTypes(
+            parentPanel.getAlignment(), true);
+    assertEquals("Not two annotation types", 2, types.size());
+    assertTrue("IUPRED missing", types.contains("IUPRED"));
+    assertTrue("JMol missing", types.contains("JMol"));
+
+    types = AnnotationChooser.getAnnotationTypes(
+            parentPanel.getAlignment(), false);
+    assertEquals("Not six annotation types", 6, types.size());
+    assertTrue("IUPRED missing", types.contains("IUPRED"));
+    assertTrue("JMol missing", types.contains("JMol"));
+    assertTrue("Beauty missing", types.contains("Beauty"));
+    // These are added by viewmodel.AlignViewport.initAutoAnnotation():
+    assertTrue("Consensus missing", types.contains("Consensus"));
+    assertTrue("Quality missing", types.contains("Quality"));
+    assertTrue("Conservation missing", types.contains("Conservation"));
+  }
+
+  /**
+   * Test result of selecting an annotation type, with 'Hide for all sequences'.
+   * 
+   * We expect all annotations of that type to be set hidden. Other annotations
+   * should be left visible.
+   */
+  @Test
+  public void testSelectType_hideForAll()
+  {
+    selectSequences(1, 2);
+    testee = new AnnotationChooser(parentPanel);
+    final Checkbox hideCheckbox = (Checkbox) getComponent(testee, 1, 0, 1);
+    setSelected(hideCheckbox, true);
+
+    final Checkbox allSequencesCheckbox = (Checkbox) getComponent(testee,
+            1, 1, 0);
+    setSelected(allSequencesCheckbox, true);
+
+    AlignmentAnnotation[] anns = parentPanel.getAlignment()
+            .getAlignmentAnnotation();
+
+    assertTrue(anns[5].visible); // JMol for seq3
+    assertTrue(anns[7].visible); // JMol for seq1
+
+    setSelected(getTypeCheckbox("JMol"), true);
+    assertTrue(anns[0].visible); // Conservation
+    assertTrue(anns[1].visible); // Quality
+    assertTrue(anns[2].visible); // Consensus
+    assertTrue(anns[3].visible); // IUPred for seq0
+    assertTrue(anns[4].visible); // Beauty
+    assertFalse(anns[5].visible); // JMol for seq3 - not selected but hidden
+    assertTrue(anns[6].visible); // IUPRED for seq2
+    assertFalse(anns[7].visible); // JMol for seq1 - selected and hidden
+  }
+
+  /**
+   * Test result of selecting an annotation type, with 'Hide for selected
+   * sequences'.
+   * 
+   * We expect the annotations of that type, linked to the sequence group, to be
+   * set hidden. Other annotations should be left visible.
+   */
+  @Test
+  public void testSelectType_hideForSelected()
+  {
+    selectSequences(1, 2);
+    testee = new AnnotationChooser(parentPanel);
+    final Checkbox hideCheckbox = (Checkbox) getComponent(testee, 1, 0, 1);
+    setSelected(hideCheckbox, true);
+
+    /*
+     * Don't set the 'selected sequences' radio button since this would trigger
+     * an update, including unselected sequences / annotation types
+     */
+    // setSelected(getSelectedSequencesCheckbox());
+
+    AlignmentAnnotation[] anns = parentPanel.getAlignment()
+            .getAlignmentAnnotation();
+
+    assertTrue(anns[7].visible); // JMol for seq1
+
+    setSelected(getTypeCheckbox("JMol"), true);
+    assertTrue(anns[0].visible); // Conservation
+    assertTrue(anns[1].visible); // Quality
+    assertTrue(anns[2].visible); // Consensus
+    assertTrue(anns[3].visible); // IUPred for seq0
+    assertTrue(anns[4].visible); // Beauty
+    assertTrue(anns[5].visible); // JMol for seq3 not in selection group
+    assertTrue(anns[6].visible); // IUPRED for seq2
+    assertFalse(anns[7].visible); // JMol for seq1 in selection group
+  }
+
+  /**
+   * Test result of deselecting an annotation type, with 'Hide for all
+   * sequences'.
+   * 
+   * We expect all annotations of that type to be set visible. Other annotations
+   * should be left unchanged.
+   */
+  @Test
+  public void testDeselectType_hideForAll()
+  {
+    selectSequences(1, 2);
+    testee = new AnnotationChooser(parentPanel);
+
+    final Checkbox hideCheckbox = (Checkbox) getComponent(testee, 1, 0, 1);
+    setSelected(hideCheckbox, true);
+
+    final Checkbox allSequencesCheckbox = (Checkbox) getComponent(testee,
+            1, 1, 0);
+    setSelected(allSequencesCheckbox, true);
+
+    AlignmentAnnotation[] anns = parentPanel.getAlignment()
+            .getAlignmentAnnotation();
+
+    final Checkbox typeCheckbox = getTypeCheckbox("JMol");
+
+    // select JMol - all hidden
+    setSelected(typeCheckbox, true);
+    assertFalse(anns[5].visible); // JMol for seq3
+    assertFalse(anns[7].visible); // JMol for seq1
+
+    // deselect JMol - all unhidden
+    setSelected(typeCheckbox, false);
+    assertTrue(anns[0].visible); // Conservation
+    assertTrue(anns[1].visible); // Quality
+    assertTrue(anns[2].visible); // Consensus
+    assertTrue(anns[3].visible); // IUPred for seq0
+    assertTrue(anns[4].visible); // Beauty
+    assertTrue(anns[5].visible); // JMol for seq3
+    assertTrue(anns[6].visible); // IUPRED for seq2
+    assertTrue(anns[7].visible); // JMol for seq1
+  }
+
+  /**
+   * Test result of deselecting an annotation type, with 'Hide for selected
+   * sequences'.
+   * 
+   * We expect the annotations of that type, linked to the sequence group, to be
+   * set visible. Other annotations should be left unchanged.
+   */
+  @Test
+  public void testDeselectType_hideForSelected()
+  {
+    selectSequences(1, 2);
+    testee = new AnnotationChooser(parentPanel);
+    final Checkbox hideCheckbox = (Checkbox) getComponent(testee, 1, 0, 1);
+    setSelected(hideCheckbox, true);
+
+    /*
+     * Don't set the 'selected sequences' radio button since this would trigger
+     * an update, including unselected sequences / annotation types
+     */
+    // setSelected(getSelectedSequencesCheckbox());
+
+    setSelected(getTypeCheckbox("JMol"), true);
+    setSelected(getTypeCheckbox("JMol"), false);
+
+    AlignmentAnnotation[] anns = parentPanel.getAlignment()
+            .getAlignmentAnnotation();
+    assertTrue(anns[0].visible); // Conservation
+    assertTrue(anns[1].visible); // Quality
+    assertTrue(anns[2].visible); // Consensus
+    assertTrue(anns[3].visible); // IUPred for seq0
+    assertTrue(anns[4].visible); // Beauty
+    assertTrue(anns[5].visible); // JMol for seq3 not in selection group
+    assertTrue(anns[6].visible); // IUPRED for seq2
+    assertTrue(anns[7].visible); // JMol for seq1 in selection group
+  }
+
+  /**
+   * Test result of selecting an annotation type, with 'Show for all sequences'.
+   * 
+   * We expect all annotations of that type to be set visible. Other annotations
+   * should be left unchanged
+   */
+  @Test
+  public void testSelectType_showForAll()
+  {
+    selectSequences(1, 2);
+    testee = new AnnotationChooser(parentPanel);
+    final Checkbox showCheckbox = (Checkbox) getComponent(testee, 1, 0, 0);
+    final Checkbox hideCheckbox = (Checkbox) getComponent(testee, 1, 0, 1);
+
+    final Checkbox allSequencesCheckbox = (Checkbox) getComponent(testee,
+            1, 1, 0);
+
+    AlignmentAnnotation[] anns = parentPanel.getAlignment()
+            .getAlignmentAnnotation();
+
+    // hide all JMol annotations
+    setSelected(allSequencesCheckbox, true);
+    setSelected(hideCheckbox, true);
+    setSelected(getTypeCheckbox("JMol"), true);
+    assertFalse(anns[5].visible); // JMol for seq3
+    assertFalse(anns[7].visible); // JMol for seq1
+    // ...now show them...
+    setSelected(showCheckbox, true);
+    assertTrue(anns[0].visible); // Conservation
+    assertTrue(anns[1].visible); // Quality
+    assertTrue(anns[2].visible); // Consensus
+    assertTrue(anns[3].visible); // IUPred for seq0
+    assertTrue(anns[4].visible); // Beauty
+    assertTrue(anns[5].visible); // JMol for seq3
+    assertTrue(anns[6].visible); // IUPRED for seq2
+    assertTrue(anns[7].visible); // JMol for seq1
+  }
+
+  /**
+   * Test result of selecting an annotation type, with 'Show for selected
+   * sequences'.
+   * 
+   * We expect all annotations of that type, linked to the sequence group, to be
+   * set visible. Other annotations should be left unchanged
+   */
+  @Test
+  public void testSelectType_showForSelected()
+  {
+    selectSequences(1, 2);
+    testee = new AnnotationChooser(parentPanel);
+    final Checkbox showCheckbox = (Checkbox) getComponent(testee, 1, 0, 0);
+    final Checkbox hideCheckbox = (Checkbox) getComponent(testee, 1, 0, 1);
+
+    final Checkbox selectedSequencesCheckbox = (Checkbox) getComponent(
+            testee, 1, 1, 1);
+
+    AlignmentAnnotation[] anns = parentPanel.getAlignment()
+            .getAlignmentAnnotation();
+
+    // hide all JMol annotations in the selection region (== annotation 7)
+    setSelected(selectedSequencesCheckbox, true);
+    setSelected(hideCheckbox, true);
+    setSelected(getTypeCheckbox("JMol"), true);
+    assertTrue(anns[5].visible); // JMol for seq3
+    assertFalse(anns[7].visible); // JMol for seq1
+    // ...now show them...
+    setSelected(showCheckbox, true);
+
+    assertTrue(anns[0].visible); // Conservation
+    assertTrue(anns[1].visible); // Quality
+    assertTrue(anns[2].visible); // Consensus
+    assertTrue(anns[3].visible); // IUPred for seq0
+    assertTrue(anns[4].visible); // Beauty
+    assertTrue(anns[5].visible); // JMol for seq3
+    assertTrue(anns[6].visible); // IUPRED for seq2
+    assertTrue(anns[7].visible); // JMol for seq1
+  }
+
+  /**
+   * Test result of deselecting an annotation type, with 'Show for all
+   * sequences'.
+   * 
+   * We expect all annotations of that type to be set hidden. Other annotations
+   * should be left unchanged.
+   */
+  @Test
+  public void testDeselectType_showForAll()
+  {
+    selectSequences(1, 2);
+    testee = new AnnotationChooser(parentPanel);
+
+    final Checkbox showCheckbox = (Checkbox) getComponent(testee, 1, 0, 0);
+    setSelected(showCheckbox, true);
+
+    final Checkbox allSequencesCheckbox = (Checkbox) getComponent(testee,
+            1, 1, 0);
+    setSelected(allSequencesCheckbox, true);
+
+    AlignmentAnnotation[] anns = parentPanel.getAlignment()
+            .getAlignmentAnnotation();
+
+    final Checkbox typeCheckbox = getTypeCheckbox("JMol");
+    // select JMol - all shown
+    setSelected(typeCheckbox, true);
+    assertTrue(anns[5].visible); // JMol for seq3
+    assertTrue(anns[7].visible); // JMol for seq1
+
+    // deselect JMol - all hidden
+    setSelected(typeCheckbox, false);
+    assertTrue(anns[0].visible); // Conservation
+    assertTrue(anns[1].visible); // Quality
+    assertTrue(anns[2].visible); // Consensus
+    assertTrue(anns[3].visible); // IUPred for seq0
+    assertTrue(anns[4].visible); // Beauty
+    assertFalse(anns[5].visible); // JMol for seq3
+    assertTrue(anns[6].visible); // IUPRED for seq2
+    assertFalse(anns[7].visible); // JMol for seq1
+  }
+
+  /**
+   * Test result of deselecting an annotation type, with 'Show for selected
+   * sequences'.
+   * 
+   * We expect the annotations of that type, linked to the sequence group, to be
+   * set hidden. Other annotations should be left unchanged.
+   */
+  @Test
+  public void testDeselectType_showForSelected()
+  {
+    selectSequences(1, 2);
+    testee = new AnnotationChooser(parentPanel);
+    final Checkbox showCheckbox = (Checkbox) getComponent(testee, 1, 0, 0);
+    setSelected(showCheckbox, true);
+
+    /*
+     * Don't set the 'selected sequences' radio button since this would trigger
+     * an update, including unselected sequences / annotation types
+     */
+    // setSelected(getSelectedSequencesCheckbox());
+
+    AlignmentAnnotation[] anns = parentPanel.getAlignment()
+            .getAlignmentAnnotation();
+
+    // select JMol - should remain visible
+    setSelected(getTypeCheckbox("JMol"), true);
+    assertTrue(anns[5].visible); // JMol for seq3
+    assertTrue(anns[7].visible); // JMol for seq1
+
+    // deselect JMol - should be hidden for selected sequences only
+    setSelected(getTypeCheckbox("JMol"), false);
+    assertTrue(anns[0].visible); // Conservation
+    assertTrue(anns[1].visible); // Quality
+    assertTrue(anns[2].visible); // Consensus
+    assertTrue(anns[3].visible); // IUPred for seq0
+    assertTrue(anns[4].visible); // Beauty
+    assertTrue(anns[5].visible); // JMol for seq3 not in selection group
+    assertTrue(anns[6].visible); // IUPRED for seq2
+    assertFalse(anns[7].visible); // JMol for seq1 in selection group
+  }
+
+  /**
+   * Helper method to drill down to a sub-component in a Container hierarchy.
+   * 
+   * @param cont
+   * @param i
+   * @param j
+   * @param k
+   * @return
+   */
+  public static Component getComponent(Container cont, int... positions)
+  {
+    Component comp = cont;
+    for (int i : positions)
+    {
+      comp = ((Container) comp).getComponent(i);
+    }
+    return comp;
+  }
+
+  /**
+   * Helper method to set or unset a checkbox and fire its action listener.
+   * 
+   * @param cb
+   * @param select
+   */
+  protected void setSelected(Checkbox cb, boolean select)
+  {
+    // TODO refactor to a test utility class
+    cb.setState(select);
+    // have to manually fire the action listener
+    cb.getItemListeners()[0].itemStateChanged(new ItemEvent(cb,
+            ItemEvent.ITEM_STATE_CHANGED, cb, select ? ItemEvent.SELECTED
+                    : ItemEvent.DESELECTED));
+  }
+
+  /**
+   * Helper method to drill down to the 'Annotation type' checkbox with given
+   * label.
+   * 
+   * @return
+   */
+  private Checkbox getTypeCheckbox(String forLabel)
+  {
+    Component[] cbs = ((JPanel) testee.getComponent(0)).getComponents();
+    for (Component comp : cbs)
+    {
+      final Checkbox cb = (Checkbox) comp;
+      if (cb.getLabel().equals(forLabel))
+      {
+        return cb;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Test isInActionScope for the case where the scope is selected sequences.
+   * Test cases include sequences in the selection group, and others not in the
+   * group.
+   */
+  @Test
+  public void testIsInActionScope_selectedScope()
+  {
+    // sequences 1 and 2 have annotations 4 and 3 respectively
+    selectSequences(1, 2);
+    testee = new AnnotationChooser(parentPanel);
+
+    final Checkbox selectedSequencesCheckbox = (Checkbox) getComponent(
+            testee, 1, 1, 1);
+    setSelected(selectedSequencesCheckbox, true);
+
+    AlignmentAnnotation[] anns = parentPanel.getAlignment()
+            .getAlignmentAnnotation();
+    // remember 3 annotations to skip (Conservation/Quality/Consensus)
+    assertFalse(testee.isInActionScope(anns[3]));
+    assertFalse(testee.isInActionScope(anns[4]));
+    assertFalse(testee.isInActionScope(anns[5]));
+    assertTrue(testee.isInActionScope(anns[6]));
+    assertTrue(testee.isInActionScope(anns[7]));
+  }
+
+  /**
+   * Test isInActionScope for the case where the scope is unselected sequences.
+   * Test cases include sequences in the selection group, and others not in the
+   * group.
+   */
+  @Test
+  public void testIsInActionScope_unselectedScope()
+  {
+    // sequences 1 and 2 have annotations 4 and 3 respectively
+    selectSequences(1, 2);
+    testee = new AnnotationChooser(parentPanel);
+
+    final Checkbox unselectedSequencesCheckbox = (Checkbox) getComponent(
+            testee, 1, 1, 2);
+    setSelected(unselectedSequencesCheckbox, true);
+
+    AlignmentAnnotation[] anns = parentPanel.getAlignment()
+            .getAlignmentAnnotation();
+    // remember 3 annotations to skip (Conservation/Quality/Consensus)
+    assertTrue(testee.isInActionScope(anns[3]));
+    assertTrue(testee.isInActionScope(anns[4]));
+    assertTrue(testee.isInActionScope(anns[5]));
+    assertFalse(testee.isInActionScope(anns[6]));
+    assertFalse(testee.isInActionScope(anns[7]));
+  }
+
+  /**
+   * Test that the reset method restores previous visibility flags.
+   */
+  @Test
+  public void testResetOriginalState()
+  {
+    testee = new AnnotationChooser(parentPanel);
+
+    AlignmentAnnotation[] anns = parentPanel.getAlignment()
+            .getAlignmentAnnotation();
+    // all start visible
+    for (int i = 0; i < anns.length; i++)
+    {
+      assertTrue(i + "'th sequence not visible", anns[i].visible);
+    }
+
+    final Checkbox hideCheckbox = (Checkbox) getComponent(testee, 1, 0, 1);
+    setSelected(hideCheckbox, true);
+
+    final Checkbox allSequencesCheckbox = (Checkbox) getComponent(testee,
+            1, 1, 0);
+    setSelected(allSequencesCheckbox, true);
+
+    setSelected(getTypeCheckbox("JMol"), true);
+    setSelected(getTypeCheckbox("IUPRED"), true);
+
+    assertTrue(anns[0].visible); // Conservation
+    assertTrue(anns[1].visible); // Quality
+    assertTrue(anns[2].visible); // Consensus
+    assertFalse(anns[3].visible); // IUPRED
+    assertTrue(anns[4].visible); // Beauty (not seq-related)
+    assertFalse(anns[5].visible); // JMol
+    assertFalse(anns[6].visible); // IUPRED
+    assertFalse(anns[7].visible); // JMol
+
+    // reset - should all be visible
+    testee.resetOriginalState();
+    for (int i = 0; i < anns.length; i++)
+    {
+      assertTrue(i + "'th sequence not visible", anns[i].visible);
+    }
+  }
+}
index a938dd6..0c25cdb 100644 (file)
@@ -5,7 +5,6 @@ import static org.junit.Assert.fail;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.function.Consumer;
 
 import org.junit.Test;
 
@@ -51,32 +50,40 @@ public class MinJabawsClientTests {
                        }
 
                        String jobid = msaservice.align(iseqs);
-                       if (jobid != null) {
-                               JobStatus js = null;
-                               do {
-                                       try {
-                                               Thread.sleep(500);
-                                       } catch (InterruptedException q) {
-                                       }
-                                       ;
-                                       js = msaservice.getJobStatus(jobid);
-                               } while (!js.equals(JobStatus.FAILED)
-                                               && !js.equals(JobStatus.CANCELLED)
-                                               && !js.equals(JobStatus.FINISHED));
-                               assertEquals("Trial alignment failed. State was " + js.name(),
-                                               js, JobStatus.FINISHED);
-                               assertEquals(
-                                               "Mismatch in number of input and result sequences - assume alignment service wasn't interacted with correctly",
-                                               msaservice.getResult(jobid).getSequences().size(),
-                                               iseqs.size());
-                               msaservice.getResult(jobid).getSequences()
-                                               .forEach(new Consumer<FastaSequence>() {
-                                                       @Override
-                                                       public void accept(FastaSequence t) {
-                                                               System.out.println(">"+t.getId());
-                                                               System.out.println(t.getFormattedFasta());
-                                                       }
-                                               });
+      if (jobid != null)
+      {
+        JobStatus js = null;
+        do
+        {
+          try
+          {
+            Thread.sleep(500);
+          } catch (InterruptedException q)
+          {
+          }
+          ;
+          js = msaservice.getJobStatus(jobid);
+        } while (!js.equals(JobStatus.FAILED)
+                && !js.equals(JobStatus.CANCELLED)
+                && !js.equals(JobStatus.FINISHED));
+        assertEquals("Trial alignment failed. State was " + js.name(), js,
+                JobStatus.FINISHED);
+        assertEquals(
+                "Mismatch in number of input and result sequences - assume alignment service wasn't interacted with correctly",
+                msaservice.getResult(jobid).getSequences().size(),
+                iseqs.size());
+        for (FastaSequence t : msaservice.getResult(jobid).getSequences())
+        {
+          System.out.println(">" + t.getId());
+          System.out.println(t.getFormattedFasta());
+        }
+        // .forEach(new Consumer<FastaSequence>() {
+        // @Override
+        // public void accept(FastaSequence t) {
+        // System.out.println(">"+t.getId());
+        // System.out.println(t.getFormattedFasta());
+        // }
+        // });
                        }
 
                }