Merge branch 'features/JAL-1264_showHideAnnotations' into forpush/JAL-674_dssp
authorJim Procter <j.procter@dundee.ac.uk>
Tue, 21 Oct 2014 10:10:52 +0000 (11:10 +0100)
committerJim Procter <j.procter@dundee.ac.uk>
Tue, 21 Oct 2014 10:10:52 +0000 (11:10 +0100)
EOL changes conflict with new lines from mungo's branch
Conflicts:
resources/lang/Messages.properties
src/jalview/datamodel/SequenceI.java

34 files changed:
.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
.settings/org.eclipse.jdt.ui.prefs [new file with mode: 0644]
help/html/features/annotation.html
help/html/io/fileformats.html
help/html/menus/alignmentMenu.html
help/html/menus/alwannotations.html
help/html/menus/alwview.html
help/html/menus/popupMenu.html
resources/lang/Messages.properties
src/jalview/datamodel/Alignment.java
src/jalview/datamodel/AlignmentI.java
src/jalview/datamodel/AlignmentOrder.java
src/jalview/datamodel/Sequence.java
src/jalview/datamodel/SequenceGroup.java
src/jalview/datamodel/SequenceI.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AnnotationChooser.java [new file with mode: 0644]
src/jalview/gui/AnnotationColourChooser.java
src/jalview/gui/AnnotationLabels.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/datamodel/AlignmentTest.java [new file with mode: 0644]
test/jalview/gui/AnnotationChooserTest.java [new file with mode: 0644]
test/jalview/gui/JAL1353bugdemo.java
test/jalview/gui/PopupMenuTest.java [new file with mode: 0644]
test/jalview/ws/jabaws/MinJabawsClientTests.java

diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..884491a
--- /dev/null
@@ -0,0 +1,285 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=1
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=next_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=next_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
+org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
+org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=4
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
+org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=8
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=76
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=2
+org.eclipse.jdt.core.formatter.use_on_off_tags=true
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
+org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644 (file)
index 0000000..1986e85
--- /dev/null
@@ -0,0 +1,62 @@
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_Jalview
+formatter_settings_version=12
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=false
+sp_cleanup.add_missing_override_annotations_interface_methods=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_functional_interfaces=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=true
+sp_cleanup.insert_inferred_type_arguments=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=true
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_redundant_type_arguments=true
+sp_cleanup.remove_trailing_whitespaces=false
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=true
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_blocks=true
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=true
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+sp_cleanup.use_type_arguments=false
index 8e9bcdf..49128c2 100755 (executable)
@@ -46,16 +46,23 @@ menu, which is obtained by clicking anywhere on the annotation row labels
 area (below the sequence ID area).
 </p>
 <ul>
-  <li>Add New Row<br>
+  <li><strong>Add New Row</strong><br>
     <em>Adds a new, named annotation row (a dialog box will pop up for you to 
     enter the label for the new row). </em> </li>
-  <li>Hide Row<br>
+  <li><strong>Edit Label/Description</strong><br>
+    <em>This opens a dialog where you can change the name (displayed label), or the description
+    (as shown on the label tooltip) of the clicked annotation. </em> </li>
+  <li><strong>Hide This Row</strong><br>
     <em>Hides the annotation row whose label was clicked in order to bring up 
     the menu.</em> </li>
-  <li>Delete Row<br>
+  <li><strong>Hide All <em>&lt;label&gt;</em></strong><br>
+    <em>Hides all annotation rows whose label matches the one clicked. 
+    (This option is only shown for annotations that relate to individual sequences, 
+    not for whole alignment annotations. Since Jalview 2.8.2.)</em> </li>
+  <li><strong>Delete This Row</strong><br>
     <em>Deletes the annotation row whose label was clicked in order to bring up 
     the menu.</em> </li>
-  <li>Show All Hidden Rows<br>
+  <li><strong>Show All Hidden Rows</strong><br>
     <em>Shows all hidden annotation rows.</em> </li>
           <li><strong>Export Annotation</strong> <em>(Application only)</em><br>
        <em>Annotations can be saved to file or output to a text window in either the 
index 35fe675..7bfc435 100755 (executable)
@@ -43,7 +43,7 @@ jalview tries to detect some text or formatting unique to one of the formats:
 <tr>
 <td width="17%">FASTA</td>
 <td width="60%">&gt;SequenceName<br>
-THISISASEQENCE<br></td>
+THISISASEQUENCE<br></td>
 <td width="23%">.fa, .fasta</td>
 </tr><tr><td width="17%">MSF</td>
 <td width="60%">!! AA_MULTIPLE_ALIGNMENT 1.0<br>
@@ -64,7 +64,7 @@ THISISASEQENCE<br></td>
 &gt;Seq2</td>
 <td width="23%">.blc</td>
 </tr><tr><td width="17%">PFAM</td>
-<td width="60%">SequenceName THISISASEQENCE</td>
+<td width="60%">SequenceName THISISASEQUENCE</td>
 <td width="23%">.pfam</td>
 </tr><tr>
 <td width="17%">Stockholm</td>
index f219269..a7cb733 100755 (executable)
                                </li>
                                <li><strong>Load Associated Tree<br> </strong><em>Jalview
                                                can <a href="../calculations/treeviewer.html">view trees</a>
-                                               stored in the Newick file format, and associate them with the
+                                                stored in the Newick file format, and associate them with the
                                                alignment. Note: the ids of the tree file and your alignment MUST
                                                be the same.</em></li>
                                <li><strong>Load Features / Annotations<br> </strong><em>Load
                                                conservation calculation, quality calculation and consensus values
                                                as bar charts. </em>
                                </li>
+                         <li><strong>Show All Annotations</strong><em><br>
+                           Show all available annotations on the alignment. You can selectively hide these from the <a href="./popupMenu.html">Popup</a> 
+                           or <a href="../features/annotation.html">Annotation</a> menus. (Since Jalview 2.8.2)</em></li>
+                         <li><strong>Hide All Annotations</strong><em><br>
+                           Hide all annotations on the alignment. (Since Jalview 2.8.2)</em></li>
                                <li><strong>Autocalculated Annotation<br> </strong><em>Settings
                                        for the display of autocalculated annotation.</em>
                                        <ul>
                                <li><strong>Show Sequence Features</strong><br> <em>Show
                                                or hide sequence features on this alignment.</em>
                                </li>
-                               <li><strong><a href="../features/featuresettings.html">Seqence
+                               <li><strong><a href="../features/featuresettings.html">Sequence
                                                        Feature Settings...</a> </strong><em><br> <em>Opens the
                                                        Sequence Feature Settings dialog box to control the colour and
                                                        display of sequence features on the alignment, and configure and
index 4b89049..7375e63 100755 (executable)
       <li><strong> Add New Row</strong><br>
         <em>Adds a new, named annotation row (a dialog box will pop up for you 
         to enter the label for the new row). </em> </li>
-      <li><strong>Hide Row</strong><br>
-        <em>Hides the annotation row whose label was clicked in order to bring 
-        up the menu.</em> </li>
+         <li><strong>Edit Label/Description</strong><br>
+           <em>This opens a dialog where you can change the name (displayed label), or the description
+           (as shown on the label tooltip) of the clicked annotation. </em> </li>
+         <li><strong>Hide This Row</strong><br>
+           <em>Hides the annotation row whose label was clicked in order to bring up 
+           the menu.</em> </li>
+         <li><strong>Hide All <em>&lt;label&gt;</em></strong><br>
+           <em>Hides all annotation rows whose label matches the one clicked. 
+           (This option is only shown for annotations that relate to individual sequences, 
+           not for whole alignment annotations. Since Jalview 2.8.2.)</em> </li>
       <li><strong>Delete Row</strong><br>
         <em>Deletes the annotation row whose label was clicked in order to bring 
         up the menu.</em> </li>
index 3d2d3be..cb38708 100755 (executable)
     </strong><em>If this is selected the &quot;Annotation Panel&quot; will be 
     displayed below the alignment. The default setting is to display the conservation 
     calculation, quality calculation and consensus values as bar charts. </em></li>
+  <li><strong>Show All Annotations</strong><em><br>
+    Show all available annotations on the alignment. You can selectively hide these from the <a href="./popupMenu.html">Popup</a> 
+    &nbsp;or <a href="../features/annotation.html">Annotation</a>&nbsp;menus. (Since Jalview 2.8.2)</em></li>
+  <li><strong>Hide All Annotations</strong><em><br>
+    Hide all annotations on the alignment. (Since Jalview 2.8.2)</em></li>
     <li><strong>Autocalculated Annotation<br></strong>Settings for the display of autocalculated annotation.
     <ul><li>
        <strong>Apply to all groups<br></strong>
@@ -77,7 +82,7 @@
   </li>
   <li><strong>Show Sequence Features</strong><br>
     <em>Show or hide sequence features on this alignment.</em></li>
-  <li><strong><a href="../features/featuresettings.html">Seqence Feature Settings...</a></strong><em><br>
+  <li><strong><a href="../features/featuresettings.html">Sequence Feature Settings...</a></strong><em><br>
     Opens the Sequence Feature Settings dialog box to control the colour and display 
     of sequence features on the alignment, and configure and retrieve features 
     from DAS annotation servers.</em></li>
index e28c7e1..511b85f 100755 (executable)
@@ -31,14 +31,24 @@ not be accessible when in 'Cursor Mode' (toggled with the F2 key).</em></p>
 <ul>
   <li><strong>Selection</strong> 
     <ul>
-      <li><a name="sqreport"><strong>Sequence Details ...<br>
+      <li><a name="sqreport"><strong>Sequence Details...<br>
           </strong></a><em>(Since Jalview 2.8)<br>Open an <a href="../io/exportseqreport.html">HTML report containing the annotation
-            and database cross references</a> normally shown in the sequence's
+            and database cross references</a>&nbsp;normally shown in the sequence's
             tooltip.</em></li>
+      <li><strong>Show Annotations...<br>
+          </strong><em>Choose to show (unhide) either All or 
+          a selected type of annotation for the selected sequences. (Since Jalview 2.8.2)</em></li>
+      <li><strong>Hide Annotations...<br>
+          </strong><em>Choose to hide either All or 
+          a selected type of annotation for the selected sequences. (Since Jalview 2.8.2)</em></li>
+      <li><strong>Add Reference Annotations...<br>
+          </strong><em>Add to the alignment window any annotations on the selected sequences
+          which have been read from reference sources or calculated (for example, 
+          secondary structure derived from 3D structure). (Since Jalview 2.8.2)</em></li>
       <li><strong>Edit </strong> 
         <ul>
           <li><strong>Copy</strong><br>
-            <em>Copys the selected region. In the applet version, the copied sequences 
+            <em>Copies the selected region. In the applet version, the copied sequences 
             are not available to the system clipboard.</em></li>
           <li><strong>Cut<br>
             </strong><em>Cuts the selected region from the alignment. In the applet 
@@ -186,9 +196,7 @@ not be accessible when in 'Cursor Mode' (toggled with the F2 key).</em></p>
     (The View representative structures option was introduced in
         Jalview 2.8.1)</em></li>
   </ul>
-  <br> <li>
-      
-      </li>
+  <br> 
     </ul>
   </li>
   <li><strong>Hide Sequences</strong><br>
index 0f935ca..33109ce 100644 (file)
@@ -198,6 +198,12 @@ label.tcoffee_scores = T-Coffee Scores
 label.average_distance_bloslum62 = Average Distance Using BLOSUM62
 label.neighbour_blosum62 = Neighbour Joining Using BLOSUM62
 label.show_annotations = Show annotations
+label.hide_annotations = Hide annotations
+label.show_all_annotations = Show all annotations
+label.hide_all_annotations = Hide all annotations
+label.hide_all = Hide all
+label.add_reference_annotations = Add reference annotations
+label.find_tip = Search alignment, selection or sequence ids for a subsequence (ignoring gaps).<br>Accepts regular expressions - search Help for 'regex' for details.
 label.colour_text = Colour Text
 label.show_non_conversed = Show nonconserved
 label.overview_window = Overview Window
@@ -1123,4 +1129,11 @@ label.news_from_jalview = News from http://www.jalview.org
 label.cut_paste_alignmen_file = Cut & Paste Alignment File
 label.enter_redundancy_thereshold = Enter the redundancy thereshold
 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>
-label.select_feature_colour = Select Feature Colour
\ No newline at end of file
+label.select_feature_colour = Select Feature Colour
+label.delete_all = Delete all sequences
+warn.delete_all = <html>Deleting all sequences will close the alignment window.<br>Confirm deletion or Cancel.
+label.add_annotations_for = Add annotations for
+label.choose_annotations = Choose annotations
+label.find = Find
+label.invalid_search = Search string invalid
+error.invalid_regex = Invalid regular expression
index 5e75725..b2d4f0f 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
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 945a9d4..f628699 100755 (executable)
@@ -22,7 +22,9 @@ package jalview.datamodel;
 
 import jalview.analysis.AlignSeq;
 
+import java.util.ArrayList;
 import java.util.Enumeration;
+import java.util.List;
 import java.util.Vector;
 
 import fr.orsay.lri.varna.models.rna.RNA;
@@ -901,7 +903,7 @@ public class Sequence implements SequenceI
     AlignmentAnnotation[] ret = new AlignmentAnnotation[annotation.size()];
     for (int r = 0; r < ret.length; r++)
     {
-      ret[r] = (AlignmentAnnotation) annotation.elementAt(r);
+      ret[r] = annotation.elementAt(r);
     }
 
     return ret;
@@ -1080,6 +1082,33 @@ public class Sequence implements SequenceI
     return anns;
   }
 
+  /**
+   * Returns a list of any annotations on the sequence that match the given
+   * calcId (source) and label (type). Null values do not match.
+   * 
+   * @param calcId
+   * @param label
+   * @return
+   */
+  @Override
+  public List<AlignmentAnnotation> getAlignmentAnnotations(String calcId,
+          String label)
+  {
+    List<AlignmentAnnotation> result = new ArrayList<AlignmentAnnotation>();
+    if (annotation != null)
+    {
+      for (AlignmentAnnotation ann : annotation)
+      {
+        if (ann.calcId != null && ann.calcId.equals(calcId)
+                && ann.label != null && ann.label.equals(label))
+        {
+          result.add(ann);
+        }
+      }
+    }
+    return result;
+  }
+
   public boolean updatePDBIds()
   {
     if (datasetSequence != null)
index b4cb3b1..17348c2 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();
index 5c77940..2e68371 100755 (executable)
@@ -20,7 +20,7 @@
  */
 package jalview.datamodel;
 
-import java.util.Vector;
+import java.util.List;
 
 import fr.orsay.lri.varna.models.rna.RNA;
 
@@ -342,6 +342,17 @@ public interface SequenceI
   public AlignmentAnnotation[] getAnnotation(String label);
 
   /**
+   * Return a list of any annotations which match the given calcId (source) and
+   * label (type). Null values do not match.
+   * 
+   * @param calcId
+   * @param label
+   * @return
+   */
+  public List<AlignmentAnnotation> getAlignmentAnnotations(String calcId,
+          String label);
+
+  /**
    * create a new dataset sequence (if necessary) for this sequence and sets
    * this sequence to refer to it. This call will move any features or
    * references on the sequence onto the dataset. It will also make a duplicate
index c3d80d1..0f47cca 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);
@@ -4327,11 +4343,22 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           // object broker mechanism.
           final Vector<JMenu> wsmenu = new Vector<JMenu>();
           final IProgressIndicator af = me;
-          final JMenu msawsmenu = new JMenu(MessageManager.getString("label.alignment"));
-          final JMenu secstrmenu = new JMenu(MessageManager.getString("label.secondary_structure_prediction"));
-          final JMenu seqsrchmenu = new JMenu(MessageManager.getString("label.sequence_database_search"));
-          final JMenu analymenu = new JMenu(MessageManager.getString("label.analysis"));
-          final JMenu dismenu = new JMenu(MessageManager.getString("label.protein_disorder"));
+          final JMenu msawsmenu = new JMenu("Alignment");
+          final JMenu secstrmenu = new JMenu(
+                  "Secondary Structure Prediction");
+          final JMenu seqsrchmenu = new JMenu("Sequence Database Search");
+          final JMenu analymenu = new JMenu("Analysis");
+          final JMenu dismenu = new JMenu("Protein Disorder");
+          // final JMenu msawsmenu = new
+          // JMenu(MessageManager.getString("label.alignment"));
+          // final JMenu secstrmenu = new
+          // JMenu(MessageManager.getString("label.secondary_structure_prediction"));
+          // final JMenu seqsrchmenu = new
+          // JMenu(MessageManager.getString("label.sequence_database_search"));
+          // final JMenu analymenu = new
+          // JMenu(MessageManager.getString("label.analysis"));
+          // final JMenu dismenu = new
+          // JMenu(MessageManager.getString("label.protein_disorder"));
           // JAL-940 - only show secondary structure prediction services from
           // the legacy server
           if (// Cache.getDefault("SHOW_JWS1_SERVICES", true)
@@ -5308,6 +5335,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 +5718,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 fdb3975..0c29840 100755 (executable)
  */
 package jalview.gui;
 
-import java.util.*;
-import java.util.regex.Pattern;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.io.FormatAdapter;
+import jalview.util.MessageManager;
 
-import java.awt.*;
-import java.awt.datatransfer.*;
-import java.awt.event.*;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.MediaTracker;
+import java.awt.RenderingHints;
+import java.awt.Toolkit;
+import java.awt.datatransfer.StringSelection;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
 import java.awt.geom.AffineTransform;
-import java.awt.image.*;
-import javax.swing.*;
+import java.awt.image.BufferedImage;
+import java.util.Vector;
+import java.util.regex.Pattern;
 
-import jalview.datamodel.*;
-import jalview.io.*;
-import jalview.util.MessageManager;
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.SwingUtilities;
+import javax.swing.ToolTipManager;
 
 /**
  * DOCUMENT ME!
@@ -115,7 +138,7 @@ public class AnnotationLabels extends JPanel implements MouseListener,
     Graphics2D g = (Graphics2D) bi.getGraphics();
     g.rotate(Math.toRadians(90));
     g.drawImage(temp, 0, -bi.getWidth(this), this);
-    image = (Image) bi;
+    image = bi;
 
     addMouseListener(this);
     addMouseMotionListener(this);
@@ -249,11 +272,18 @@ public class AnnotationLabels extends JPanel implements MouseListener,
       aa[selectedRow].scaleColLabel = !aa[selectedRow].scaleColLabel;
     }
 
+    refresh();
+
+  }
+
+  /**
+   * Redraw sensibly.
+   */
+  protected void refresh()
+  {
     ap.validateAnnotationDimensions(false);
     ap.addNotify();
     ap.repaint();
-    // validate();
-    // ap.paintAlignment(true);
   }
 
   /**
@@ -480,7 +510,7 @@ public class AnnotationLabels extends JPanel implements MouseListener,
    */
   public void mouseClicked(MouseEvent evt)
   {
-    AlignmentAnnotation[] aa = ap.av.getAlignment()
+    final AlignmentAnnotation[] aa = ap.av.getAlignment()
             .getAlignmentAnnotation();
     if (SwingUtilities.isLeftMouseButton(evt))
     {
@@ -579,6 +609,35 @@ public class AnnotationLabels extends JPanel implements MouseListener,
     item = new JMenuItem(HIDE);
     item.addActionListener(this);
     pop.add(item);
+    // JAL-1264 hide all sequence-specific annotations of this type
+    final String label = aa[selectedRow].label;
+    if (selectedRow < aa.length)
+    {
+      if (aa[selectedRow].sequenceRef != null)
+      {
+        JMenuItem hideType = new JMenuItem();
+        String text = MessageManager.getString("label.hide_all") + " " + label;
+        hideType.setText(text);
+        hideType.addActionListener(new ActionListener()
+        {
+          @Override
+          public void actionPerformed(ActionEvent e)
+          {
+            for (AlignmentAnnotation ann : ap.av.getAlignment()
+                    .getAlignmentAnnotation())
+            {
+              if (ann.sequenceRef != null && ann.label != null
+                      && ann.label.equals(label))
+              {
+                ann.visible = false;
+              }
+            }
+            refresh();
+          }
+        });
+        pop.add(hideType);
+      }
+    }
     item = new JMenuItem(DELETE);
     item.addActionListener(this);
     pop.add(item);
@@ -608,7 +667,7 @@ public class AnnotationLabels extends JPanel implements MouseListener,
           pop.add(item);
         }
       }
-      else if (aa[selectedRow].label.indexOf("Consensus") > -1)
+      else if (label.indexOf("Consensus") > -1)
       {
         pop.addSeparator();
         // av and sequencegroup need to implement same interface for
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 662d7c6..693e6fe 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..78c1592 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.HashMap;
 import java.util.Hashtable;
 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();
@@ -285,20 +308,19 @@ public class PopupMenu extends JPopupMenu
 
           menuItem = new JMenuItem();
           menuItem.setText(pdb.getId());
-          menuItem.addActionListener(new java.awt.event.ActionListener()
+          menuItem.addActionListener(new ActionListener() 
           {
-            public void actionPerformed(ActionEvent e)
-            {
-              // TODO re JAL-860: optionally open dialog or provide a menu entry
-              // allowing user to open just one structure per sequence
-              // new AppJmol(pdb, ap.av.collateForPDB(new PDBEntry[]
-              // { pdb })[0], null, ap);
-              new StructureViewer(ap.getStructureSelectionManager())
-                      .viewStructures(pdb,
-                              ap.av.collateForPDB(new PDBEntry[]
-                              { pdb })[0], null, ap);
+            @Override
+            public void actionPerformed(ActionEvent e) {
+            // TODO re JAL-860: optionally open dialog or provide a menu entry
+            // allowing user to open just one structure per sequence
+            // new AppJmol(pdb, ap.av.collateForPDB(new PDBEntry[]
+            // { pdb })[0], null, ap);
+           new StructureViewer(ap.getStructureSelectionManager())
+                    .viewStructures(pdb,
+                            ap.av.collateForPDB(new PDBEntry[]
+                            { pdb })[0], null, ap);
             }
-
           });
           viewStructureMenu.add(menuItem);
 
@@ -335,8 +357,8 @@ public class PopupMenu extends JPopupMenu
                     "label.2d_rna_structure_line", new String[]
                     { structureLine }));
             menuItem.addActionListener(new java.awt.event.ActionListener()
-
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 // System.out.println("1:"+structureLine);
@@ -377,6 +399,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 +420,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 +436,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 +456,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 +478,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 +582,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 +796,307 @@ 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()
+  {
+    final SequenceGroup selectionGroup = ap.av.getSelectionGroup();
+    if (selectionGroup == null)
+    {
+      // this menu option is only for a selection
+      return;
+    }
+
+    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);
+
+    /*
+     * Find shown/hidden annotations types, distinguished by source (calcId),
+     * and grouped by graphGroup.
+     */
+    Map<String, List<List<String>>> shownTypes = new HashMap<String, List<List<String>>>();
+    Map<String, List<List<String>>> hiddenTypes = new HashMap<String, List<List<String>>>();
+    PopupMenu.getAnnotationTypesForShowHide(shownTypes, hiddenTypes,
+            visibleGraphGroups, annotations, selectionGroup);
+
+    for (String calcId : hiddenTypes.keySet())
+    {
+      for (List<String> type : hiddenTypes.get(calcId))
+      {
+        addAnnotationTypeToShowHide(showAnnotationsMenu, calcId, type,
+                false, true);
+      }
+    }
+
+    for (String calcId : shownTypes.keySet())
+    {
+      for (List<String> type : shownTypes.get(calcId))
+      {
+        addAnnotationTypeToShowHide(hideAnnotationsMenu, calcId, type,
+                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
+   *          a map, keyed by calcId (annotation source), whose entries are the
+   *          lists of annotation types found for the calcId; each annotation
+   *          type in turn may be a list (in the case of grouped annotations)
+   * @param hiddenTypes
+   *          a map, similar to shownTypes, but for hidden annotation types
+   * @param visibleGraphGroups
+   *          a lookup keyed by graphGroup identifier
+   * @param annotations
+   *          the annotations on the alignment to scan
+   * @param sequenceGroup
+   *          the sequence group to restrict search to
+   */
+  public static void getAnnotationTypesForShowHide(
+          Map<String, List<List<String>>> shownTypes,
+          Map<String, List<List<String>>> hiddenTypes,
+          BitSet visibleGraphGroups, AlignmentAnnotation[] annotations,
+          SequenceGroup sequenceGroup)
+  {
+    /*
+     * Build a lookup, by calcId (annotation source), of all annotation types in
+     * each graph group.
+     */
+    Map<String, Map<Integer, List<String>>> groupLabels = new HashMap<String, Map<Integer, List<String>>>();
+
+    // trackers for which calcId!label combinations we have dealt with
+    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)))
+      {
+        String calcId = aa.getCalcId();
+
+        /*
+         * Build a 'composite label' for types in line graph groups.
+         */
+        final List<String> labelAsList = new ArrayList<String>();
+        final String displayLabel = aa.label;
+        labelAsList.add(displayLabel);
+        if (aa.graph == AlignmentAnnotation.LINE_GRAPH
+                && aa.graphGroup > -1)
+        {
+          if (!groupLabels.containsKey(calcId))
+          {
+            groupLabels.put(calcId, new HashMap<Integer, List<String>>());
+          }
+          Map<Integer, List<String>> groupLabelsForCalcId = groupLabels
+                  .get(calcId);
+          if (groupLabelsForCalcId.containsKey(aa.graphGroup))
+          {
+            if (!groupLabelsForCalcId.get(aa.graphGroup).contains(
+                    displayLabel))
+            {
+              groupLabelsForCalcId.get(aa.graphGroup).add(displayLabel);
+            }
+          }
+          else
+          {
+            groupLabelsForCalcId.put(aa.graphGroup, labelAsList);
+          }
+        }
+        else
+        /*
+         * 'Simple case' - not a grouped annotation type - list of one label
+         * only
+         */
+        {
+          String rememberAs = calcId + "!" + displayLabel;
+          if (aa.visible && !addedToShown.contains(rememberAs))
+          {
+            if (!shownTypes.containsKey(calcId))
+            {
+              shownTypes.put(calcId, new ArrayList<List<String>>());
+            }
+            shownTypes.get(calcId).add(labelAsList);
+            addedToShown.add(rememberAs);
+          }
+          else
+          {
+            if (!aa.visible && !addedToHidden.contains(rememberAs))
+            {
+              if (!hiddenTypes.containsKey(calcId))
+              {
+                hiddenTypes.put(calcId, new ArrayList<List<String>>());
+              }
+              hiddenTypes.get(calcId).add(labelAsList);
+              addedToHidden.add(rememberAs);
+            }
+          }
+        }
+      }
+    }
+    /*
+     * finally add the 'composite group labels' to the appropriate lists,
+     * depending on whether the group is identified as visible or hidden
+     */
+    for (String calcId : groupLabels.keySet())
+    {
+      for (int group : groupLabels.get(calcId).keySet())
+      {
+        final List<String> groupLabel = groupLabels.get(calcId).get(group);
+        if (visibleGraphGroups.get(group))
+        {
+          if (!shownTypes.containsKey(calcId))
+          {
+            shownTypes.put(calcId, new ArrayList<List<String>>());
+          }
+          shownTypes.get(calcId).add(groupLabel);
+        }
+        else
+        {
+          if (!hiddenTypes.containsKey(calcId))
+          {
+            hiddenTypes.put(calcId, new ArrayList<List<String>>());
+          }
+          hiddenTypes.get(calcId).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 calcId
+   * @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,
+          String calcId, final List<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.setToolTipText(calcId);
+    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())
+    {
+      // TODO: select by calcId (source of annotation) as well as label
+      // e.g. by refactoring of buildAnnotationTypeMenus to as
+      // to construct the actionPerformed methods as the calcId/labels are found
+      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 +1269,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 +1311,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 +1348,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 +1359,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 +1390,7 @@ public class PopupMenu extends JPopupMenu
     sequenceSelDetails
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 sequenceSelectionDetails_actionPerformed();
@@ -1056,6 +1401,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 +1412,7 @@ public class PopupMenu extends JPopupMenu
     createGroupMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 createGroupMenuItem_actionPerformed();
@@ -1075,6 +1422,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 +1432,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 +1443,7 @@ public class PopupMenu extends JPopupMenu
     showBoxes.setState(true);
     showBoxes.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showBoxes_actionPerformed();
@@ -1103,6 +1453,7 @@ public class PopupMenu extends JPopupMenu
     showText.setState(true);
     showText.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showText_actionPerformed();
@@ -1111,6 +1462,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 +1473,7 @@ public class PopupMenu extends JPopupMenu
     displayNonconserved.setState(true);
     displayNonconserved.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showNonconserved_actionPerformed();
@@ -1130,6 +1483,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 +1492,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 +1501,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 +1510,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 +1519,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 +1530,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 +1565,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 +1574,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 +1582,16 @@ 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"));
+    configureReferenceAnnotationsMenu();
     sequenceFeature.setText(MessageManager
             .getString("label.create_sequence_feature"));
     sequenceFeature.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         sequenceFeature_actionPerformed();
@@ -1233,6 +1600,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 +1615,7 @@ public class PopupMenu extends JPopupMenu
             + "...");
     editSequence.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent actionEvent)
       {
         editSequence_actionPerformed(actionEvent);
@@ -1263,6 +1632,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 +1676,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 +1716,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 +1727,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 +1736,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 +1745,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 +1756,7 @@ public class PopupMenu extends JPopupMenu
     hydrophobicityColour
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 hydrophobicityColour_actionPerformed();
@@ -1386,6 +1765,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 +1775,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 +1784,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 +1793,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 +1803,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 +1813,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 +1823,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 +1832,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 +1843,7 @@ public class PopupMenu extends JPopupMenu
     purinePyrimidineColour
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 purinePyrimidineColour_actionPerformed();
@@ -1473,6 +1861,7 @@ public class PopupMenu extends JPopupMenu
     conservationMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 conservationMenuItem_actionPerformed();
@@ -1480,6 +1869,138 @@ public class PopupMenu extends JPopupMenu
             });
   }
 
+  /**
+   * Check for any annotations on the underlying dataset sequences (for the
+   * current selection group) which are not on the alignment. If any are found,
+   * enable the option to add them to the alignment. The criteria for 'on the
+   * alignment' is finding an annotation that matches on
+   * sequenceRef.datasetSequence, calcId and label.
+   */
+  protected void configureReferenceAnnotationsMenu()
+  {
+    addDatasequenceAnnotations.setText(MessageManager
+            .getString("label.add_reference_annotations"));
+    addDatasequenceAnnotations.setEnabled(false);
+
+    /*
+     * Temporary store so we can write distinct calcId / type pairs on the
+     * tooltip.
+     */
+    Map<String, String> tipEntries = new HashMap<String, String>();
+    StringBuilder tooltip = new StringBuilder(64);
+    tooltip.append(MessageManager.getString("label.add_annotations_for"));
+
+    // this menu option only applies for a Selection
+    if (this.ap.av.getSelectionGroup() == null)
+    {
+      return;
+    }
+
+    /*
+     * For each sequence selected in the alignment, make a list of any
+     * annotations on the underlying dataset sequence which are not already on
+     * the sequence in the alignment.
+     * 
+     * Build a map of { alignmentSequence, <List of annotations to add> }
+     */
+    final Map<SequenceI, List<AlignmentAnnotation>> candidates = new HashMap<SequenceI, List<AlignmentAnnotation>>();
+    for (SequenceI seq : this.ap.av.getSelectionGroup().getSequences())
+    {
+      SequenceI dataset = seq.getDatasetSequence();
+      if (dataset == null)
+      {
+        continue;
+      }
+      AlignmentAnnotation[] datasetAnnotations = dataset.getAnnotation();
+      if (datasetAnnotations == null)
+      {
+        continue;
+      }
+      final List<AlignmentAnnotation> result = new ArrayList<AlignmentAnnotation>();
+      for (AlignmentAnnotation dsann : datasetAnnotations)
+      {
+        /*
+         * If the sequence has no annotation that matches this one, then add
+         * this one to the results list.
+         */
+        if (seq.getAlignmentAnnotations(dsann.getCalcId(), dsann.label)
+                .isEmpty())
+        {
+          result.add(dsann);
+          tipEntries.put(dsann.getCalcId(), dsann.label);
+        }
+      }
+      /*
+       * Save any addable annotations for this sequence
+       */
+      if (!result.isEmpty())
+      {
+        candidates.put(seq, result);
+      }
+    }
+    if (!candidates.isEmpty())
+    {
+      /*
+       * Found annotations that could be added. Enable the menu item, and
+       * configure its tooltip and action.
+       */
+      addDatasequenceAnnotations.setEnabled(true);
+      for (String calcId : tipEntries.keySet())
+      {
+        tooltip.append("<br/>" + calcId + "/" + tipEntries.get(calcId));
+      }
+      String tooltipText = JvSwingUtils.wrapTooltip(true,
+              tooltip.toString());
+      addDatasequenceAnnotations.setToolTipText(tooltipText);
+
+      addDatasequenceAnnotations.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          addReferenceAnnotations_actionPerformed(candidates);
+        }
+      });
+    }
+  }
+
+  /**
+   * Add annotations to the sequences and to the alignment.
+   * 
+   * @param candidates
+   *          a map whose keys are sequences on the alignment, and values a list
+   *          of annotations to add to each sequence
+   */
+  protected void addReferenceAnnotations_actionPerformed(
+          Map<SequenceI, List<AlignmentAnnotation>> candidates)
+  {
+    for (SequenceI seq : candidates.keySet())
+    {
+      for (AlignmentAnnotation ann : candidates.get(seq))
+      {
+        AlignmentAnnotation copyAnn = new AlignmentAnnotation(ann);
+        int startRes = 0;
+        int endRes = ann.annotations.length;
+        final SequenceGroup selectionGroup = this.ap.av.getSelectionGroup();
+        if (selectionGroup != null)
+        {
+          startRes = selectionGroup.getStartRes();
+          endRes = selectionGroup.getEndRes();
+        }
+        copyAnn.restrict(startRes, endRes);
+
+        // add to the sequence (sets correct copyAnn.datasetSequence)
+        seq.addAlignmentAnnotation(copyAnn);
+        // adjust for gaps
+        copyAnn.adjustForAlignment();
+        // add to the alignment and set visible
+        this.ap.getAlignment().addAnnotation(copyAnn);
+        copyAnn.visible = true;
+      }
+    }
+    refresh();
+  }
+
   protected void sequenceSelectionDetails_actionPerformed()
   {
     createSequenceDetailsReport(ap.av.getSequenceSelection());
@@ -1721,6 +2242,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 +2642,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 +2705,7 @@ public class PopupMenu extends JPopupMenu
             : ap.av.getSequenceSelection());
     Thread discpdb = new Thread(new Runnable()
     {
+      @Override
       public void run()
       {
 
@@ -2255,7 +2790,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..afb0dc1 100755 (executable)
@@ -20,6 +20,8 @@
  */
 package jalview.jbgui;
 
+import jalview.bin.Cache;
+import jalview.gui.JvSwingUtils;
 import jalview.schemes.ColourSchemeProperty;
 import jalview.util.MessageManager;
 
@@ -302,6 +304,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 +377,7 @@ public class GAlignFrame extends JInternalFrame
 
         item.addActionListener(new java.awt.event.ActionListener()
         {
+          @Override
           public void actionPerformed(ActionEvent e)
           {
             outputText_actionPerformed(e);
@@ -381,6 +388,7 @@ public class GAlignFrame extends JInternalFrame
       }
     } catch (Exception e)
     {
+      System.err.println(e.toString());
     }
 
     if (!new jalview.util.Platform().isAMac())
@@ -407,6 +415,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 +440,7 @@ public class GAlignFrame extends JInternalFrame
               {
                 radioItem.addActionListener(new ActionListener()
                 {
+                  @Override
                   public void actionPerformed(ActionEvent evt)
                   {
                     userDefinedColour_actionPerformed(evt);
@@ -442,6 +452,7 @@ public class GAlignFrame extends JInternalFrame
         });
         radioItem.addActionListener(new ActionListener()
         {
+          @Override
           public void actionPerformed(ActionEvent evt)
           {
             userDefinedColour_actionPerformed(evt);
@@ -580,6 +591,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 +603,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 +622,7 @@ public class GAlignFrame extends JInternalFrame
     selectAllSequenceMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 selectAllSequenceMenuItem_actionPerformed(e);
@@ -621,6 +635,7 @@ public class GAlignFrame extends JInternalFrame
     deselectAllSequenceMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 deselectAllSequenceMenuItem_actionPerformed(e);
@@ -634,6 +649,7 @@ public class GAlignFrame extends JInternalFrame
     invertSequenceMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 invertSequenceMenuItem_actionPerformed(e);
@@ -643,6 +659,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 +685,7 @@ public class GAlignFrame extends JInternalFrame
     remove2LeftMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 remove2LeftMenuItem_actionPerformed(e);
@@ -681,6 +699,7 @@ public class GAlignFrame extends JInternalFrame
     remove2RightMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 remove2RightMenuItem_actionPerformed(e);
@@ -694,6 +713,7 @@ public class GAlignFrame extends JInternalFrame
     removeGappedColumnMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 removeGappedColumnMenuItem_actionPerformed(e);
@@ -708,6 +728,7 @@ public class GAlignFrame extends JInternalFrame
     removeAllGapsMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 removeAllGapsMenuItem_actionPerformed(e);
@@ -718,6 +739,7 @@ public class GAlignFrame extends JInternalFrame
     justifyLeftMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 justifyLeftMenuItem_actionPerformed(e);
@@ -728,6 +750,7 @@ public class GAlignFrame extends JInternalFrame
     justifyRightMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 justifyRightMenuItem_actionPerformed(e);
@@ -737,6 +760,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 +770,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 +782,7 @@ public class GAlignFrame extends JInternalFrame
     showNonconservedMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 showUnconservedMenuItem_actionPerformed(e);
@@ -767,6 +793,7 @@ public class GAlignFrame extends JInternalFrame
     sortPairwiseMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 sortPairwiseMenuItem_actionPerformed(e);
@@ -775,6 +802,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 +813,7 @@ public class GAlignFrame extends JInternalFrame
     sortLengthMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 sortLengthMenuItem_actionPerformed(e);
@@ -793,6 +822,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 +836,7 @@ public class GAlignFrame extends JInternalFrame
     removeRedundancyMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 removeRedundancyMenuItem_actionPerformed(e);
@@ -816,6 +847,7 @@ public class GAlignFrame extends JInternalFrame
     pairwiseAlignmentMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 pairwiseAlignmentMenuItem_actionPerformed(e);
@@ -825,6 +857,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 +868,7 @@ public class GAlignFrame extends JInternalFrame
     averageDistanceTreeMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 averageDistanceTreeMenuItem_actionPerformed(e);
@@ -845,6 +879,7 @@ public class GAlignFrame extends JInternalFrame
     neighbourTreeMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 neighbourTreeMenuItem_actionPerformed(e);
@@ -862,6 +897,7 @@ public class GAlignFrame extends JInternalFrame
 
     clustalColour.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         clustalColour_actionPerformed(e);
@@ -870,6 +906,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 +915,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 +926,7 @@ public class GAlignFrame extends JInternalFrame
     hydrophobicityColour
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 hydrophobicityColour_actionPerformed(e);
@@ -896,6 +935,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 +945,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 +954,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 +963,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 +973,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 +983,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 +993,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 +1002,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 +1014,7 @@ public class GAlignFrame extends JInternalFrame
     purinePyrimidineColour
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 purinePyrimidineColour_actionPerformed(e);
@@ -977,6 +1025,7 @@ public class GAlignFrame extends JInternalFrame
     RNAInteractionColour
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 RNAInteractionColour_actionPerformed(e);
@@ -994,6 +1043,7 @@ public class GAlignFrame extends JInternalFrame
     avDistanceTreeBlosumMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 avTreeBlosumMenuItem_actionPerformed(e);
@@ -1004,6 +1054,7 @@ public class GAlignFrame extends JInternalFrame
     njTreeBlosumMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 njTreeBlosumMenuItem_actionPerformed(e);
@@ -1012,21 +1063,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 +1112,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 +1122,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 +1135,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 +1148,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 +1159,7 @@ public class GAlignFrame extends JInternalFrame
     conservationMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 conservationMenuItem_actionPerformed(e);
@@ -1086,6 +1168,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 +1177,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 +1189,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 +1201,7 @@ public class GAlignFrame extends JInternalFrame
     renderGapsMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 renderGapsMenuItem_actionPerformed(e);
@@ -1125,8 +1211,11 @@ public class GAlignFrame extends JInternalFrame
     findMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(
             java.awt.event.KeyEvent.VK_F, Toolkit.getDefaultToolkit()
                     .getMenuShortcutKeyMask(), false));
+    findMenuItem.setToolTipText(JvSwingUtils.wrapTooltip(true,
+            MessageManager.getString("label.find_tip")));
     findMenuItem.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         findMenuItem_actionPerformed(e);
@@ -1136,6 +1225,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 +1235,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 +1252,7 @@ public class GAlignFrame extends JInternalFrame
     showDbRefsMenuitem.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showDbRefs_actionPerformed(e);
@@ -1172,6 +1264,7 @@ public class GAlignFrame extends JInternalFrame
     showNpFeatsMenuitem.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showNpFeats_actionPerformed(e);
@@ -1183,6 +1276,7 @@ public class GAlignFrame extends JInternalFrame
     showGroupConservation.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showGroupConservation_actionPerformed(e);
@@ -1195,6 +1289,7 @@ public class GAlignFrame extends JInternalFrame
     showGroupConsensus.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showGroupConsensus_actionPerformed(e);
@@ -1206,6 +1301,7 @@ public class GAlignFrame extends JInternalFrame
     showConsensusHistogram.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showConsensusHistogram_actionPerformed(e);
@@ -1217,6 +1313,7 @@ public class GAlignFrame extends JInternalFrame
     showSequenceLogo.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         showSequenceLogo_actionPerformed(e);
@@ -1228,6 +1325,7 @@ public class GAlignFrame extends JInternalFrame
     normaliseSequenceLogo.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         normaliseSequenceLogo_actionPerformed(e);
@@ -1241,6 +1339,7 @@ public class GAlignFrame extends JInternalFrame
     applyAutoAnnotationSettings.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         applyAutoAnnotationSettings_actionPerformed(e);
@@ -1251,6 +1350,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 +1376,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 +1388,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 +1401,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 +1414,7 @@ public class GAlignFrame extends JInternalFrame
 
     copy.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         copy_actionPerformed(e);
@@ -1322,16 +1426,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 +1449,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 +1461,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 +1471,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 +1479,7 @@ public class GAlignFrame extends JInternalFrame
     });
     createPNG.addActionListener(new java.awt.event.ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         createPNG(null);
@@ -1383,6 +1491,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 +1503,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 +1512,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 +1524,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 +1535,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 +1546,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 +1557,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 +1570,7 @@ public class GAlignFrame extends JInternalFrame
     centreColumnLabelsMenuItem
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 centreColumnLabels_actionPerformed(e);
@@ -1467,6 +1583,7 @@ public class GAlignFrame extends JInternalFrame
     followHighlightMenuItem.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         followHighlight_actionPerformed();
@@ -1478,6 +1595,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 +1606,7 @@ public class GAlignFrame extends JInternalFrame
     modifyConservation
             .addActionListener(new java.awt.event.ActionListener()
             {
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 modifyConservation_actionPerformed(e);
@@ -1498,15 +1617,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 +1639,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 +1666,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 +1676,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 +1686,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 +1696,7 @@ public class GAlignFrame extends JInternalFrame
             + "...");
     extractScores.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         extractScores_actionPerformed(e);
@@ -1586,6 +1715,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 +1725,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 +1736,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 +1747,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 +1758,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 +1770,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 +1786,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 +1802,7 @@ public class GAlignFrame extends JInternalFrame
     listenToViewSelections.setState(false);
     listenToViewSelections.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         listenToViewSelections_actionPerformed(e);
@@ -1677,6 +1814,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 +1823,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 +1832,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 +1842,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 +1852,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 +1865,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 +1876,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 +1889,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 +1901,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 +1911,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 +1922,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 +1934,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 +1958,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 +1966,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 +1976,7 @@ public class GAlignFrame extends JInternalFrame
     });
     tabbedPane.addMouseListener(new MouseAdapter()
     {
+      @Override
       public void mousePressed(MouseEvent e)
       {
         tabbedPane_mousePressed(e);
@@ -1832,6 +1984,7 @@ public class GAlignFrame extends JInternalFrame
     });
     tabbedPane.addFocusListener(new FocusAdapter()
     {
+      @Override
       public void focusGained(FocusEvent e)
       {
         tabbedPane_focusGained(e);
@@ -1843,6 +1996,7 @@ public class GAlignFrame extends JInternalFrame
                     .getMenuShortcutKeyMask(), false));
     save.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         save_actionPerformed(e);
@@ -1852,6 +2006,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 +2018,7 @@ public class GAlignFrame extends JInternalFrame
                     .getMenuShortcutKeyMask(), false));
     newView.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         newView_actionPerformed(e);
@@ -1875,6 +2031,7 @@ public class GAlignFrame extends JInternalFrame
             + "...");
     textColour.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         textColour_actionPerformed(e);
@@ -1886,6 +2043,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 +2055,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 +2067,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 +2077,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 +2087,7 @@ public class GAlignFrame extends JInternalFrame
             .getString("label.alignment_props") + "...");
     alignmentProperties.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent actionEvent)
       {
         alignmentProperties();
@@ -1989,6 +2151,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 +2271,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/datamodel/AlignmentTest.java b/test/jalview/datamodel/AlignmentTest.java
new file mode 100644 (file)
index 0000000..93170b7
--- /dev/null
@@ -0,0 +1,71 @@
+package jalview.datamodel;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import jalview.io.AppletFormatAdapter;
+
+import java.io.IOException;
+import java.util.Iterator;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Unit tests for Alignment datamodel.
+ * 
+ * @author gmcarstairs
+ *
+ */
+public class AlignmentTest
+{
+  // @formatter:off
+  private static final String TEST_DATA = 
+          "# STOCKHOLM 1.0\n" +
+          "#=GS D.melanogaster.1 AC AY119185.1/838-902\n" +
+          "#=GS D.melanogaster.2 AC AC092237.1/57223-57161\n" +
+          "#=GS D.melanogaster.3 AC AY060611.1/560-627\n" +
+          "D.melanogaster.1          G.AGCC.CU...AUGAUCGA\n" +
+          "#=GR D.melanogaster.1 SS  ................((((\n" +
+          "D.melanogaster.2          C.AUUCAACU.UAUGAGGAU\n" +
+          "#=GR D.melanogaster.2 SS  ................((((\n" +
+          "D.melanogaster.3          G.UGGCGCU..UAUGACGCA\n" +
+          "#=GR D.melanogaster.3 SS  (.(((...(....(((((((\n" +
+          "//";
+  // @formatter:on
+
+
+  private Alignment al;
+
+  /*
+   * Read in Stockholm format test data including secondary structure
+   * annotations.
+   */
+  @Before
+  public void setUp() throws IOException
+  {
+    al = new jalview.io.FormatAdapter().readFile(TEST_DATA,
+            AppletFormatAdapter.PASTE, "STH");
+    for (int i = 0; i < al.getSequencesArray().length; ++i)
+    {
+      al.addAnnotation(al.getSequenceAt(i).getAnnotation()[0]);
+      al.getSequenceAt(i).getAnnotation()[0].setCalcId("CalcIdFor"
+              + al.getSequenceAt(i).getName());
+    }
+  }
+
+  /**
+   * Test method that returns annotations that match on calcId.
+   */
+  @Test
+  public void testFindAnnotation_byCalcId()
+  {
+    Iterable<AlignmentAnnotation> anns = al
+            .findAnnotation("CalcIdForD.melanogaster.2");
+    Iterator<AlignmentAnnotation> iter = anns.iterator();
+    assertTrue(iter.hasNext());
+    AlignmentAnnotation ann = iter.next();
+    assertEquals("D.melanogaster.2", ann.sequenceRef.getName());
+    assertFalse(iter.hasNext());
+  }
+}
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 438a208..7acd843 100644 (file)
  */
 package jalview.gui;
 
-import static org.junit.Assert.*;
 import jalview.bin.Cache;
 
-import java.awt.Component;
 import java.awt.Dimension;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
@@ -35,11 +33,11 @@ import javax.swing.JFrame;
 import javax.swing.JInternalFrame;
 import javax.swing.JMenu;
 import javax.swing.JMenuItem;
-import javax.swing.JPanel;
 import javax.swing.JTextArea;
 
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
+import org.junit.Ignore;
 import org.junit.Test;
 
 public class JAL1353bugdemo
@@ -58,6 +56,8 @@ public class JAL1353bugdemo
   volatile boolean finish = false;
 
   @Test
+  @Ignore
+  // comment out @Ignore to enable this test
   public void test()
   {
     Cache.initLogger();
diff --git a/test/jalview/gui/PopupMenuTest.java b/test/jalview/gui/PopupMenuTest.java
new file mode 100644 (file)
index 0000000..64215bb
--- /dev/null
@@ -0,0 +1,319 @@
+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.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.io.AppletFormatAdapter;
+
+import java.io.IOException;
+import java.util.BitSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Unit tests for PopupMenu
+ * 
+ * @author gmcarstairs
+ *
+ */
+public class PopupMenuTest
+{
+  // 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";
+
+  private static final int SEQ_ANN_COUNT = 10;
+
+  private static final int AUTO_ANNS = 3;
+
+  AlignmentI alignment;
+
+  AlignmentPanel parentPanel;
+
+  @Before
+  public void setUp() throws IOException
+  {
+    AlignmentI al = new jalview.io.FormatAdapter().readFile(TEST_DATA,
+            AppletFormatAdapter.PASTE, "FASTA");
+    AlignFrame af = new AlignFrame(al, 700, 500);
+    parentPanel = new AlignmentPanel(af, af.getViewport());
+    alignment = parentPanel.getAlignment();
+
+    AlignmentAnnotation[] anns = new AlignmentAnnotation[SEQ_ANN_COUNT];
+    for (int i = 0; i < anns.length; i++)
+    {
+      anns[i] = new AlignmentAnnotation("Label" + i, null, 0d);
+      anns[i].setCalcId("CalcId" + i);
+      anns[i].visible = true;
+      alignment.addAnnotation(anns[i]);
+    }
+  }
+
+  /**
+   * Test method that determines visible graph groups.
+   */
+  @Test
+  public void testGetVisibleGraphGroups()
+  {
+    AlignmentAnnotation[] anns = alignment.getAlignmentAnnotation();
+    /*
+     * a bar graph group is not included
+     */
+    anns[0].graph = AlignmentAnnotation.BAR_GRAPH;
+    anns[0].graphGroup = 1;
+    anns[0].visible = true;
+
+    /*
+     * a line graph group is included as long as one of its members is visible
+     */
+    anns[1].graph = AlignmentAnnotation.LINE_GRAPH;
+    anns[1].graphGroup = 5;
+    anns[1].visible = false;
+    anns[2].graph = AlignmentAnnotation.LINE_GRAPH;
+    anns[2].graphGroup = 5;
+    anns[2].visible = true;
+
+    /*
+     * a line graph group with no visible rows is not included
+     */
+    anns[3].graph = AlignmentAnnotation.LINE_GRAPH;
+    anns[3].graphGroup = 3;
+    anns[3].visible = false;
+
+    // a visible line graph with no graph group is not included
+    anns[4].graph = AlignmentAnnotation.LINE_GRAPH;
+    anns[4].graphGroup = -1;
+    anns[4].visible = true;
+
+    BitSet result = PopupMenu.getVisibleLineGraphGroups(anns);
+    assertTrue(result.get(5));
+    assertFalse(result.get(0));
+    assertFalse(result.get(1));
+    assertFalse(result.get(2));
+    assertFalse(result.get(3));
+  }
+
+  /**
+   * Test a mixture of show/hidden annotations in/outside selection group.
+   */
+  @Test
+  public void testGetAnnotationTypesForShowHide_forSelectionGroup()
+  {
+    Map<String, List<List<String>>> shownTypes = new HashMap<String, List<List<String>>>();
+    Map<String, List<List<String>>> hiddenTypes = new HashMap<String, List<List<String>>>();
+    AlignmentAnnotation[] anns = alignment.getAlignmentAnnotation();
+    BitSet visibleGraphGroups = new BitSet();
+    selectSequences(0, 3);
+    SequenceI[] seqs = parentPanel.getAlignment().getSequencesArray();
+
+    /*
+     * Configure annotation properties for test (offsetting for auto-calculated
+     * rows).
+     */
+    // not in selection group (should be ignored):
+    // hidden annotation Label4 not in selection group
+    anns[AUTO_ANNS + 4].sequenceRef = seqs[2];
+    anns[AUTO_ANNS + 4].visible = false;
+    anns[AUTO_ANNS + 7].sequenceRef = seqs[1];
+    anns[AUTO_ANNS + 7].visible = true;
+
+    /*
+     * in selection group, hidden:
+     */
+    anns[AUTO_ANNS + 2].sequenceRef = seqs[3]; // CalcId2/Label2
+    anns[AUTO_ANNS + 2].visible = false;
+    anns[AUTO_ANNS + 3].sequenceRef = seqs[3]; // CalcId3/Label2
+    anns[AUTO_ANNS + 3].visible = false;
+    anns[AUTO_ANNS + 3].label = "Label2";
+    anns[AUTO_ANNS + 4].sequenceRef = seqs[3]; // CalcId2/Label3
+    anns[AUTO_ANNS + 4].visible = false;
+    anns[AUTO_ANNS + 4].label = "Label3";
+    anns[AUTO_ANNS + 4].setCalcId("CalcId2");
+    anns[AUTO_ANNS + 8].sequenceRef = seqs[0]; // CalcId9/Label9
+    anns[AUTO_ANNS + 8].visible = false;
+    anns[AUTO_ANNS + 8].label = "Label9";
+    anns[AUTO_ANNS + 8].setCalcId("CalcId9");
+    /*
+     * in selection group, visible
+     */
+    anns[AUTO_ANNS + 6].sequenceRef = seqs[0]; // CalcId6/Label6
+    anns[AUTO_ANNS + 6].visible = true;
+    anns[AUTO_ANNS + 9].sequenceRef = seqs[3]; // CalcId9/Label9
+    anns[AUTO_ANNS + 9].visible = true;
+
+    PopupMenu.getAnnotationTypesForShowHide(shownTypes, hiddenTypes,
+            visibleGraphGroups, anns, parentPanel.av.getSelectionGroup());
+
+    // check results; note CalcId9/Label9 is both hidden and shown (for
+    // different sequences) so should be in both
+    // shown: CalcId6/Label6 and CalcId9/Label9
+    assertEquals(2, shownTypes.size());
+    assertEquals(1, shownTypes.get("CalcId6").size());
+    assertEquals(1, shownTypes.get("CalcId6").get(0).size());
+    assertEquals("Label6", shownTypes.get("CalcId6").get(0).get(0));
+    assertEquals(1, shownTypes.get("CalcId9").size());
+    assertEquals(1, shownTypes.get("CalcId9").get(0).size());
+    assertEquals("Label9", shownTypes.get("CalcId9").get(0).get(0));
+
+    // hidden: CalcId2/Label2, CalcId2/Label3, CalcId3/Label2, CalcId9/Label9
+    assertEquals(3, hiddenTypes.size());
+    assertEquals(2, hiddenTypes.get("CalcId2").size());
+    assertEquals(1, hiddenTypes.get("CalcId2").get(0).size());
+    assertEquals("Label2", hiddenTypes.get("CalcId2").get(0).get(0));
+    assertEquals(1, hiddenTypes.get("CalcId2").get(1).size());
+    assertEquals("Label3", hiddenTypes.get("CalcId2").get(1).get(0));
+    assertEquals(1, hiddenTypes.get("CalcId3").size());
+    assertEquals(1, hiddenTypes.get("CalcId3").get(0).size());
+    assertEquals("Label2", hiddenTypes.get("CalcId3").get(0).get(0));
+    assertEquals(1, hiddenTypes.get("CalcId9").size());
+    assertEquals(1, hiddenTypes.get("CalcId9").get(0).size());
+    assertEquals("Label9", hiddenTypes.get("CalcId9").get(0).get(0));
+
+    consoleDebug(shownTypes, hiddenTypes);
+  }
+
+  /**
+   * This output is not part of the test but may help make sense of it...
+   * 
+   * @param shownTypes
+   * @param hiddenTypes
+   */
+  protected void consoleDebug(Map<String, List<List<String>>> shownTypes,
+          Map<String, List<List<String>>> hiddenTypes)
+  {
+    for (String calcId : shownTypes.keySet())
+    {
+      System.out.println("Visible annotation types for calcId=" + calcId);
+      for (List<String> type : shownTypes.get(calcId))
+      {
+        System.out.println("   " + type);
+      }
+    }
+    for (String calcId : hiddenTypes.keySet())
+    {
+      System.out.println("Hidden annotation types for calcId=" + calcId);
+      for (List<String> type : hiddenTypes.get(calcId))
+      {
+        System.out.println("   " + type);
+      }
+    }
+  }
+
+  /**
+   * Test case where there are 'grouped' annotations, visible and hidden, within
+   * and without the selection group.
+   */
+  @Test
+  public void testGetAnnotationTypesForShowHide_withGraphGroups()
+  {
+    final int GROUP_4 = 4;
+    final int GROUP_5 = 5;
+    final int GROUP_6 = 6;
+
+    Map<String, List<List<String>>> shownTypes = new HashMap<String, List<List<String>>>();
+    Map<String, List<List<String>>> hiddenTypes = new HashMap<String, List<List<String>>>();
+    AlignmentAnnotation[] anns = alignment.getAlignmentAnnotation();
+    BitSet visibleGraphGroups = new BitSet();
+    visibleGraphGroups.set(GROUP_4);
+    visibleGraphGroups.set(GROUP_6);
+    selectSequences(0, 3);
+    SequenceI[] seqs = parentPanel.getAlignment().getSequencesArray();
+
+    /*
+     * Configure annotation properties for test (offsetting for auto-calculated
+     * rows).
+     */
+    // annotations for selection group and graph group
+    // hidden annotations Label2, Label3, in (hidden) group 5
+    anns[AUTO_ANNS + 2].sequenceRef = seqs[3];
+    anns[AUTO_ANNS + 2].visible = false;
+    anns[AUTO_ANNS + 2].graph = AlignmentAnnotation.LINE_GRAPH;
+    anns[AUTO_ANNS + 2].graphGroup = GROUP_5; // not a visible group
+    anns[AUTO_ANNS + 3].sequenceRef = seqs[0];
+    anns[AUTO_ANNS + 3].visible = false;
+    anns[AUTO_ANNS + 3].graph = AlignmentAnnotation.LINE_GRAPH;
+    anns[AUTO_ANNS + 3].graphGroup = GROUP_5;
+    // need to ensure annotations have the same calcId as well
+    anns[AUTO_ANNS + 3].setCalcId("CalcId2");
+
+    // annotations Label1 (hidden), Label5 (visible) in group 6 (visible)
+    anns[AUTO_ANNS + 1].sequenceRef = seqs[3];
+    // being in a visible group should take precedence over this visibility
+    anns[AUTO_ANNS + 1].visible = false;
+    anns[AUTO_ANNS + 1].graph = AlignmentAnnotation.LINE_GRAPH;
+    anns[AUTO_ANNS + 1].graphGroup = GROUP_6;
+    anns[AUTO_ANNS + 5].sequenceRef = seqs[0];
+    anns[AUTO_ANNS + 5].visible = true; // visibleGraphGroups overrides this
+    anns[AUTO_ANNS + 5].graph = AlignmentAnnotation.LINE_GRAPH;
+    anns[AUTO_ANNS + 5].graphGroup = GROUP_6;
+    anns[AUTO_ANNS + 5].setCalcId("CalcId1");
+
+    // annotations outwith selection group - should be ignored
+    // hidden grouped annotations
+    anns[AUTO_ANNS + 6].sequenceRef = seqs[2];
+    anns[AUTO_ANNS + 6].visible = false;
+    anns[AUTO_ANNS + 6].graph = AlignmentAnnotation.LINE_GRAPH;
+    anns[AUTO_ANNS + 6].graphGroup = GROUP_4;
+    anns[AUTO_ANNS + 8].sequenceRef = seqs[1];
+    anns[AUTO_ANNS + 8].visible = false;
+    anns[AUTO_ANNS + 8].graph = AlignmentAnnotation.LINE_GRAPH;
+    anns[AUTO_ANNS + 8].graphGroup = GROUP_4;
+    // visible grouped annotations Label7, Label9
+    anns[AUTO_ANNS + 7].sequenceRef = seqs[2];
+    anns[AUTO_ANNS + 7].visible = true;
+    anns[AUTO_ANNS + 7].graph = AlignmentAnnotation.LINE_GRAPH;
+    anns[AUTO_ANNS + 7].graphGroup = GROUP_4;
+    anns[AUTO_ANNS + 9].sequenceRef = seqs[1];
+    anns[AUTO_ANNS + 9].visible = true;
+    anns[AUTO_ANNS + 9].graph = AlignmentAnnotation.LINE_GRAPH;
+    anns[AUTO_ANNS + 9].graphGroup = GROUP_4;
+
+    PopupMenu.getAnnotationTypesForShowHide(shownTypes, hiddenTypes,
+            visibleGraphGroups, anns, parentPanel.av.getSelectionGroup());
+
+    consoleDebug(shownTypes, hiddenTypes);
+
+    // CalcId1 / Label1, Label5 (only) should be 'shown', as a compound type
+    assertEquals(1, shownTypes.get("CalcId1").size());
+    assertEquals(2, shownTypes.get("CalcId1").get(0).size());
+    assertEquals("Label1", shownTypes.get("CalcId1").get(0).get(0));
+    assertEquals("Label5", shownTypes.get("CalcId1").get(0).get(1));
+
+    // CalcId2 / Label2, Label3 (only) should be 'hidden'
+    assertEquals(1, hiddenTypes.get("CalcId2").size());
+    assertEquals(2, hiddenTypes.get("CalcId2").get(0).size());
+    assertEquals("Label2", hiddenTypes.get("CalcId2").get(0).get(0));
+    assertEquals("Label3", hiddenTypes.get("CalcId2").get(0).get(1));
+  }
+
+  /**
+   * 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);
+  }
+}
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());
+        // }
+        // });
                        }
 
                }