Merge branch 'develop' into trialMerge
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Fri, 19 Apr 2019 15:04:51 +0000 (16:04 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Fri, 19 Apr 2019 15:04:51 +0000 (16:04 +0100)
Conflicts:
resources/lang/Messages.properties
resources/lang/Messages_es.properties
src/jalview/gui/FeatureSettings.java
src/jalview/gui/FeatureTypeSettings.java

1  2 
resources/lang/Messages.properties
resources/lang/Messages_es.properties
src/jalview/bin/Jalview.java
src/jalview/controller/AlignViewController.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/FeatureSettings.java
src/jalview/gui/FeatureTypeSettings.java
src/jalview/gui/SequenceFetcher.java
test/jalview/controller/AlignViewControllerTest.java
test/jalview/gui/AlignFrameTest.java

@@@ -30,6 -30,7 +30,7 @@@ action.minimize_associated_windows = Mi
  action.close_all = Close all
  action.load_project = Load Project
  action.save_project = Save Project
+ action.save_project_as = Save Project as...
  action.quit = Quit
  action.expand_views = Expand Views
  action.gather_views = Gather Views
@@@ -118,10 -119,8 +119,8 @@@ action.select = Selec
  action.new_view = New View
  action.close = Close
  action.add = Add
- action.save_as_default = Save as default
  action.save_as = Save as...
  action.save = Save
- action.cancel_fetch = Cancel Fetch
  action.change_font = Change Font
  action.change_font_tree_panel = Change Font (Tree Panel)
  action.colour = Colour
@@@ -140,7 -139,6 +139,6 @@@ action.fetch_db_references = Fetch DB R
  action.view_flanking_regions = Show flanking regions
  label.view_flanking_regions = Show sequence data either side of the subsequences involved in this alignment
  label.structures_manager = Structures Manager
- label.nickname = Nickname:
  label.url = URL
  label.url\: = URL:
  label.input_file_url = Enter URL or Input File
@@@ -162,7 -160,6 +160,6 @@@ label.current_parameter_set_name = Curr
  label.service_action = Service Action:
  label.post_url = POST URL:
  label.url_suffix = URL Suffix
- label.sequence_source = Sequence Source
  label.per_seq = per Sequence
  label.result_vertically_separable = Results are vertically separable
  label.amend = Amend
@@@ -172,10 -169,9 +169,9 @@@ label.principal_component_analysis = Pr
  label.average_distance_identity = Average Distance Using % Identity
  label.neighbour_joining_identity = Neighbour Joining Using % Identity
  label.choose_calculation = Choose Calculation
- label.treecalc_title = {0} Using {1}
+ label.calc_title = {0} Using {1}
  label.tree_calc_av = Average Distance
  label.tree_calc_nj = Neighbour Joining
- label.select_score_model = Select score model
  label.score_model_pid = % Identity
  label.score_model_blosum62 = BLOSUM62
  label.score_model_pam250 = PAM 250
@@@ -188,21 -184,22 +184,22 @@@ label.out_to_textbox = Output to Textbo
  label.occupancy = Occupancy
  # delete Clustal - use FileFormat name instead
  label.clustal = Clustal
- # label.colourScheme_<schemeName> as in JalviewColourScheme
+ # label.colourScheme_<schemeName> as in JalviewColourScheme, spaces removed
  label.colourScheme_clustal = Clustalx
  label.colourScheme_blosum62 = BLOSUM62 Score
- label.colourScheme_%_identity = Percentage Identity
+ label.colourScheme_%identity = Percentage Identity
  label.colourScheme_zappo = Zappo
  label.colourScheme_taylor = Taylor
  label.colourScheme_hydrophobic = Hydrophobicity
- label.colourScheme_helix_propensity = Helix Propensity
- label.colourScheme_strand_propensity = Strand Propensity
- label.colourScheme_turn_propensity = Turn Propensity
- label.colourScheme_buried_index = Buried Index
+ label.colourScheme_helixpropensity = Helix Propensity
+ label.colourScheme_strandpropensity = Strand Propensity
+ label.colourScheme_turnpropensity = Turn Propensity
+ label.colourScheme_buriedindex = Buried Index
  label.colourScheme_purine/pyrimidine = Purine/Pyrimidine
  label.colourScheme_nucleotide = Nucleotide
- label.colourScheme_t-coffee_scores = T-Coffee Scores
- label.colourScheme_rna_helices = By RNA Helices
+ label.colourScheme_t-coffeescores = T-Coffee Scores
+ label.colourScheme_rnahelices = By RNA Helices
+ label.colourScheme_sequenceid = Sequence ID Colour
  label.blc = BLC
  label.fasta = Fasta
  label.msf = MSF
@@@ -353,7 -350,6 +350,6 @@@ label.status = Statu
  label.channels = Channels
  label.channel_title_item_count = {0} ({1})
  label.blog_item_published_on_date = {0} {1} 
- label.select_das_service_from_table = Select a DAS service from the table to read a full description here.</font></html>
  label.session_update = Session Update
  label.new_vamsas_session = New Vamsas Session
  action.load_vamsas_session = Load Vamsas Session...
@@@ -371,7 -367,6 +367,6 @@@ label.load_colours = Load Colour
  label.save_colours = Save Colours
  label.load_colours_tooltip = Load feature colours and filters from file
  label.save_colours_tooltip = Save feature colours and filters to file
- label.fetch_das_features = Fetch DAS Features
  label.selected_database_to_fetch_from = Selected {0} database {1} to fetch from {2} 
  label.database_param = Database: {0}
  label.example = Example
@@@ -409,14 -404,11 +404,11 @@@ label.couldnt_find_pdb_id_in_file = Cou
  label.no_pdb_id_in_file = No PDB Id in File
  label.couldnt_read_pasted_text = Couldn't read the pasted text {0}
  label.error_parsing_text = Error parsing text
- label.enter_local_das_source = Enter Nickname & URL of Local DAS Source
- label.you_can_only_edit_or_remove_local_das_sources = You can only edit or remove local DAS Sources!
- label.public_das_source = Public DAS source - not editable
  label.input_alignment_from_url = Input Alignment From URL
  label.input_alignment = Input Alignment
  label.couldnt_import_as_vamsas_session = Couldn't import {0} as a new vamsas session.
  label.vamsas_document_import_failed = Vamsas Document Import Failed
- label.couldnt_locate = Couldn't locate {0}
+ label.couldnt_locate = Could not locate {0}
  label.url_not_found = URL not found
  label.new_sequence_url_link = New sequence URL link
  label.cannot_edit_annotations_in_wrapped_view = Cannot edit annotations in wrapped view
@@@ -428,8 -420,6 +420,6 @@@ label.invalid_url = Invalid URL 
  label.error_loading_file = Error loading file
  label.problems_opening_file = Encountered problems opening {0}!!
  label.file_open_error = File open error
- label.no_das_sources_selected_warn = No das sources were selected.\nPlease select some sources and\ntry again.
- label.no_das_sources_selected_title = No DAS Sources Selected
  label.colour_scheme_exists_overwrite = Colour scheme {0} exists.\nContinue saving colour scheme as {1}?"
  label.duplicate_scheme_name = Duplicate scheme name
  label.jalview_new_questionnaire = There is a new Questionnaire available. Would you like to complete it now ?\n
@@@ -502,6 -492,10 +492,10 @@@ label.edit_name_description = Edit Name
  label.create_sequence_feature = Create Sequence Feature...
  label.edit_sequence = Edit Sequence
  label.edit_sequences = Edit Sequences
+ label.insert_gap = Insert 1 gap
+ label.insert_gaps = Insert {0} gaps
+ label.delete_gap = Delete 1 gap
+ label.delete_gaps = Delete {0} gaps
  label.sequence_details = Sequence Details
  label.jmol_help = Jmol Help
  label.chimera_help = Chimera Help
@@@ -622,7 -616,6 +616,6 @@@ label.visual = Visua
  label.connections = Connections
  label.output = Output
  label.editing = Editing
- label.das_settings = DAS Settings
  label.web_services = Web Services
  label.right_click_to_edit_currently_selected_parameter = Right click to edit currently selected parameter.
  label.let_jmol_manage_structure_colours = Let Jmol manage structure colours
@@@ -638,10 -631,6 +631,6 @@@ label.delete_service_url = Delete Servi
  label.details = Details
  label.options = Options
  label.parameters = Parameters
- label.available_das_sources = Available DAS Sources
- label.full_details = Full Details
- label.authority = Authority
- label.type = Type
  label.proxy_server = Proxy Server
  label.file_output = File Output
  label.select_input_type = Select input type
@@@ -710,9 -699,6 +699,6 @@@ label.sort_alignment_new_tree = Sort Al
  label.add_sequences = Add Sequences
  label.new_window = New Window
  label.split_window = Split Window
- label.refresh_available_sources = Refresh Available Sources
- label.use_registry = Use Registry
- label.add_local_source = Add Local Source
  label.set_as_default = Set as Default
  label.show_labels = Show labels
  action.background_colour = Background Colour...
@@@ -771,7 -757,7 +757,7 @@@ label.run_with_preset_params = Run {0} 
  label.view_and_change_parameters_before_running_calculation = View and change parameters before running calculation
  label.view_documentation = View documentation
  label.select_return_type = Select return type
- label.translation_of_params = Translation of {0}
+ label.translation_of_params = Translation of {0} (Table {1})
  label.features_for_params = Features for - {0}
  label.annotations_for_params = Annotations for - {0}
  label.generating_features_for_params = Generating features for - {0}
@@@ -814,7 -800,6 +800,7 @@@ label.rest_client_submit = {0} using {1
  label.fetch_retrieve_from =Retrieve from {0}</html>
  label.fetch_retrieve_from_all_sources = Retrieve from all {0} sources in {1}<br>First is :{2}<html> 
  label.feature_settings_click_drag = Drag up or down to change render order.<br/>Double click to select columns containing feature.
 +label.feature_settings_select_columns = Double click to select columns containing feature
  label.transparency_tip = Adjust transparency to 'see through' feature colours.
  label.opt_and_params_further_details = see further details by right-clicking
  label.opt_and_params_show_brief_desc_image_link = <html>Click to show brief description<br><img src="{0}"/> Right click for further information.</html> 
@@@ -854,7 -839,6 +840,6 @@@ label.multiharmony = Multi-Harmon
  label.unable_start_web_service_analysis = Unable to start web service analysis
  label.job_couldnt_be_started_check_input = The Job couldn't be started. Please check your input, and the Jalview console for any warning messages.
  label.prompt_each_time = Prompt each time
- label.use_source = Use Source
  label.couldnt_save_project = Couldn't save project
  label.error_whilst_saving_current_state_to = Error whilst saving current state to {0}
  label.error_whilst_loading_project_from = Error whilst loading project from {0}
@@@ -880,7 -864,6 +865,6 @@@ label.error_unsupported_owwner_user_col
  label.save_alignment_to_file = Save Alignment to file
  label.save_features_to_file = Save Features to File
  label.save_annotation_to_file = Save Annotation to File
- label.no_features_on_alignment = No features found on alignment
  label.save_pdb_file = Save PDB File
  label.save_text_to_file = Save Text to File
  label.save_state = Save State
@@@ -1080,8 -1063,6 +1064,6 @@@ exception.unable_to_create_internet_con
  exception.invocation_target_calling_url = InvocationTargetException while calling openURL: {0}
  exception.illegal_access_calling_url = IllegalAccessException while calling openURL: {0}
  exception.interrupted_launching_browser = InterruptedException while launching browser: {0}
- exception.das_source_doesnt_support_sequence_command = Source {0} does not support the sequence command.
- exception.invalid_das_source = Invalid das source: {0}
  exception.ebiembl_retrieval_failed_on = EBI EMBL XML retrieval failed on {0}:{1}
  exception.no_pdb_records_for_chain = No PDB Records for {0} chain {1}
  exception.unexpected_handling_rnaml_translation_for_pdb = Unexpected exception when handling RNAML translation of PDB data
@@@ -1136,10 -1117,6 +1118,6 @@@ status.parsing_results = Parsing result
  status.processing = Processing...
  status.refreshing_web_service_menus = Refreshing Web Service Menus
  status.collecting_job_results = Collecting job results.
- status.fetching_das_sequence_features = Fetching DAS Sequence Features
- status.no_das_sources_active = No DAS Sources Active
- status.das_feature_fetching_cancelled = DAS Feature Fetching Cancelled
- status.das_feature_fetching_complete = DAS Feature Fetching Complete
  status.fetching_db_refs = Fetching db refs
  status.loading_cached_pdb_entries = Loading Cached PDB Entries
  status.searching_for_pdb_structures = Searching for PDB Structures
@@@ -1162,8 -1139,6 +1140,6 @@@ warn.urls_not_contacted = URLs that cou
  warn.urls_no_jaba = URLs without any JABA Services
  info.validate_jabaws_server = Validate JabaWS Server ?\n(Look in console output for results)
  label.test_server = Test Server?
- info.you_want_jalview_to_find_uniprot_accessions = Do you want Jalview to find\nUniprot Accession ids for given sequence names?
- label.find_uniprot_accession_ids = Find Uniprot Accession Ids
  label.new_sequence_fetcher = New Sequence Fetcher
  label.additional_sequence_fetcher = Additional Sequence Fetcher
  label.select_database_retrieval_source = Select Database Retrieval Source
@@@ -1285,7 -1260,6 +1261,6 @@@ label.SEQUENCE_ID_for_DB_ACCESSION1 = P
  label.SEQUENCE_ID_for_DB_ACCESSION2 = URL links using '$SEQUENCE_ID$' for DB accessions now use '$DB_ACCESSION$'.
  label.do_not_display_again = Do not display this message again
  exception.url_cannot_have_duplicate_id = {0} cannot be used as a label for more than one line
- label.filter = Filter text:
  action.customfilter = Custom only
  action.showall = Show All
  label.insert = Insert:
@@@ -1300,7 -1274,6 +1275,6 @@@ label.edit_sequence_url_link = Edit seq
  warn.name_cannot_be_duplicate = User-defined URL names must be unique and cannot be MIRIAM ids
  label.output_seq_details = Output Sequence Details to list all database references
  label.urllinks = Links
- label.default_cache_size = Default Cache Size
  action.clear_cached_items = Clear Cached Items
  label.togglehidden = Show hidden regions
  label.quality_descr = Alignment Quality based on Blosum62 scores
@@@ -1353,7 -1326,6 +1327,6 @@@ label.colour_by_text = Colour by tex
  label.graduated_colour = Graduated Colour
  label.by_text_of = By text of
  label.by_range_of = By range of
- label.filters_tooltip = Click to set or amend filters
  label.or = Or
  label.and = And
  label.sequence_feature_colours = Sequence Feature Colours
@@@ -1364,7 -1336,60 +1337,64 @@@ label.most_bound_molecules = Most Boun
  label.most_polymer_residues = Most Polymer Residues
  label.cached_structures = Cached Structures
  label.free_text_search = Free Text Search
 +label.summary_view = Summary View
 +label.summary_view_tip = Show only top level ontology terms
 +label.apply_to_subtypes = Apply changes also to sub-types of ''{0}''
- label.apply_also_to = Apply also to:
++label.apply_also_to = Apply also to:
+ label.backupfiles_confirm_delete = Confirm delete
+ label.backupfiles_confirm_delete_old_files = Delete the following older backup files? (see the Backups tab in Preferences for more options)
+ label.backupfiles_confirm_save_file = Confirm save file
+ label.backupfiles_confirm_save_file_backupfiles_roll_wrong = Something possibly went wrong with the backups of this file.
+ label.backupfiles_confirm_save_new_saved_file_ok = The new saved file seems okay.
+ label.backupfiles_confirm_save_new_saved_file_not_ok = The new saved file might not be okay.
+ label.backups = Backups
+ label.backup = Backup
+ label.backup_files = Backup Files
+ label.enable_backupfiles = Enable backup files
+ label.backup_filename_strategy = Backup filename strategy
+ label.append_to_filename = Append to filename (%n is replaced by the backup number)
+ label.append_to_filename_tooltip = %n in the text will be replaced by the backup number. The text will appear after the filename. See the summary box above.
+ label.index_digits = Number of digits to use for the backup number (%n)
+ label.summary_of_backups_scheme = Summary of backup scheme
+ label.increment_index = Increase appended text numbers - newest file has largest number.
+ label.reverse_roll = "Roll" appended text numbers - newest backup file is always number 1.
+ label.keep_files = Deleting old backup files
+ label.keep_all_backup_files = Do not delete old backup files
+ label.keep_only_this_number_of_backup_files = Keep only this number of most recent backup files
+ label.autodelete_old_backup_files = Autodelete old backup files:
+ label.always_ask = Always ask
+ label.auto_delete = Automatically delete
+ label.filename = filename
+ label.braced_oldest = (oldest)
+ label.braced_newest = (most recent)
+ label.configuration = Configuration
+ label.configure_feature_tooltip = Click to configure variable colour or filters
+ label.schemes = Schemes
+ label.customise = Customise
+ label.default = Default
+ label.single_file = Single backup
+ label.keep_all_versions = Keep all versions
+ label.rolled_backups = Rolled backup files
+ label.previously_saved_scheme = Previously saved scheme
+ label.no_backup_files = NO BACKUP FILES
+ label.include_backup_files = Include backup files
+ label.cancel_changes = Cancel changes
+ label.warning_confirm_change_reverse = Warning!\nIf you change the increment/decrement of the backup filename number, without changing the suffix or number of digits,\nthis may cause loss of backup files created with the previous backup filename scheme.\nAre you sure you wish to do this?
+ label.change_increment_decrement = Change increment/decrement?
+ label.was_previous = was {0}
+ label.newerdelete_replacement_line = Backup file\n''{0}''\t(modified {2}, size {4})\nis to be deleted and replaced by apparently older file\n''{1}''\t(modified {3}, size {5}).
+ label.confirm_deletion_or_rename = Confirm deletion of ''{0}'' or rename to ''{1}''?
+ label.newerdelete_line = Backup file\n''{0}''\t(modified {2}, size {4})\nis to be deleted but is newer than the oldest remaining backup file\n''{1}''\t(modified {3}, size {5}).
+ label.confirm_deletion = Confirm deletion of ''{0}''?
+ label.delete = Delete
+ label.rename = Rename
+ label.keep = Keep
+ label.file_info = (modified {0}, size {1})
+ label.annotation_name = Annotation Name
+ label.annotation_description = Annotation Description 
+ label.edit_annotation_name_description = Edit Annotation Name/Description
+ label.alignment = alignment
+ label.pca = PCA
+ label.create_image_of = Create {0} image of {1}
+ label.click_to_edit = Click to edit, right-click for menu
+ label.by_annotation_tooltip = Annotation Colour is configured from the main Colour menu
@@@ -30,6 -30,7 +30,7 @@@ action.minimize_associated_windows = Mi
  action.close_all = Cerrar todo
  action.load_project = Cargar proyecto
  action.save_project = Guardar proyecto
+ action.save_project_as = Guardar proyecto como...
  action.quit = Salir
  action.expand_views = Expandir vistas
  action.gather_views = Capturar vistas
@@@ -115,10 -116,8 +116,8 @@@ action.select = Selecciona
  action.new_view = Nueva vista
  action.close = Cerrar
  action.add = Añadir
- action.save_as_default = Guardar como por defecto
  action.save_as = Guardar como
  action.save = Guardar
- action.cancel_fetch = Cancelar búsqueda
  action.change_font = Cambiar Fuente
  action.change_font_tree_panel = Cambiar fuente (panel del árbol)
  action.colour = Color
@@@ -137,7 -136,6 +136,6 @@@ action.fetch_db_references = Recuperar 
  action.view_flanking_regions = Mostrar flancos
  label.view_flanking_regions = Mostrar los datos de la secuencia a ambos lados de las subsecuencias implicadas en este alineamiento
  label.structures_manager = Administrar estructuras
- label.nickname = Sobrenombre:
  label.url\: = URL:
  label.url = URL 
  label.input_file_url = Introducir URL en el fichero de entrada
@@@ -159,7 -157,6 +157,6 @@@ label.current_parameter_set_name = Nomb
  label.service_action = Acción de servicio:
  label.post_url = POST URL: 
  label.url_suffix = URL Sufijo
- label.sequence_source = Fuente de la secuencia
  label.per_seq = por secuencia
  label.result_vertically_separable = Los resultados son separables verticalmente
  label.amend = Modificar
@@@ -169,10 -166,9 +166,9 @@@ label.principal_component_analysis = An
  label.average_distance_identity = Distancia Media Usando % de Identidad
  label.neighbour_joining_identity = Unir vecinos utilizando % de Identidad
  label.choose_calculation = Elegir el cálculo
- label.treecalc_title = {0} utilizando {1}
+ label.calc_title = {0} utilizando {1}
  label.tree_calc_av = Distancia media
  label.tree_calc_nj = Unir vecinos
- label.select_score_model = Selecciones modelo de puntuación
  label.score_model_pid = % Identidad
  label.score_model_blosum62 = BLOSUM62
  label.score_model_pam250 = PAM 250
@@@ -187,18 -183,19 +183,19 @@@ label.clustal = Clusta
  # label.colourScheme_<schemeName> as in JalviewColourScheme
  label.colourScheme_clustal = Clustalx
  label.colourScheme_blosum62 = Puntuación del BLOSUM62
- label.colourScheme_%_identity = Porcentaje de identidad
+ label.colourScheme_%identity = Porcentaje de identidad
  label.colourScheme_zappo = Zappo
  label.colourScheme_taylor = Taylor
  label.colourScheme_hydrophobic = Hidrofobicidad
- label.colourScheme_helix_propensity = Tendencia de la hélice
- label.colourScheme_strand_propensity = Tendencia de la hebra
- label.colourScheme_turn_propensity = Tendencia de giro
- label.colourScheme_buried_index = Índice de encubrimiento
+ label.colourScheme_helixpropensity = Tendencia de la hélice
+ label.colourScheme_strandpropensity = Tendencia de la hebra
+ label.colourScheme_turnpropensity = Tendencia de giro
+ label.colourScheme_buriedindex = Índice de encubrimiento
  label.colourScheme_purine/pyrimidine = Purina/Pirimidina
  label.colourScheme_nucleotide = Nucleótido
- label.colourScheme_t-coffee_scores = Puntuación del T-Coffee
- label.colourScheme_rna_helices = Por hélices de RNA
+ label.colourScheme_t-coffeescores = Puntuación del T-Coffee
+ label.colourScheme_rnahelices = Por hélices de RNA
+ label.colourScheme_sequenceid = Color de ID de secuencia
  label.blc = BLC
  label.fasta = Fasta
  label.msf = MSF
@@@ -322,7 -319,6 +319,6 @@@ label.status =  [Estado
  label.channels = Canales
  label.channel_title_item_count = {0} ({1})
  label.blog_item_published_on_date = {0} {1} 
- label.select_das_service_from_table = Seleccionar servicio DAS de la tabla para leer una descripción completa aquí.
  label.session_update = Actualizar sesión
  label.new_vamsas_session = Nueva sesión Vamsas
  action.save_vamsas_session = Guardar Sesión Vamsas
@@@ -339,7 -335,6 +335,6 @@@ label.load_colours = Cargar colore
  label.save_colours = Guardar colores
  label.load_colours_tooltip = Cargar colores y filtros desde fichero
  label.save_colours_tooltip = Guardar colores y filtros en fichero
- label.fetch_das_features = Recuperar funciones DAS
  label.selected_database_to_fetch_from = Seleccionada {0} Base de datos {1} para buscar de {2} 
  label.database_param = Base de datos: {0}
  label.example = Ejemplo
@@@ -376,9 -371,6 +371,6 @@@ label.couldnt_find_pdb_id_in_file = No 
  label.no_pdb_id_in_file = No hay un Id PDB en el fichero
  label.couldnt_read_pasted_text = No se pudo leer el texto pegado {0}
  label.error_parsing_text = Error analizando el texto
- label.enter_local_das_source = Intruduzca el Nickname & URL de la fuente DAS local
- label.you_can_only_edit_or_remove_local_das_sources = Sólo puedes editar o eliminar fuentes DAS locales!
- label.public_das_source = Fuente pública DAS - no editable
  label.input_alignment_from_url = Alineamiento de entrada desde URL
  label.input_alignment = Alineamiento de entrada
  label.couldnt_import_as_vamsas_session = No se pudo importar {0} como una nueva sesión Vamsas.
@@@ -395,8 -387,6 +387,6 @@@ label.invalid_url = URL Invalido
  label.error_loading_file = Error al cargar el fichero
  label.problems_opening_file = Encontrados problemas al abrir el fichero {0}!!
  label.file_open_error = Error al abrir el fichero
- label.no_das_sources_selected_warn = No han sido seleccionadas fuentes DAS.\nPor favor, seleccione algunas fuentes y\npruebe de nuevo.
- label.no_das_sources_selected_title = No han sido seleccionadas fuentes DAS
  label.colour_scheme_exists_overwrite = El esquema de colores {0} ya existe.\nContinuar guardando el esquema de colores como {1}?
  label.duplicate_scheme_name = Duplicar nombre de esquema
  label.jalview_new_questionnaire = Hay un nuevo cuestionario disponible. Querr\u00EDa completarlo ahora ?\n
@@@ -468,6 -458,10 +458,10 @@@ label.edit_name_description = Editar no
  label.create_sequence_feature = Crear función de secuencia
  label.edit_sequence = Editar secuencia
  label.edit_sequences = Editar secuencias
+ label.insert_gap = Insertar 1 hueco
+ label.insert_gaps = Insertar {0} huecos
+ label.delete_gap = Borrar 1 hueco
+ label.delete_gaps = Borrar {0} huecos
  label.sequence_details = Detalles de la secuencia
  label.jmol_help = Ayuda de Jmol
  # Todos/Todas is gender-sensitive, but currently only used for feminine (cadena / anotación)! 
@@@ -577,7 -571,6 +571,6 @@@ label.visual = Visua
  label.connections = Conexiones
  label.output = Salida
  label.editing = Edición
- label.das_settings = Configuración DAS
  label.web_services = Servicios web
  label.right_click_to_edit_currently_selected_parameter = Haga clic en el botón derecho para editar el parámetro seleccionado actualmente.
  label.let_jmol_manage_structure_colours = Permitir que Jmol gestione la estructuras cromáticas
@@@ -590,10 -583,6 +583,6 @@@ label.delete_service_url = Borrar la UR
  label.details = Detalles
  label.options = Opciones
  label.parameters = Paramétros
- label.available_das_sources = Fuentes DAS disponibles
- label.full_details = Detalles completos
- label.authority = Autoridad
- label.type = Tipo
  label.proxy_server = Servidor proxy
  label.file_output = Fichero de salida
  label.select_input_type = Seleccionar el tipo de entrada
@@@ -656,9 -645,6 +645,6 @@@ label.get_cross_refs = Obtener referenc
  label.sort_alignment_new_tree = Alinear el alineamiento con el nuevo árbol
  label.add_sequences = Añadir secuencias
  label.new_window = Nueva ventana
- label.refresh_available_sources = Refrescar las fuentes disponibles
- label.use_registry = Utilizar el registro
- label.add_local_source = Añadir fuente local
  label.set_as_default = Establecer por defecto
  label.show_labels = Mostrar etiquetas
  label.associate_nodes_with = Asociar nodos con
@@@ -700,7 -686,7 +686,7 @@@ label.run_with_preset_params = Ejecuta
  label.view_and_change_parameters_before_running_calculation = Ver y cambiar los parámetros antes de lanzar el cálculo
  label.view_documentation = Ver documentación
  label.select_return_type = Seleccionar el tipo de retorno
- label.translation_of_params = Traducción de {0}
+ label.translation_of_params = Traducción de {0} (Tabla {1})
  label.features_for_params = Características de - {0}
  label.annotations_for_params = Anotaciones de - {0}
  label.generating_features_for_params = Generando características de - {0}
@@@ -739,8 -725,7 +725,8 @@@ label.services_at = Servicios en {0
  label.rest_client_submit = {0} utilizando {1}
  label.fetch_retrieve_from =Recuperar de {0}
  label.fetch_retrieve_from_all_sources = Recuperar de todas las fuentes {0} en {1}<br>La primera es :{2}
 -label.feature_settings_click_drag = Haga clic o arrastre los tipos de las características hacia arriba o hacia abajo para cambiar el orden de visualización.<br/>Haga doble clic para seleccionar las columnas que contienen las características del alineamiento/selección actual.<br/>
 +label.feature_settings_click_drag = Haga clic o arrastre los tipos de las características hacia arriba o hacia abajo para cambiar el orden de visualización.<br/>Haga doble clic para seleccionar las columnas que contienen las características del alineamiento/selección actual.
 +label.feature_settings_select_columns =Haga doble clic para seleccionar las columnas que contienen las características del alineamiento/selección actual
  label.opt_and_params_further_details = ver los detalles adicionales haciendo clic en el botón derecho
  label.opt_and_params_show_brief_desc_image_link = Haga clic para ver una descripción breve<br><img src="{0}"/>Haga clic en el botón derecho para obtener información adicional.
  label.opt_and_params_show_brief_desc = Haga clic para ver una descripción breve<br>
@@@ -779,7 -764,6 +765,6 @@@ label.multiharmony = Multi-Harmon
  label.unable_start_web_service_analysis = No es posible iniciar el servicio web de análisis
  label.job_couldnt_be_started_check_input = El trabajo no puede arrancarse. Por favor, compruebe los parámetros de entrada y los mensajes de advertencia de la consola de Jalview.
  label.prompt_each_time = Preguntar siempre
- label.use_source = Fuente
  label.couldnt_save_project = No es posible guardar el proyecto
  label.error_whilst_saving_current_state_to = Error mientras se guardaba el estado a {0}
  label.error_whilst_loading_project_from = Error cargando el proyecto desde  {0}
@@@ -805,7 -789,6 +790,6 @@@ label.error_unsupported_owwner_user_col
  label.save_alignment_to_file = Guardar Alineamiento en fichero
  label.save_features_to_file = Guardar Características en un fichero
  label.save_annotation_to_file = Guardar Anotación en un fichero
- label.no_features_on_alignment = No se han encontrado características en el alineamiento
  label.save_pdb_file = Guardar fichero PDB 
  label.save_text_to_file = Guardar Texto en un fichero
  label.save_state = Guardar estado
@@@ -1005,8 -988,6 +989,6 @@@ exception.unable_to_create_internet_con
  exception.invocation_target_calling_url = InvocationTargetException mientras se invocaba openURL: {0}
  exception.illegal_access_calling_url = IllegalAccessException mientras se invocaba openURL: {0}
  exception.interrupted_launching_browser = InterruptedException mientras se lanzaba el navegador: {0}
- exception.das_source_doesnt_support_sequence_command = La fuente {0} no soporta el comando sequence.
- exception.invalid_das_source = Fuente DAS no válida: {0}
  exception.ebiembl_retrieval_failed_on = La recuperación de datos EBI EMBL XML ha fallado en {0}:{1}
  exception.no_pdb_records_for_chain = No se han encontrado registros {0} para la cadena {1}
  exception.unexpected_handling_rnaml_translation_for_pdb = Excepcion inesperada cuando se traducían a RNAML los datos PDB
@@@ -1058,10 -1039,6 +1040,6 @@@ status.parsing_results = Parseando resu
  status.processing = Procesando...
  status.refreshing_web_service_menus = Refrescando los menús de servicios web
  status.collecting_job_results = Recolectando los resultados de los trabajos.
- status.fetching_das_sequence_features = Recuperando las características DAS de las secuencias
- status.no_das_sources_active = No existe ninguna fuente DAS activa
- status.das_feature_fetching_cancelled = Recuperación de características DAS cancelada
- status.das_feature_fetching_complete = Recuperación de características DAS completada
  status.fetching_db_refs = Recuperando db refs
  label.font_doesnt_have_letters_defined = La fuente no tiene letras definidas\npor lo que no puede emplease\ncon datos de alineamientos
  label.font_too_small = Tamaño de la letra es demasiado pequeña
@@@ -1078,8 -1055,6 +1056,6 @@@ warn.server_didnt_pass_validation = El 
  warn.url_must_contain = La URL de la secuencia debe contener $SEQUENCE_ID$, $DB_ACCESSION$ o un regex
  info.validate_jabaws_server = \u00BFValidar el servidor JabaWS?\n(Consulte la consola de salida para obtener los resultados)
  label.test_server = ¿Probar servidor?
- info.you_want_jalview_to_find_uniprot_accessions = \u00BFDesea que Jalview encuentre\nUniprot Accession ids para los nombres de secuencias dados?
- label.find_uniprot_accession_ids = Buscar Uniprot Accession Ids
  label.new_sequence_fetcher = Añadir recuperador de secuencias
  label.additional_sequence_fetcher = Recuperador de secuencia adicional
  label.select_database_retrieval_source = Seleccionar fuente de recuperación de bases de datos
@@@ -1286,7 -1261,6 +1262,6 @@@ label.SEQUENCE_ID_for_DB_ACCESSION1 = P
  label.SEQUENCE_ID_for_DB_ACCESSION2 = URL enlaza usando '$SEQUENCE_ID$' para accesiones DB ahora usar '$DB_ACCESSION$'.
  label.do_not_display_again = No mostrar este mensaje de nuevo
  exception.url_cannot_have_duplicate_id = {0} no puede ser usada como etiqueta en más de un enlace
- label.filter = Filtrar texto:
  action.customfilter = Sólo personalizado
  action.showall = Mostrar todo
  label.insert = Insertar:
@@@ -1301,7 -1275,6 +1276,6 @@@ label.edit_sequence_url_link = Editar l
  warn.name_cannot_be_duplicate = Los nombres URL definidos por el usuario deben ser únicos y no pueden ser ids de MIRIAM
  label.output_seq_details = Seleccionar Detalles de la secuencia para ver todas
  label.urllinks = Enlaces
- label.default_cache_size = Tamaño del caché por defecto
  action.clear_cached_items = Borrar elementos en caché
  label.quality_descr = Calidad de alineamiento basándose en puntuación Blosum62
  label.conservation_descr = Conservación del alineamiento total menos de {0}% huecos
@@@ -1354,7 -1327,6 +1328,6 @@@ label.colour_by_text = Colorear por tex
  label.graduated_colour = Color graduado
  label.by_text_of = Por texto de
  label.by_range_of = Por rango de
- label.filters_tooltip = Haga clic para configurar o modificar los filtros
  label.or = O
  label.and = Y
  label.sequence_feature_colours = Colores de características de las secuencias
@@@ -1365,7 -1337,60 +1338,64 @@@ label.most_bound_molecules = Más Molécu
  label.most_polymer_residues = Más Residuos de Polímeros
  label.cached_structures = Estructuras en Caché
  label.free_text_search = Búsqueda de texto libre
 +label.summary_view = Vista Resumida
 +label.summary_view_tip = Mostrar solo términos de ontología de nivel mayor
 +label.apply_to_subtypes = Aplicar cambios también a subtipos de ''{0}''
- label.apply_also_to = Aplicar también a:
++label.apply_also_to = Aplicar también a:
+ label.backupfiles_confirm_delete = Confirmar borrar
+ label.backupfiles_confirm_delete_old_files = ¿Borrar los siguientes archivos? (ver la pestaña 'Copias' de la ventana de Preferencias para más opciones)
+ label.backupfiles_confirm_save_file = Confirmar guardar archivo
+ label.backupfiles_confirm_save_file_backupfiles_roll_wrong = Posiblemente algo está mal con los archivos de respaldos.
+ label.backupfiles_confirm_save_new_saved_file_ok = El nuevo archivo guardado parece estar bien.
+ label.backupfiles_confirm_save_new_saved_file_not_ok = El nuevo archivo guardado podría no estar bien.
+ label.backups = Respaldos
+ label.backup = Respaldo
+ label.backup_files = Archivos de respaldos
+ label.enable_backupfiles = Habilitar archivos de respaldos
+ label.backup_filename_strategy = Estrategia de nombres de archivo de respaldos
+ label.append_to_filename = Adjuntar texto (%n es reemplazado por el número de respaldo)
+ label.append_to_filename_tooltip = %n en el texto será reemplazado por el número de respaldo. El texto será después del nombre del archivo. Vea el cuadro de resumen arriba.
+ label.index_digits = Número de dígitos a utilizar para el número de respaldo.
+ label.summary_of_backups_scheme = Resumen del esquema de copias de seguridad
+ label.increment_index = Aumente los números de texto adjuntos: el archivo más nuevo tiene el número más grande
+ label.reverse_roll = Ciclos de texto adjuntos: el respaldo más reciente es siempre el número 1
+ label.keep_files = Borrando los respaldos antiguos
+ label.keep_all_backup_files = No borrar respaldos antiguas
+ label.keep_only_this_number_of_backup_files = Mantenga solo este número de respaldos más recientes
+ label.autodelete_old_backup_files = Borrer automáticamente respaldos antiguos:
+ label.always_ask = Pregunta siempre
+ label.auto_delete = Borrer automáticamente
+ label.filename = nombre_de_archivo
+ label.braced_oldest = (mas antiguo)
+ label.braced_newest = (mas nuevo)
+ label.configuration = Configuración
+ label.configure_feature_tooltip = Haga clic para configurar el color o los filtros
+ label.schemes = Esquemas
+ label.customise = Personalizado
+ label.default = Defecto
+ label.single_file = Solo uno respaldo
+ label.keep_all_versions = Mantener todas las versiones
+ label.rolled_backups = Ciclos respaldos
+ label.previously_saved_scheme = Esquema previamente guardado
+ label.no_backup_files = NO ARCHIVOS DE RESPALDOS
+ label.include_backup_files = Incluir archivos de respaldos
+ label.cancel_changes = Cancelar cambios
+ label.warning_confirm_change_reverse = ¡Advertencia!\nSi cambia el incremento/decremento del número de archivos de respaldos, sin cambiar el sufijo o número de dígitos,\nesto puede causar la pérdida de los archivos de respaldos creados con el esquema anterior de nombre de archivo de respaldos.\n¿Está seguro de que desea hacer esto?
+ label.change_increment_decrement = ¿Cambiar de incremento/decremento?
+ label.was_previous = era {0}
+ label.newerdelete_replacement_line = El archivo de respaldo\n''{0}''\t(modificado {2}, tamaño {4})\nserá borrado y reemplazarse por un archivo aparentemente más antiguo\n''{1}''\t(modificado {3}, tamaño {5}).
+ label.confirm_deletion_or_rename = Confirmar borrar ''{0}'', o cambiar el nombre a ''{1}''?
+ label.newerdelete_line = El archivo de respaldo\n''{0}''\t(modificado {2}, tamaño {4})\nserá borrado pero es mas nuevo que el archivo de respaldo restante más antiguo\n''{1}''\t(modified {3}, size {5}).
+ label.confirm_deletion = Confirmar eliminar ''{0}''?
+ label.delete = Borrar
+ label.rename = Cambiar
+ label.keep = Mantener
+ label.file_info = (modificado {0}, tamaño {1})
+ label.annotation_name = Nombre de la anotación
+ label.annotation_description = Descripción de la anotación 
+ label.edit_annotation_name_description = Editar el nombre/descripción de la anotación
+ label.alignment = alineamiento
+ label.pca = ACP
+ label.create_image_of = Crear imagen {0} de {1}
+ label.click_to_edit = Haga clic para editar, clic en el botón derecho para ver el menú  
+ label.by_annotation_tooltip = El color de anotación se configura desde el menú principal de colores
@@@ -326,7 -326,7 +326,7 @@@ public class Jalvie
       * configure 'full' SO model if preferences say to, 
       * else use the default (SO Lite)
       */
 -    if (Cache.getDefault("USE_FULL_SO", false))
 +    if (Cache.getDefault("USE_FULL_SO", true))
      {
        SequenceOntologyFactory.setInstance(new SequenceOntology());
      }
      FileFormatI format = null;
      DataSourceType protocol = null;
      FileLoader fileLoader = new FileLoader(!headless);
-     Vector<String> getFeatures = null; // vector of das source nicknames to
-                                        // fetch
-     // features from
-     // loading is done.
      String groovyscript = null; // script to execute after all loading is
      // completed one way or another
      // extract groovy argument and execute if necessary
            data.replaceAll("%20", " ");
  
            ColourSchemeI cs = ColourSchemeProperty
-                   .getColourScheme(af.getViewport().getAlignment(), data);
+                   .getColourScheme(af.getViewport(),
+                           af.getViewport().getAlignment(), data);
  
            if (cs != null)
            {
          // TODO - load PDB structure(s) to alignment JAL-629
          // (associate with identical sequence in alignment, or a specified
          // sequence)
-         getFeatures = checkDasArguments(aparser);
-         if (af != null && getFeatures != null)
-         {
-           FeatureFetcher ff = startFeatureFetching(getFeatures);
-           if (ff != null)
-           {
-             while (!ff.allFinished() || af.operationInProgress())
-             {
-               // wait around until fetching is finished.
-               try
-               {
-                 Thread.sleep(100);
-               } catch (Exception e)
-               {
-               }
-             }
-           }
-           getFeatures = null; // have retrieved features - forget them now.
-         }
          if (groovyscript != null)
          {
            // Execute the groovy script after we've done all the rendering stuff
  
        startUpAlframe = fileLoader.LoadFileWaitTillLoaded(file, protocol,
                format);
-       getFeatures = checkDasArguments(aparser);
        // extract groovy arguments before anything else.
      }
-     // If the user has specified features to be retrieved,
-     // or a groovy script to be executed, do them if they
-     // haven't been done already
-     // fetch features for the default alignment
-     if (getFeatures != null)
-     {
-       if (startUpAlframe != null)
-       {
-         startFeatureFetching(getFeatures);
-       }
-     }
      // Once all other stuff is done, execute any groovy scripts (in order)
      if (groovyscript != null)
      {
                      // (quote the 'PROPERTY=VALUE' pair to ensure spaces are
                      // passed in correctly)"
                      + "-jabaws URL\tSpecify URL for Jabaws services (e.g. for a local installation).\n"
-                     + "-dasserver nickname=URL\tAdd and enable a das server with given nickname\n\t\t\t(alphanumeric or underscores only) for retrieval of features for all alignments.\n"
-                     + "\t\t\tSources that also support the sequence command may be specified by prepending the URL with sequence:\n"
-                     + "\t\t\t e.g. sequence:http://localdas.somewhere.org/das/source)\n"
                      + "-fetchfrom nickname\tQuery nickname for features for the alignments and display them.\n"
                      // +
                      // "-vdoc vamsas-document\tImport vamsas document into new
      }
    }
  
-   /**
-    * Check commandline for any das server definitions or any fetchfrom switches
-    * 
-    * @return vector of DAS source nicknames to retrieve from
-    */
-   private static Vector<String> checkDasArguments(ArgsParser aparser)
-   {
-     Vector<String> source = null;
-     String data;
-     String locsources = Cache.getProperty(Cache.DAS_LOCAL_SOURCE);
-     while ((data = aparser.getValue("dasserver", true)) != null)
-     {
-       String nickname = null;
-       String url = null;
-       int pos = data.indexOf('=');
-       // determine capabilities
-       if (pos > 0)
-       {
-         nickname = data.substring(0, pos);
-       }
-       url = data.substring(pos + 1);
-       if (url != null && (url.startsWith("http:")
-               || url.startsWith("sequence:http:")))
-       {
-         if (nickname == null)
-         {
-           nickname = url;
-         }
-         if (locsources == null)
-         {
-           locsources = "";
-         }
-         else
-         {
-           locsources += "\t";
-         }
-         locsources = locsources + nickname + "|" + url;
-         System.err.println(
-                 "NOTE! dasserver parameter not yet really supported (got args of "
-                         + nickname + "|" + url);
-         if (source == null)
-         {
-           source = new Vector<>();
-         }
-         source.addElement(nickname);
-       }
-       System.out.println(
-               "CMD [-dasserver " + data + "] executed successfully!");
-     } // loop until no more server entries are found.
-     if (locsources != null && locsources.indexOf('|') > -1)
-     {
-       Cache.log.debug("Setting local source list in properties file to:\n"
-               + locsources);
-       Cache.setProperty(Cache.DAS_LOCAL_SOURCE, locsources);
-     }
-     while ((data = aparser.getValue("fetchfrom", true)) != null)
-     {
-       System.out.println("adding source '" + data + "'");
-       if (source == null)
-       {
-         source = new Vector<>();
-       }
-       source.addElement(data);
-     }
-     return source;
-   }
-   /**
-    * start a feature fetcher for every alignment frame
-    * 
-    * @param dasSources
-    */
-   private FeatureFetcher startFeatureFetching(
-           final Vector<String> dasSources)
-   {
-     FeatureFetcher ff = new FeatureFetcher();
-     AlignFrame afs[] = Desktop.getAlignFrames();
-     if (afs == null || afs.length == 0)
-     {
-       return null;
-     }
-     for (int i = 0; i < afs.length; i++)
-     {
-       ff.addFetcher(afs[i], dasSources);
-     }
-     return ff;
-   }
    public static boolean isHeadlessMode()
    {
      String isheadless = System.getProperty("java.awt.headless");
@@@ -35,6 -35,7 +35,7 @@@ import jalview.datamodel.SequenceGroup
  import jalview.datamodel.SequenceI;
  import jalview.io.DataSourceType;
  import jalview.io.FeaturesFile;
+ import jalview.schemes.ColourSchemeI;
  import jalview.util.MessageManager;
  
  import java.awt.Color;
@@@ -97,19 -98,22 +98,22 @@@ public class AlignViewController implem
        viewport.getAlignment().deleteAllGroups();
        viewport.clearSequenceColours();
        viewport.setSelectionGroup(null);
+       ColourSchemeI colours = viewport.getGlobalColourScheme();
        // set view properties for each group
        for (int g = 0; g < gps.length; g++)
        {
          // gps[g].setShowunconserved(viewport.getShowUnconserved());
          gps[g].setshowSequenceLogo(viewport.isShowSequenceLogo());
          viewport.getAlignment().addGroup(gps[g]);
-         Color col = new Color((int) (Math.random() * 255),
-                 (int) (Math.random() * 255), (int) (Math.random() * 255));
-         col = col.brighter();
-         for (SequenceI sq : gps[g].getSequences(null))
+         if (colours != null)
          {
-           viewport.setSequenceColour(sq, col);
+           gps[g].setColourScheme(colours.getInstance(viewport, gps[g]));
          }
+         Color col = new Color((int) (Math.random() * 255),
+                 (int) (Math.random() * 255), (int) (Math.random() * 255));
+         gps[g].idColour = col;
+         viewport.setUpdateStructures(true);
+         viewport.addSequenceGroup(gps[g]);
        }
        return true;
      }
  
    @Override
    public boolean markColumnsContainingFeatures(boolean invert,
 -          boolean extendCurrent, boolean toggle, String featureType)
 +          boolean extendCurrent, boolean toggle, String... featureType)
    {
      // JBPNote this routine could also mark rows, not just columns.
      // need a decent query structure to allow all types of feature searches
              || extendCurrent) ? viewport.getAlignment()
                      : viewport.getSelectionGroup();
  
 -    int nseq = findColumnsWithFeature(featureType, sqcol, bs);
 +    int nseq = findColumnsWithFeature(sqcol, bs, featureType);
  
      ColumnSelection cs = viewport.getColumnSelection();
      if (cs == null)
        cs = new ColumnSelection();
      }
  
 +    String featureTypeString = featureType.length == 1 ? featureType[0]
 +            : featureType.toString();
 +
      if (bs.cardinality() > 0 || invert)
      {
        boolean changed = cs.markColumns(bs, sqcol.getStartRes(),
                      invert ? MessageManager
                              .getString("label.not_containing")
                              : MessageManager.getString("label.containing"),
 -                    featureType, Integer.valueOf(nseq).toString() }));
 +                    featureTypeString, Integer.valueOf(nseq).toString() }));
          return true;
        }
      }
      {
        avcg.setStatus(MessageManager
                .formatMessage("label.no_feature_of_type_found", new String[]
 -              { featureType }));
 +              { featureTypeString }));
        if (!extendCurrent)
        {
          cs.clear();
  
    /**
     * Sets a bit in the BitSet for each column (base 0) in the sequence
 -   * collection which includes a visible feature of the specified feature type.
 -   * Returns the number of sequences which have the feature visible in the
 -   * selected range.
 +   * collection which includes a visible feature of the specified feature
 +   * type(s). Returns the number of sequences which have the feature(s) visible
 +   * in the selected range.
     * 
 -   * @param featureType
     * @param sqcol
     * @param bs
 +   * @param featureType
 +   * 
     * @return
     */
 -  int findColumnsWithFeature(String featureType,
 -          SequenceCollectionI sqcol, BitSet bs)
 +  int findColumnsWithFeature(SequenceCollectionI sqcol,
 +          BitSet bs, String... featureType)
    {
      FeatureRenderer fr = alignPanel == null ? null : alignPanel
              .getFeatureRenderer();
@@@ -24,6 -24,7 +24,7 @@@ import jalview.analysis.AlignmentSorter
  import jalview.analysis.AlignmentUtils;
  import jalview.analysis.CrossRef;
  import jalview.analysis.Dna;
+ import jalview.analysis.GeneticCodeI;
  import jalview.analysis.ParseProperties;
  import jalview.analysis.SequenceIdMatcher;
  import jalview.api.AlignExportSettingI;
@@@ -64,6 -65,7 +65,7 @@@ import jalview.gui.ColourMenuHelper.Col
  import jalview.gui.ViewSelectionMenu.ViewSetProvider;
  import jalview.io.AlignmentProperties;
  import jalview.io.AnnotationFile;
+ import jalview.io.BackupFiles;
  import jalview.io.BioJsHTMLOutput;
  import jalview.io.DataSourceType;
  import jalview.io.FileFormat;
@@@ -134,6 -136,7 +136,7 @@@ import java.util.Hashtable
  import java.util.List;
  import java.util.Vector;
  
+ import javax.swing.ButtonGroup;
  import javax.swing.JCheckBoxMenuItem;
  import javax.swing.JEditorPane;
  import javax.swing.JInternalFrame;
@@@ -733,9 -736,9 +736,9 @@@ public class AlignFrame extends GAlignF
  
      int aSize = alignPanels.size();
  
-     tabbedPane.setVisible(aSize > 1 || ap.av.viewName != null);
+     tabbedPane.setVisible(aSize > 1 || ap.av.getViewName() != null);
  
-     if (aSize == 1 && ap.av.viewName == null)
+     if (aSize == 1 && ap.av.getViewName() == null)
      {
        this.getContentPane().add(ap, BorderLayout.CENTER);
      }
  
        expandViews.setEnabled(true);
        gatherViews.setEnabled(true);
-       tabbedPane.addTab(ap.av.viewName, ap);
+       tabbedPane.addTab(ap.av.getViewName(), ap);
  
        ap.setVisible(false);
      }
      gatherViews.setEnabled(true);
      tabbedPane.setVisible(true);
      AlignmentPanel first = alignPanels.get(0);
-     tabbedPane.addTab(first.av.viewName, first);
+     tabbedPane.addTab(first.av.getViewName(), first);
      this.getContentPane().add(tabbedPane, BorderLayout.CENTER);
    }
  
     * @param av
     *          AlignViewport
     */
-   void setMenusFromViewport(AlignViewport av)
+   public void setMenusFromViewport(AlignViewport av)
    {
      padGapsMenuitem.setSelected(av.isPadGaps());
      colourTextMenuItem.setSelected(av.isShowColourText());
      return progressBar.operationInProgress();
    }
  
+   /**
+    * Sets the text of the status bar. Note that setting a null or empty value
+    * will cause the status bar to be hidden, with possibly undesirable flicker
+    * of the screen layout.
+    */
    @Override
    public void setStatus(String text)
    {
-     statusBar.setText(text);
+     statusBar.setText(text == null || text.isEmpty() ? " " : text);
    }
  
    /*
                  shortName.lastIndexOf(java.io.File.separatorChar) + 1);
        }
  
-       success = new Jalview2XML().saveAlignment(this, file, shortName);
+       success = new jalview.project.Jalview2XML().saveAlignment(this, file,
+               shortName);
  
        statusBar.setText(MessageManager.formatMessage(
                "label.successfully_saved_to_file_in_format", new Object[]
        }
        else
        {
+         // create backupfiles object and get new temp filename destination
+         BackupFiles backupfiles = new BackupFiles(file);
          try
          {
-           PrintWriter out = new PrintWriter(new FileWriter(file));
+           PrintWriter out = new PrintWriter(
+                   new FileWriter(backupfiles.getTempFilePath()));
  
            out.print(output);
            out.close();
            success = false;
            ex.printStackTrace();
          }
+         backupfiles.setWriteSuccess(success);
+         // do the backup file roll and rename the temp file to actual file
+         success = backupfiles.rollBackupsAndRenameTempFile();
        }
      }
  
    @Override
    public void selectAllSequenceMenuItem_actionPerformed(ActionEvent e)
    {
-     SequenceGroup sg = new SequenceGroup();
-     for (int i = 0; i < viewport.getAlignment().getSequences().size(); i++)
-     {
-       sg.addSequence(viewport.getAlignment().getSequenceAt(i), false);
-     }
+     SequenceGroup sg = new SequenceGroup(
+             viewport.getAlignment().getSequences());
  
      sg.setEndRes(viewport.getAlignment().getWidth() - 1);
      viewport.setSelectionGroup(sg);
+     viewport.isSelectionGroupChanged(true);
      viewport.sendSelection();
      // JAL-2034 - should delegate to
      // alignPanel to decide if overview needs
      /*
       * Create a new AlignmentPanel (with its own, new Viewport)
       */
-     AlignmentPanel newap = new Jalview2XML().copyAlignPanel(alignPanel);
+     AlignmentPanel newap = new jalview.project.Jalview2XML()
+             .copyAlignPanel(alignPanel);
      if (!copyAnnotation)
      {
        /*
  
      newap.av.setGatherViewsHere(false);
  
-     if (viewport.viewName == null)
+     if (viewport.getViewName() == null)
      {
-       viewport.viewName = MessageManager
-               .getString("label.view_name_original");
+       viewport.setViewName(MessageManager
+               .getString("label.view_name_original"));
      }
  
      /*
      newap.av.setRedoList(viewport.getRedoList());
  
      /*
+      * copy any visualisation settings that are not saved in the project
+      */
+     newap.av.setColourAppliesToAllGroups(
+             viewport.getColourAppliesToAllGroups());
+     /*
       * Views share the same mappings; need to deregister any new mappings
       * created by copyAlignPanel, and register the new reference to the shared
       * mappings
        newap.refresh(true); // adjust layout of annotations
      }
  
-     newap.av.viewName = getNewViewName(viewTitle);
+     newap.av.setViewName(getNewViewName(viewTitle));
  
      addAlignmentPanel(newap, true);
      newap.alignmentChanged();
        if (comp instanceof AlignmentPanel)
        {
          AlignmentPanel ap = (AlignmentPanel) comp;
-         if (!existingNames.contains(ap.av.viewName))
+         if (!existingNames.contains(ap.av.getViewName()))
          {
-           existingNames.add(ap.av.viewName);
+           existingNames.add(ap.av.getViewName());
          }
        }
      }
      viewport.setFollowHighlight(state);
      if (state)
      {
-       alignPanel.scrollToPosition(viewport.getSearchResults(), false);
+       alignPanel.scrollToPosition(viewport.getSearchResults());
      }
    }
  
      viewport.expandColSelection(sg, false);
      viewport.hideAllSelectedSeqs();
      viewport.hideSelectedColumns();
+     alignPanel.updateLayout();
      alignPanel.paintAlignment(true, true);
      viewport.sendSelection();
    }
    public void hideSelColumns_actionPerformed(ActionEvent e)
    {
      viewport.hideSelectedColumns();
+     alignPanel.updateLayout();
      alignPanel.paintAlignment(true, true);
      viewport.sendSelection();
    }
    protected void scaleAbove_actionPerformed(ActionEvent e)
    {
      viewport.setScaleAboveWrapped(scaleAbove.isSelected());
-     // TODO: do we actually need to update overview for scale above change ?
+     alignPanel.updateLayout();
      alignPanel.paintAlignment(true, false);
    }
  
    protected void scaleLeft_actionPerformed(ActionEvent e)
    {
      viewport.setScaleLeftWrapped(scaleLeft.isSelected());
+     alignPanel.updateLayout();
      alignPanel.paintAlignment(true, false);
    }
  
    protected void scaleRight_actionPerformed(ActionEvent e)
    {
      viewport.setScaleRightWrapped(scaleRight.isSelected());
+     alignPanel.updateLayout();
      alignPanel.paintAlignment(true, false);
    }
  
       * otherwise set the chosen colour scheme (or null for 'None')
       */
      ColourSchemeI cs = ColourSchemes.getInstance().getColourScheme(name,
+             viewport,
              viewport.getAlignment(), viewport.getHiddenRepSequences());
      changeColour(cs);
    }
  
      frameTitle += " from ";
  
-     if (viewport.viewName != null)
+     if (viewport.getViewName() != null)
      {
-       frameTitle += viewport.viewName + " of ";
+       frameTitle += viewport.getViewName() + " of ";
      }
  
      frameTitle += this.title;
     * frame's DNA sequences to their aligned protein (amino acid) equivalents.
     */
    @Override
-   public void showTranslation_actionPerformed(ActionEvent e)
+   public void showTranslation_actionPerformed(GeneticCodeI codeTable)
    {
      AlignmentI al = null;
      try
      {
        Dna dna = new Dna(viewport, viewport.getViewAsVisibleContigs(true));
  
-       al = dna.translateCdna();
+       al = dna.translateCdna(codeTable);
      } catch (Exception ex)
      {
        jalview.bin.Cache.log.error(
        af.setFileFormat(this.currentFileFormat);
        final String newTitle = MessageManager
                .formatMessage("label.translation_of_params", new Object[]
-               { this.getTitle() });
+               { this.getTitle(), codeTable.getId() });
        af.setTitle(newTitle);
        if (Cache.getDefault(Preferences.ENABLE_SPLIT_FRAME, true))
        {
  
        if (reply != null)
        {
-         viewport.viewName = reply;
+         viewport.setViewName(reply);
          // TODO warn if reply is in getExistingViewNames()?
          tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), reply);
        }
      {
        PaintRefresher.Refresh(this, viewport.getSequenceSetId());
        alignPanel.updateAnnotation();
-       alignPanel.paintAlignment(true, true);
+       alignPanel.paintAlignment(true,
+               viewport.needToUpdateStructureViews());
      }
    }
  
     */
    public List<? extends AlignmentViewPanel> getAlignPanels()
    {
-     return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels;
+     // alignPanels is never null
+     // return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels;
+     return alignPanels;
    }
  
    /**
    }
  
    /**
 -   * Hides columns containing (or not containing) a specified feature, provided
 -   * that would not leave all columns hidden
 +   * Hides columns containing (or not containing) the specified feature(s),
 +   * provided that would not leave all columns hidden
     * 
 -   * @param featureType
     * @param columnsContaining
 +   * @param featureTypes
 +   * 
     * @return
     */
 -  public boolean hideFeatureColumns(String featureType,
 -          boolean columnsContaining)
 +  public boolean hideFeatureColumns(boolean columnsContaining,
 +          String... featureTypes)
    {
      boolean notForHiding = avc.markColumnsContainingFeatures(
 -            columnsContaining, false, false, featureType);
 +            columnsContaining, false, false, featureTypes);
      if (notForHiding)
      {
        if (avc.markColumnsContainingFeatures(!columnsContaining, false,
 -              false, featureType))
 +              false, featureTypes))
        {
          getViewport().hideSelectedColumns();
          return true;
      colourMenu.add(textColour);
      colourMenu.addSeparator();
  
-     ColourMenuHelper.addMenuItems(colourMenu, this, viewport.getAlignment(),
-             false);
+     ButtonGroup bg = ColourMenuHelper.addMenuItems(colourMenu, this,
+             viewport.getAlignment(), false);
  
+     colourMenu.add(annotationColour);
+     bg.add(annotationColour);
      colourMenu.addSeparator();
      colourMenu.add(conservationMenuItem);
      colourMenu.add(modifyConservation);
      colourMenu.add(abovePIDThreshold);
      colourMenu.add(modifyPID);
-     colourMenu.add(annotationColour);
  
      ColourSchemeI colourScheme = viewport.getGlobalColourScheme();
      ColourMenuHelper.setColourSelected(colourMenu, colourScheme);
@@@ -24,21 -24,21 +24,23 @@@ import jalview.api.FeatureColourI
  import jalview.api.FeatureSettingsControllerI;
  import jalview.datamodel.AlignmentI;
  import jalview.datamodel.SequenceI;
+ import jalview.datamodel.features.FeatureMatcher;
  import jalview.datamodel.features.FeatureMatcherI;
  import jalview.datamodel.features.FeatureMatcherSet;
  import jalview.datamodel.features.FeatureMatcherSetI;
 +import jalview.datamodel.ontology.OntologyI;
  import jalview.gui.Help.HelpId;
  import jalview.io.JalviewFileChooser;
  import jalview.io.JalviewFileView;
 +import jalview.io.gff.SequenceOntologyFactory;
- import jalview.schemabinding.version2.Filter;
- import jalview.schemabinding.version2.JalviewUserColours;
- import jalview.schemabinding.version2.MatcherSet;
  import jalview.schemes.FeatureColour;
  import jalview.util.MessageManager;
  import jalview.util.Platform;
  import jalview.viewmodel.seqfeatures.FeatureRendererModel.FeatureSettingsBean;
+ import jalview.xml.binding.jalview.JalviewUserColours;
+ import jalview.xml.binding.jalview.JalviewUserColours.Colour;
+ import jalview.xml.binding.jalview.JalviewUserColours.Filter;
+ import jalview.xml.binding.jalview.ObjectFactory;
  
  import java.awt.BorderLayout;
  import java.awt.Color;
@@@ -64,7 -64,6 +66,7 @@@ import java.io.FileOutputStream
  import java.io.InputStreamReader;
  import java.io.OutputStreamWriter;
  import java.io.PrintWriter;
 +import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Comparator;
  import java.util.HashMap;
@@@ -81,7 -80,6 +83,6 @@@ 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;
@@@ -94,21 -92,24 +95,28 @@@ import javax.swing.JScrollPane
  import javax.swing.JSlider;
  import javax.swing.JTable;
  import javax.swing.ListSelectionModel;
 +import javax.swing.RowFilter;
  import javax.swing.SwingConstants;
+ import javax.swing.border.Border;
  import javax.swing.event.ChangeEvent;
  import javax.swing.event.ChangeListener;
  import javax.swing.table.AbstractTableModel;
+ import javax.swing.table.JTableHeader;
  import javax.swing.table.TableCellEditor;
  import javax.swing.table.TableCellRenderer;
  import javax.swing.table.TableColumn;
 +import javax.swing.table.TableRowSorter;
+ import javax.xml.bind.JAXBContext;
+ import javax.xml.bind.JAXBElement;
+ import javax.xml.bind.Marshaller;
+ import javax.xml.stream.XMLInputFactory;
+ import javax.xml.stream.XMLStreamReader;
  
  public class FeatureSettings extends JPanel
          implements FeatureSettingsControllerI
  {
 +  private static final Font VERDANA_12 = new Font("Verdana", Font.PLAIN, 12);
 +
    private static final String SEQUENCE_FEATURE_COLOURS = MessageManager
            .getString("label.sequence_feature_colours");
  
  
    private static final int MIN_HEIGHT = 400;
  
+   private final static String BASE_TOOLTIP = MessageManager.getString("label.click_to_edit");
    final FeatureRenderer fr;
  
    public final AlignFrame af;
     */
    Map<String, float[]> typeWidth = null;
  
 +  /*
 +   * if true, 'child' feature types are not displayed
 +   */
 +  JCheckBox summaryView;
 +
 +  /*
 +   * those feature types that do not have a parent feature type present
 +   * (as determined by an Ontology relationship)
 +   */
 +  List<String> topLevelTypes;
 +
    /**
     * Constructor
     * 
  
      originalFilters = new HashMap<>(fr.getFeatureFilters()); // shallow copy
  
 +    topLevelTypes = new ArrayList<>();
 +
      try
      {
        jbInit();
        ex.printStackTrace();
      }
  
 +    initTable();
 +
 +    scrollPane.setViewportView(table);
 +
 +    if (af.getViewport().isShowSequenceFeatures() || !fr.hasRenderOrder())
 +    {
 +      fr.findAllFeatures(true); // display everything!
 +    }
 +
 +    discoverAllFeatureData();
 +    final PropertyChangeListener change;
 +    final FeatureSettings fs = this;
 +    fr.addPropertyChangeListener(change = new PropertyChangeListener()
 +    {
 +      @Override
 +      public void propertyChange(PropertyChangeEvent evt)
 +      {
 +        if (!fs.resettingTable && !fs.handlingUpdate)
 +        {
 +          fs.handlingUpdate = true;
 +          fs.resetTable(null);
 +          // new groups may be added with new sequence feature types only
 +          fs.handlingUpdate = false;
 +        }
 +      }
 +    });
 +
 +    frame = new JInternalFrame();
 +    frame.setContentPane(this);
 +    if (Platform.isAMac())
 +    {
 +      Desktop.addInternalFrame(frame,
 +              MessageManager.getString("label.sequence_feature_settings"),
 +              600, 480);
 +    }
 +    else
 +    {
 +      Desktop.addInternalFrame(frame,
 +              MessageManager.getString("label.sequence_feature_settings"),
 +              600, 450);
 +    }
 +    frame.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
 +
 +    frame.addInternalFrameListener(
 +            new javax.swing.event.InternalFrameAdapter()
 +            {
 +              @Override
 +              public void internalFrameClosed(
 +                      javax.swing.event.InternalFrameEvent evt)
 +              {
 +                fr.removePropertyChangeListener(change);
 +              };
 +            });
 +    frame.setLayer(JLayeredPane.PALETTE_LAYER);
 +    inConstruction = false;
 +  }
 +
 +  /**
 +   * Constructs and configures the JTable which displays columns of data for
 +   * each feature type
 +   */
 +  protected void initTable()
 +  {
      table = new JTable()
      {
        @Override
        {
          String tip = null;
          int column = table.columnAtPoint(e.getPoint());
+         int row = table.rowAtPoint(e.getPoint());
          switch (column)
          {
          case TYPE_COLUMN:
 -          tip = JvSwingUtils.wrapTooltip(true, MessageManager
 +          /*
 +           * drag to reorder not enabled in Summary View
 +           */
 +          tip = summaryView.isSelected()
 +                  ? MessageManager.getString(
 +                          "label.feature_settings_select_columns")
 +                  : JvSwingUtils.wrapTooltip(true, MessageManager
                    .getString("label.feature_settings_click_drag"));
            break;
+         case COLOUR_COLUMN:
+           FeatureColourI colour = (FeatureColourI) table.getValueAt(row,
+                   column);
+           tip = getColorTooltip(colour, true);
+           break;
          case FILTER_COLUMN:
            FeatureMatcherSet o = (FeatureMatcherSet) table.getValueAt(row,
                    column);
            tip = o.isEmpty()
-                   ? MessageManager.getString("label.filters_tooltip")
+                   ? MessageManager
+                           .getString("label.configure_feature_tooltip")
                    : o.toString();
            break;
          default:
            break;
          }
 -        
          return tip;
        }
+       /**
+        * Position the tooltip near the bottom edge of, and half way across, the
+        * current cell
+        */
+       @Override
+       public Point getToolTipLocation(MouseEvent e)
+       {
+         Point point = e.getPoint();
+         int column = table.columnAtPoint(point);
+         int row = table.rowAtPoint(point);
+         Rectangle r = getCellRect(row, column, false);
+         Point loc = new Point(r.x + r.width / 2, r.y + r.height - 3);
+         return loc;
+       }
      };
-     table.getTableHeader().setFont(VERDANA_12);
++
+     JTableHeader tableHeader = table.getTableHeader();
 -    tableHeader.setFont(new Font("Verdana", Font.PLAIN, 12));
++    tableHeader.setFont(VERDANA_12);
+     tableHeader.setReorderingAllowed(false);
 -    table.setFont(new Font("Verdana", Font.PLAIN, 12));
 +    table.setFont(VERDANA_12);
  
      table.setDefaultEditor(FeatureColour.class, new ColorEditor(this));
      table.setDefaultRenderer(FeatureColour.class, new ColorRenderer());
          String type = (String) table.getValueAt(selectedRow, TYPE_COLUMN);
          if (evt.isPopupTrigger())
          {
--          Object colour = table.getValueAt(selectedRow, COLOUR_COLUMN);
-           popupMenu(selectedRow, type, colour, evt.getX(), evt.getY());
 -          popupSort(selectedRow, type, colour, fr.getMinMax(), evt.getX(),
 -                  evt.getY());
++          popupMenu(selectedRow, type, evt.getX(), evt.getY());
          }
          else if (evt.getClickCount() == 2)
          {
            boolean invertSelection = evt.isAltDown();
            boolean toggleSelection = Platform.isControlDown(evt);
            boolean extendSelection = evt.isShiftDown();
 +          String[] terms = getTermsInScope(type);
            fr.ap.alignFrame.avc.markColumnsContainingFeatures(
 -                  invertSelection, extendSelection, toggleSelection, type);
 +                  invertSelection, extendSelection, toggleSelection, terms);
          }
        }
  
          if (evt.isPopupTrigger())
          {
            String type = (String) table.getValueAt(selectedRow, TYPE_COLUMN);
--          Object colour = table.getValueAt(selectedRow, COLOUR_COLUMN);
-           popupMenu(selectedRow, type, colour, evt.getX(), evt.getY());
 -          popupSort(selectedRow, type, colour, fr.getMinMax(), evt.getX(),
 -                  evt.getY());
++          popupMenu(selectedRow, type, evt.getX(), evt.getY());
          }
        }
      });
        public void mouseDragged(MouseEvent evt)
        {
          int newRow = table.rowAtPoint(evt.getPoint());
 -        if (newRow != selectedRow && selectedRow != -1 && newRow != -1)
 -        {
 -          /*
 -           * reposition 'selectedRow' to 'newRow' (the dragged to location)
 -           * this could be more than one row away for a very fast drag action
 -           * so just swap it with adjacent rows until we get it there
 -           */
 -          Object[][] data = ((FeatureTableModel) table.getModel())
 -                  .getData();
 -          int direction = newRow < selectedRow ? -1 : 1;
 -          for (int i = selectedRow; i != newRow; i += direction)
 -          {
 -            Object[] temp = data[i];
 -            data[i] = data[i + direction];
 -            data[i + direction] = temp;
 -          }
 -          updateFeatureRenderer(data);
 -          table.repaint();
 -          selectedRow = newRow;
 -        }
 +        dragRow(newRow);
        }
      });
 -    // table.setToolTipText(JvSwingUtils.wrapTooltip(true,
 -    // MessageManager.getString("label.feature_settings_click_drag")));
 -    scrollPane.setViewportView(table);
 +  }
  
 -    if (af.getViewport().isShowSequenceFeatures() || !fr.hasRenderOrder())
 +  /**
 +   * Answers an array consisting of the given type, and also (if 'Summary View'
 +   * is selected), any child terms in the sequence ontology
 +   * 
 +   * @param type
 +   * @return
 +   */
 +  protected String[] getTermsInScope(String type)
 +  {
 +    if (!summaryView.isSelected())
      {
 -      fr.findAllFeatures(true); // display everything!
 +      return new String[] { type };
      }
  
 -    discoverAllFeatureData();
 -    final PropertyChangeListener change;
 -    final FeatureSettings fs = this;
 -    fr.addPropertyChangeListener(change = new PropertyChangeListener()
 -    {
 -      @Override
 -      public void propertyChange(PropertyChangeEvent evt)
 -      {
 -        if (!fs.resettingTable && !fs.handlingUpdate)
 -        {
 -          fs.handlingUpdate = true;
 -          fs.resetTable(null);
 -          // new groups may be added with new sequence feature types only
 -          fs.handlingUpdate = false;
 -        }
 -      }
 +    List<String> terms = new ArrayList<>();
 +    terms.add(type);
  
 -    });
 +    OntologyI so = SequenceOntologyFactory.getInstance();
  
 -    frame = new JInternalFrame();
 -    frame.setContentPane(this);
 -    if (Platform.isAMac())
 -    {
 -      Desktop.addInternalFrame(frame,
 -              MessageManager.getString("label.sequence_feature_settings"),
 -              600, 480);
 -    }
 -    else
 +    Object[][] data = ((FeatureTableModel) table.getModel()).getData();
 +    for (Object[] row : data)
      {
 -      Desktop.addInternalFrame(frame,
 -              MessageManager.getString("label.sequence_feature_settings"),
 -              600, 450);
 +      String type2 = (String) row[TYPE_COLUMN];
 +      if (!type2.equals(type) && so.isA(type2, type))
 +      {
 +        terms.add(type2);
 +      }
      }
 -    frame.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
 -
 -    frame.addInternalFrameListener(
 -            new javax.swing.event.InternalFrameAdapter()
 -            {
 -              @Override
 -              public void internalFrameClosed(
 -                      javax.swing.event.InternalFrameEvent evt)
 -              {
 -                fr.removePropertyChangeListener(change);
 -              };
 -            });
 -    frame.setLayer(JLayeredPane.PALETTE_LAYER);
 -    inConstruction = false;
 +    return terms.toArray(new String[terms.size()]);
    }
  
-   protected void popupMenu(final int rowSelected, final String type,
-           final Object typeCol, int x, int y)
 -  protected void popupSort(final int rowSelected, final String type,
 -          final Object typeCol, final Map<String, float[][]> minmax, int x,
++  protected void popupMenu(final int rowSelected, final String type, int x,
+           int y)
    {
--    final FeatureColourI featureColour = (FeatureColourI) typeCol;
--
      JPopupMenu men = new JPopupMenu(MessageManager
              .formatMessage("label.settings_for_param", new String[]
              { type }));
      final FeatureSettings me = this;
      scr.addActionListener(new ActionListener()
      {
        @Override
        public void actionPerformed(ActionEvent e)
        {
 -        me.af.avc
 -                .sortAlignmentByFeatureScore(Arrays.asList(new String[]
 -                { type }));
 +        String[] types = getTermsInScope(type);
 +        me.af.avc.sortAlignmentByFeatureScore(Arrays.asList(types));
        }
 -
      });
      JMenuItem dens = new JMenuItem(
              MessageManager.getString("label.sort_by_density"));
      dens.addActionListener(new ActionListener()
      {
        @Override
        public void actionPerformed(ActionEvent e)
        {
 -        me.af.avc
 -                .sortAlignmentByFeatureDensity(Arrays.asList(new String[]
 -                { type }));
 +        String[] types = getTermsInScope(type);
 +        me.af.avc.sortAlignmentByFeatureDensity(Arrays.asList(types));
        }
      });
      men.add(dens);
  
-     /*
-      * variable colour options include colour by label, by score,
-      * by selected attribute text, or attribute value
-      */
-     final JCheckBoxMenuItem mxcol = new JCheckBoxMenuItem(
-             MessageManager.getString("label.variable_colour"));
-     mxcol.setSelected(!featureColour.isSimpleColour());
-     men.add(mxcol);
-     mxcol.addActionListener(new ActionListener()
-     {
-       JColorChooser colorChooser;
-       @Override
-       public void actionPerformed(ActionEvent e)
-       {
-         if (e.getSource() == mxcol)
-         {
-           if (featureColour.isSimpleColour())
-           {
-             FeatureTypeSettings fc = new FeatureTypeSettings(me.fr, type);
-             fc.addActionListener(this);
-           }
-           else
-           {
-             // bring up simple color chooser
-             colorChooser = new JColorChooser();
-             String title = MessageManager
-                     .getString("label.select_colour");
-             JDialog dialog = JColorChooser.createDialog(me,
-                     title, true, // modal
-                     colorChooser, this, // OK button handler
-                     null); // no CANCEL button handler
-             colorChooser.setColor(featureColour.getMaxColour());
-             dialog.setVisible(true);
-           }
-         }
-         else
-         {
-           if (e.getSource() instanceof FeatureTypeSettings)
-           {
-             /*
-              * update after OK in feature colour dialog; the updated
-              * colour will have already been set in the FeatureRenderer
-              */
-             FeatureColourI fci = fr.getFeatureColours().get(type);
-             table.setValueAt(fci, rowSelected, 1);
-             table.validate();
-           }
-           else
-           {
-             // probably the color chooser!
-             table.setValueAt(new FeatureColour(colorChooser.getColor()),
-                     rowSelected, 1);
-             table.validate();
-             me.updateFeatureRenderer(
-                     ((FeatureTableModel) table.getModel()).getData(),
-                     false);
-           }
-         }
-       }
-     });
      JMenuItem selCols = new JMenuItem(
              MessageManager.getString("label.select_columns_containing"));
      selCols.addActionListener(new ActionListener()
        @Override
        public void actionPerformed(ActionEvent arg0)
        {
 +        String[] types = getTermsInScope(type);
          fr.ap.alignFrame.avc.markColumnsContainingFeatures(false, false,
 -                false, type);
 +                false, types);
        }
      });
      JMenuItem clearCols = new JMenuItem(MessageManager
        @Override
        public void actionPerformed(ActionEvent arg0)
        {
 +        String[] types = getTermsInScope(type);
          fr.ap.alignFrame.avc.markColumnsContainingFeatures(true, false,
 -                false, type);
 +                false, types);
        }
      });
      JMenuItem hideCols = new JMenuItem(
        @Override
        public void actionPerformed(ActionEvent arg0)
        {
 -        fr.ap.alignFrame.hideFeatureColumns(type, true);
 +        String[] types = getTermsInScope(type);
 +        fr.ap.alignFrame.hideFeatureColumns(true, types);
        }
      });
      JMenuItem hideOtherCols = new JMenuItem(
        @Override
        public void actionPerformed(ActionEvent arg0)
        {
 -        fr.ap.alignFrame.hideFeatureColumns(type, false);
 +        String[] types = getTermsInScope(type);
 +        fr.ap.alignFrame.hideFeatureColumns(false, types);
        }
      });
      men.add(selCols);
         */
        Set<String> types = seq.getFeatures().getFeatureTypesForGroups(true,
                visibleGroups.toArray(new String[visibleGroups.size()]));
 +
        for (String type : types)
        {
          displayableTypes.add(type);
        }
      }
  
 +    /*
 +     * enable 'Summary View' if some types are sub-types of others
 +     */
 +    Set<String> parents = SequenceOntologyFactory.getInstance()
 +            .getParentTerms(displayableTypes);
 +    summaryView.setEnabled(parents.size() < displayableTypes.size());
 +
      Object[][] data = new Object[displayableTypes.size()][COLUMN_COUNT];
      int dataIndex = 0;
  
          {
            continue;
          }
 -
          data[dataIndex][TYPE_COLUMN] = type;
          data[dataIndex][COLOUR_COLUMN] = fr.getFeatureStyle(type);
          FeatureMatcherSetI featureFilter = fr.getFeatureFilter(type);
        updateOriginalData(data);
      }
  
 -    table.setModel(new FeatureTableModel(data));
 +    /*
 +     * recreate the table model
 +     */
 +    FeatureTableModel dataModel = new FeatureTableModel(data);
 +    table.setModel(dataModel);
 +
 +    /*
 +     * we want to be able to filter out rows for sub-types, but not to sort 
 +     * rows, so have to add a RowFilter to a disabled TableRowSorter (!)
 +     */
 +    final TableRowSorter<FeatureTableModel> sorter = new TableRowSorter<>(
 +            dataModel);
 +    for (int i = 0; i < table.getColumnCount(); i++)
 +    {
 +      sorter.setSortable(i, false);
 +    }
 +
 +    /*
 +     * filter rows to only top-level Ontology types if requested
 +     */
 +    sorter.setRowFilter(new RowFilter<FeatureTableModel, Integer>()
 +    {
 +      @Override
 +      public boolean include(
 +              Entry<? extends FeatureTableModel, ? extends Integer> entry)
 +      {
 +        if (!summaryView.isSelected())
 +        {
 +          return true;
 +        }
 +        int row = entry.getIdentifier(); // this is model, not view, row number
 +        String featureType = (String) entry.getModel().getData()[row][TYPE_COLUMN];
 +        return parents.contains(featureType);
 +      }
 +    });
 +    table.setRowSorter(sorter);
 +
      table.getColumnModel().getColumn(0).setPreferredWidth(200);
  
      groupPanel.setLayout(
        InputStreamReader in = new InputStreamReader(
                new FileInputStream(file), "UTF-8");
  
-       JalviewUserColours jucs = JalviewUserColours.unmarshal(in);
+       JAXBContext jc = JAXBContext
+               .newInstance("jalview.xml.binding.jalview");
+       javax.xml.bind.Unmarshaller um = jc.createUnmarshaller();
+       XMLStreamReader streamReader = XMLInputFactory.newInstance()
+               .createXMLStreamReader(in);
+       JAXBElement<JalviewUserColours> jbe = um.unmarshal(streamReader,
+               JalviewUserColours.class);
+       JalviewUserColours jucs = jbe.getValue();
+       // JalviewUserColours jucs = JalviewUserColours.unmarshal(in);
  
        /*
         * load feature colours
         */
-       for (int i = jucs.getColourCount() - 1; i >= 0; i--)
+       for (int i = jucs.getColour().size() - 1; i >= 0; i--)
        {
-         jalview.schemabinding.version2.Colour newcol = jucs.getColour(i);
-         FeatureColourI colour = Jalview2XML.unmarshalColour(newcol);
+         Colour newcol = jucs.getColour().get(i);
+         FeatureColourI colour = jalview.project.Jalview2XML
+                 .parseColour(newcol);
          fr.setColour(newcol.getName(), colour);
-         fr.setOrder(newcol.getName(), i / (float) jucs.getColourCount());
+         fr.setOrder(newcol.getName(), i / (float) jucs.getColour().size());
        }
  
        /*
         * load feature filters; loaded filters will replace any that are
         * currently defined, other defined filters are left unchanged 
         */
-       for (int i = 0; i < jucs.getFilterCount(); i++)
+       for (int i = 0; i < jucs.getFilter().size(); i++)
        {
-         jalview.schemabinding.version2.Filter filterModel = jucs
-                 .getFilter(i);
+         Filter filterModel = jucs.getFilter().get(i);
          String featureType = filterModel.getFeatureType();
-         FeatureMatcherSetI filter = Jalview2XML.unmarshalFilter(featureType,
-                 filterModel.getMatcherSet());
+         FeatureMatcherSetI filter = jalview.project.Jalview2XML
+                 .parseFilter(featureType, filterModel.getMatcherSet());
          if (!filter.isEmpty())
          {
            fr.setFeatureFilter(featureType, filter);
        for (String featureType : sortedTypes)
        {
          FeatureColourI fcol = fr.getFeatureStyle(featureType);
-         jalview.schemabinding.version2.Colour col = Jalview2XML.marshalColour(
-                 featureType, fcol);
-         ucs.addColour(col);
+         Colour col = jalview.project.Jalview2XML.marshalColour(featureType,
+                 fcol);
+         ucs.getColour().add(col);
        }
  
        /*
          {
            Iterator<FeatureMatcherI> iterator = filter.getMatchers().iterator();
            FeatureMatcherI firstMatcher = iterator.next();
-           MatcherSet ms = Jalview2XML.marshalFilter(firstMatcher, iterator,
+           jalview.xml.binding.jalview.FeatureMatcherSet ms = jalview.project.Jalview2XML
+                   .marshalFilter(firstMatcher, iterator,
                    filter.isAnded());
            Filter filterModel = new Filter();
            filterModel.setFeatureType(featureType);
            filterModel.setMatcherSet(ms);
-           ucs.addFilter(filterModel);
+           ucs.getFilter().add(filterModel);
          }
        }
+       JAXBContext jaxbContext = JAXBContext
+               .newInstance(JalviewUserColours.class);
+       Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
+       jaxbMarshaller.marshal(
+               new ObjectFactory().createJalviewUserColours(ucs), out);
+       // jaxbMarshaller.marshal(object, pout);
+       // marshaller.marshal(object);
+       out.flush();
  
-       ucs.marshal(out);
+       // ucs.marshal(out);
        out.close();
      } catch (Exception ex)
      {
          }
        }
      });
-     help.setFont(JvSwingUtils.getLabelFont());
-     help.setText(MessageManager.getString("action.help"));
-     help.addActionListener(new ActionListener()
-     {
-       @Override
-       public void actionPerformed(ActionEvent e)
-       {
-         try
-         {
-           Help.showHelpWindow(HelpId.SequenceFeatureSettings);
-         } catch (HelpSetException e1)
-         {
-           e1.printStackTrace();
-         }
-       }
-     });
  
      JButton cancel = new JButton(MessageManager.getString("action.cancel"));
      cancel.setFont(JvSwingUtils.getLabelFont());
        }
      });
  
 +    summaryView = new JCheckBox(
 +            MessageManager.getString("label.summary_view"));
 +    summaryView
 +            .setToolTipText(
 +                    MessageManager.getString("label.summary_view_tip"));
 +    summaryView.addActionListener(new ActionListener()
 +    {
 +      @Override
 +      public void actionPerformed(ActionEvent e)
 +      {
 +        resetTable(null);
 +      }
 +    });
 +
      transparency.setMaximum(70);
      transparency.setToolTipText(
              MessageManager.getString("label.transparency_tip"));
  
 -    JPanel transPanel = new JPanel(new GridLayout(1, 2));
 -    bigPanel.add(transPanel, BorderLayout.SOUTH);
 +    JPanel lowerPanel = new JPanel(new GridLayout(1, 2));
 +    bigPanel.add(lowerPanel, BorderLayout.SOUTH);
  
      JPanel transbuttons = new JPanel(new GridLayout(5, 1));
      transbuttons.add(optimizeOrder);
      transbuttons.add(sortByScore);
      transbuttons.add(sortByDens);
      transbuttons.add(help);
 +    JPanel transPanel = new JPanel(new GridLayout(3, 1));
 +    transPanel.add(summaryView);
 +    transPanel.add(new JLabel(" Colour transparency" + ":"));
      transPanel.add(transparency);
 -    transPanel.add(transbuttons);
 +    lowerPanel.add(transPanel);
 +    lowerPanel.add(transbuttons);
  
      JPanel buttonPanel = new JPanel();
      buttonPanel.add(ok);
    }
  
    /**
 +   * Reorders features by 'dragging' selectedRow to 'newRow'
 +   * 
 +   * @param newRow
 +   */
 +  protected void dragRow(int newRow)
 +  {
 +    if (summaryView.isSelected())
 +    {
 +      // no drag while in summary view
 +      return;
 +    }
 +
 +    if (newRow != selectedRow && selectedRow != -1 && newRow != -1)
 +    {
 +      /*
 +       * reposition 'selectedRow' to 'newRow' (the dragged to location)
 +       * this could be more than one row away for a very fast drag action
 +       * so just swap it with adjacent rows until we get it there
 +       */
 +      Object[][] data = ((FeatureTableModel) table.getModel())
 +              .getData();
 +      int direction = newRow < selectedRow ? -1 : 1;
 +      for (int i = selectedRow; i != newRow; i += direction)
 +      {
 +        Object[] temp = data[i];
 +        data[i] = data[i + direction];
 +        data[i + direction] = temp;
 +      }
 +      updateFeatureRenderer(data);
 +      table.repaint();
 +      selectedRow = newRow;
 +    }
 +  }
 +
 +  protected void refreshTable()
 +  {
 +    Object[][] data = ((FeatureTableModel) table.getModel()).getData();
 +    for (Object[] row : data)
 +    {
 +      String type = (String) row[TYPE_COLUMN];
 +      FeatureColourI colour = fr.getFeatureColours().get(type);
 +      FeatureMatcherSetI filter = fr.getFeatureFilter(type);
 +      if (filter == null)
 +      {
 +        filter = new FeatureMatcherSet();
 +      }
 +      row[COLOUR_COLUMN] = colour;
 +      row[FILTER_COLUMN] = filter;
 +    }
 +    repaint();
 +  }
 +
++  /*
+    * Answers a suitable tooltip to show on the colour cell of the table
+    * 
+    * @param fcol
+    * @param withHint
+    *          if true include 'click to edit' and similar text
+    * @return
+    */
+   public static String getColorTooltip(FeatureColourI fcol,
+           boolean withHint)
+   {
+     if (fcol == null)
+     {
+       return null;
+     }
+     if (fcol.isSimpleColour())
+     {
+       return withHint ? BASE_TOOLTIP : null;
+     }
+     String description = fcol.getDescription();
+     description = description.replaceAll("<", "&lt;");
+     description = description.replaceAll(">", "&gt;");
+     StringBuilder tt = new StringBuilder(description);
+     if (withHint)
+     {
+       tt.append("<br>").append(BASE_TOOLTIP).append("</br>");
+     }
+     return JvSwingUtils.wrapTooltip(true, tt.toString());
+   }
+   public static void renderGraduatedColor(JLabel comp, FeatureColourI gcol,
+           int w, int h)
+   {
+     boolean thr = false;
+     StringBuilder tx = new StringBuilder();
+   
+     if (gcol.isColourByAttribute())
+     {
+       tx.append(FeatureMatcher
+               .toAttributeDisplayName(gcol.getAttributeName()));
+     }
+     else if (!gcol.isColourByLabel())
+     {
+       tx.append(MessageManager.getString("label.score"));
+     }
+     tx.append(" ");
+     if (gcol.isAboveThreshold())
+     {
+       thr = true;
+       tx.append(">");
+     }
+     if (gcol.isBelowThreshold())
+     {
+       thr = true;
+       tx.append("<");
+     }
+     if (gcol.isColourByLabel())
+     {
+       if (thr)
+       {
+         tx.append(" ");
+       }
+       if (!gcol.isColourByAttribute())
+       {
+         tx.append("Label");
+       }
+       comp.setIcon(null);
+     }
+     else
+     {
+       Color newColor = gcol.getMaxColour();
+       comp.setBackground(newColor);
+       // System.err.println("Width is " + w / 2);
+       Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w, h, thr);
+       comp.setIcon(ficon);
+       // tt+="RGB value: Max (" + newColor.getRed() + ", "
+       // + newColor.getGreen() + ", " + newColor.getBlue()
+       // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
+       // + ", " + minCol.getBlue() + ")");
+     }
+     comp.setHorizontalAlignment(SwingConstants.CENTER);
+     comp.setText(tx.toString());
+   }
    // ///////////////////////////////////////////////////////////////////////
    // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html
    // ///////////////////////////////////////////////////////////////////////
      private String[] columnNames = {
          MessageManager.getString("label.feature_type"),
          MessageManager.getString("action.colour"),
-         MessageManager.getString("label.filter"),
+         MessageManager.getString("label.configuration"),
          MessageManager.getString("label.show") };
  
      private Object[][] data;
      }
  
      /**
 -     * Answers the class of the object in column c of the first row of the table
 +     * Answers the class of column c of the table
       */
      @Override
      public Class<?> getColumnClass(int c)
      {
 -      Object v = getValueAt(0, c);
 -      return v == null ? null : v.getClass();
 +      switch (c)
 +      {
 +      case TYPE_COLUMN:
 +        return String.class;
 +      case COLOUR_COLUMN:
 +        return FeatureColour.class;
 +      case FILTER_COLUMN:
 +        return FeatureMatcherSet.class;
 +      default:
 +        return Boolean.class;
 +      }
      }
  
 +    /**
 +     * Answers true for all columns except Feature Type
 +     */
      @Override
      public boolean isCellEditable(int row, int col)
      {
 -      return col == 0 ? false : true;
 +      return col != TYPE_COLUMN;
      }
  
 +    /**
 +     * Sets the value in the model for a given row and column. If Visibility
 +     * (Show/Hide) is being set, and the table is in Summary View, then it is
 +     * set also on any sub-types of the row's feature type.
 +     */
      @Override
      public void setValueAt(Object value, int row, int col)
      {
        data[row][col] = value;
        fireTableCellUpdated(row, col);
 +      if (summaryView.isSelected() && col == SHOW_COLUMN)
 +      {
 +        setSubtypesVisibility(row, (Boolean) value);
 +      }
        updateFeatureRenderer(data);
      }
  
 +    /**
 +     * Sets the visibility of any feature types which are sub-types of the type
 +     * in the given row of the table
 +     * 
 +     * @param row
 +     * @param value
 +     */
 +    protected void setSubtypesVisibility(int row, Boolean value)
 +    {
 +      String type = (String) data[row][TYPE_COLUMN];
 +      OntologyI so = SequenceOntologyFactory.getInstance();
 +
 +      for (int r = 0; r < data.length; r++)
 +      {
 +        if (r != row)
 +        {
 +          String type2 = (String) data[r][TYPE_COLUMN];
 +          if (so.isA(type2, type))
 +          {
 +            data[r][SHOW_COLUMN] = value;
 +            fireTableCellUpdated(r, SHOW_COLUMN);
 +          }
 +        }
 +      }
 +    }
    }
  
    class ColorRenderer extends JLabel implements TableCellRenderer
    {
-     javax.swing.border.Border unselectedBorder = null;
+     Border unselectedBorder = null;
  
-     javax.swing.border.Border selectedBorder = null;
-     final String baseTT = "Click to edit, right/apple click for menu.";
+     Border selectedBorder = null;
  
      public ColorRenderer()
      {
      {
        FeatureColourI cellColour = (FeatureColourI) color;
        setOpaque(true);
-       setToolTipText(baseTT);
        setBackground(tbl.getBackground());
        if (!cellColour.isSimpleColour())
        {
      renderGraduatedColor(comp, gcol, w, h);
    }
  
-   public static void renderGraduatedColor(JLabel comp, FeatureColourI gcol,
-           int w, int h)
-   {
-     boolean thr = false;
-     StringBuilder tt = new StringBuilder();
-     StringBuilder tx = new StringBuilder();
-     if (gcol.isColourByAttribute())
-     {
-       tx.append(String.join(":", gcol.getAttributeName()));
-     }
-     else if (!gcol.isColourByLabel())
-     {
-       tx.append(MessageManager.getString("label.score"));
-     }
-     tx.append(" ");
-     if (gcol.isAboveThreshold())
-     {
-       thr = true;
-       tx.append(">");
-       tt.append("Thresholded (Above ").append(gcol.getThreshold())
-               .append(") ");
-     }
-     if (gcol.isBelowThreshold())
-     {
-       thr = true;
-       tx.append("<");
-       tt.append("Thresholded (Below ").append(gcol.getThreshold())
-               .append(") ");
-     }
-     if (gcol.isColourByLabel())
-     {
-       tt.append("Coloured by label text. ").append(tt);
-       if (thr)
-       {
-         tx.append(" ");
-       }
-       if (!gcol.isColourByAttribute())
-       {
-         tx.append("Label");
-       }
-       comp.setIcon(null);
-     }
-     else
-     {
-       Color newColor = gcol.getMaxColour();
-       comp.setBackground(newColor);
-       // System.err.println("Width is " + w / 2);
-       Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w, h, thr);
-       comp.setIcon(ficon);
-       // tt+="RGB value: Max (" + newColor.getRed() + ", "
-       // + newColor.getGreen() + ", " + newColor.getBlue()
-       // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
-       // + ", " + minCol.getBlue() + ")");
-     }
-     comp.setHorizontalAlignment(SwingConstants.CENTER);
-     comp.setText(tx.toString());
-     if (tt.length() > 0)
-     {
-       if (comp.getToolTipText() == null)
-       {
-         comp.setToolTipText(tt.toString());
-       }
-       else
-       {
-         comp.setToolTipText(
-                 tt.append(" ").append(comp.getToolTipText()).toString());
-       }
-     }
-   }
    class ColorEditor extends AbstractCellEditor
            implements TableCellEditor, ActionListener
    {
  
      String type;
  
 -    JButton button;
 +    JButton colourButton;
  
      JColorChooser colorChooser;
  
        // which is a button.
        // This button brings up the color chooser dialog,
        // which is the editor from the user's point of view.
 -      button = new JButton();
 -      button.setActionCommand(EDIT);
 -      button.addActionListener(this);
 -      button.setBorderPainted(false);
 +      colourButton = new JButton();
 +      colourButton.setActionCommand(EDIT);
 +      colourButton.addActionListener(this);
 +      colourButton.setBorderPainted(false);
        // Set up the dialog that the button brings up.
        colorChooser = new JColorChooser();
 -      dialog = JColorChooser.createDialog(button,
 +      dialog = JColorChooser.createDialog(colourButton,
                MessageManager.getString("label.select_colour"), true, // modal
                colorChooser, this, // OK button handler
                null); // no CANCEL button handler
          if (currentColor.isSimpleColour())
          {
            // bring up simple color chooser
 -          button.setBackground(currentColor.getColour());
 +          colourButton.setBackground(currentColor.getColour());
            colorChooser.setColor(currentColor.getColour());
            dialog.setVisible(true);
          }
          {
            // bring up graduated chooser.
            chooser = new FeatureTypeSettings(me.fr, type);
 -          /**
 -           * @j2sNative
 -           */
 -          {
 -            chooser.setRequestFocusEnabled(true);
 -            chooser.requestFocus();
 -          }
 +          chooser.setRequestFocusEnabled(true);
 +          chooser.requestFocus();
            chooser.addActionListener(this);
            // Make the renderer reappear.
            fireEditingStopped();
             * (or filters!) are already set in FeatureRenderer, so just
             * update table data without triggering updateFeatureRenderer
             */
 -          currentColor = fr.getFeatureColours().get(type);
 -          FeatureMatcherSetI currentFilter = me.fr.getFeatureFilter(type);
 -          if (currentFilter == null)
 -          {
 -            currentFilter = new FeatureMatcherSet();
 -          }
 -          Object[] data = ((FeatureTableModel) table.getModel())
 -                  .getData()[rowSelected];
 -          data[COLOUR_COLUMN] = currentColor;
 -          data[FILTER_COLUMN] = currentFilter;
 +          refreshTable();
          }
          fireEditingStopped();
          me.table.validate();
        currentColor = (FeatureColourI) value;
        this.rowSelected = row;
        type = me.table.getValueAt(row, TYPE_COLUMN).toString();
 -      button.setOpaque(true);
 -      button.setBackground(me.getBackground());
 +      colourButton.setOpaque(true);
 +      colourButton.setBackground(me.getBackground());
        if (!currentColor.isSimpleColour())
        {
          JLabel btn = new JLabel();
 -        btn.setSize(button.getSize());
 +        btn.setSize(colourButton.getSize());
          FeatureSettings.renderGraduatedColor(btn, currentColor);
 -        button.setBackground(btn.getBackground());
 -        button.setIcon(btn.getIcon());
 -        button.setText(btn.getText());
 +        colourButton.setBackground(btn.getBackground());
 +        colourButton.setIcon(btn.getIcon());
 +        colourButton.setText(btn.getText());
        }
        else
        {
 -        button.setText("");
 -        button.setIcon(null);
 -        button.setBackground(currentColor.getColour());
 +        colourButton.setText("");
 +        colourButton.setIcon(null);
 +        colourButton.setBackground(currentColor.getColour());
        }
 -      return button;
 +      return colourButton;
      }
    }
  
  
      String type;
  
 -    JButton button;
 +    JButton filterButton;
  
      protected static final String EDIT = "edit";
  
      public FilterEditor(FeatureSettings me)
      {
        this.me = me;
 -      button = new JButton();
 -      button.setActionCommand(EDIT);
 -      button.addActionListener(this);
 -      button.setBorderPainted(false);
 +      filterButton = new JButton();
 +      filterButton.setActionCommand(EDIT);
 +      filterButton.addActionListener(this);
 +      filterButton.setBorderPainted(false);
      }
  
      /**
      @Override
      public void actionPerformed(ActionEvent e)
      {
 -      if (button == e.getSource())
 +      if (filterButton == e.getSource())
        {
          FeatureTypeSettings chooser = new FeatureTypeSettings(me.fr, type);
          chooser.addActionListener(this);
        }
        else if (e.getSource() instanceof Component)
        {
 -
          /*
           * after OK in variable colour dialog, any changes to filter
           * (or colours!) are already set in FeatureRenderer, so just
           * update table data without triggering updateFeatureRenderer
           */
 -        FeatureColourI currentColor = fr.getFeatureColours().get(type);
 -        currentFilter = me.fr.getFeatureFilter(type);
 -        if (currentFilter == null)
 -        {
 -          currentFilter = new FeatureMatcherSet();
 -        }
 -        Object[] data = ((FeatureTableModel) table.getModel())
 -                .getData()[rowSelected];
 -        data[COLOUR_COLUMN] = currentColor;
 -        data[FILTER_COLUMN] = currentFilter;
 +        refreshTable();
          fireEditingStopped();
          me.table.validate();
        }
        currentFilter = (FeatureMatcherSetI) value;
        this.rowSelected = row;
        type = me.table.getValueAt(row, TYPE_COLUMN).toString();
 -      button.setOpaque(true);
 -      button.setBackground(me.getBackground());
 -      button.setText(currentFilter.toString());
 -      button.setIcon(null);
 -      return button;
 +      filterButton.setOpaque(true);
 +      filterButton.setBackground(me.getBackground());
 +      filterButton.setText(currentFilter.toString());
 +      filterButton.setToolTipText(currentFilter.toString());
 +      filterButton.setIcon(null);
 +      return filterButton;
      }
    }
  }
  
  class FeatureIcon implements Icon
  {
 +  private static final Font VERDANA_9 = new Font("Verdana", Font.PLAIN, 9);
 +
    FeatureColourI gcol;
  
    Color backg;
        // need an icon here.
        g.setColor(gcol.getMaxColour());
  
 -      g.setFont(new Font("Verdana", Font.PLAIN, 9));
 +      g.setFont(VERDANA_9);
  
        // g.setFont(g.getFont().deriveFont(
        // AffineTransform.getScaleInstance(
@@@ -29,7 -29,6 +29,7 @@@ import jalview.datamodel.features.Featu
  import jalview.datamodel.features.FeatureMatcherI;
  import jalview.datamodel.features.FeatureMatcherSet;
  import jalview.datamodel.features.FeatureMatcherSetI;
 +import jalview.io.gff.SequenceOntologyFactory;
  import jalview.schemes.FeatureColour;
  import jalview.util.ColorUtils;
  import jalview.util.MessageManager;
@@@ -50,11 -49,7 +50,11 @@@ import java.awt.event.MouseAdapter
  import java.awt.event.MouseEvent;
  import java.text.DecimalFormat;
  import java.util.ArrayList;
 +import java.util.Collections;
 +import java.util.HashMap;
  import java.util.List;
 +import java.util.Map;
 +import java.util.Map.Entry;
  
  import javax.swing.BorderFactory;
  import javax.swing.BoxLayout;
@@@ -123,11 -118,10 +123,11 @@@ public class FeatureTypeSettings extend
  
    /*
     * the colour and filters to reset to on Cancel
 +   * (including feature sub-types if modified)
     */
 -  private final FeatureColourI originalColour;
 +  private Map<String, FeatureColourI> originalColours;
  
 -  private final FeatureMatcherSetI originalFilter;
 +  private Map<String, FeatureMatcherSetI> originalFilters;
  
    /*
     * set flag to true when setting values programmatically,
  
    private JPanel chooseFiltersPanel;
  
 +  /*
 +   * feature types present in Feature Renderer which are
 +   * sub-types of the one this editor is acting on
 +   */
 +  private final List<String> subTypes;
 +
 +  /*
 +   * if true, filter or colour settings are also applied to 
 +   * any feature sub-types in the Sequence Ontology
 +   */
 +  private boolean applyFiltersToSubtypes;
 +
 +  private boolean applyColourToSubtypes;
 +
    /**
     * Constructor
     * 
      this.fr = frender;
      this.featureType = theType;
      ap = fr.ap;
 -    originalFilter = fr.getFeatureFilter(theType);
 -    originalColour = fr.getFeatureColours().get(theType);
 -    
 +
 +    /*
 +     * determine sub-types (if any) of this feature type
 +     */
 +    List<String> types = fr.getRenderOrder();
 +    subTypes = SequenceOntologyFactory.getInstance()
 +            .getChildTerms(this.featureType, types);
 +    Collections.sort(subTypes); // sort for ease of reading in tooltip
 +
 +    /*
 +     * save original colours and filters for this feature type
 +     * and any sub-types, to restore on Cancel
 +     */
 +    originalFilters = new HashMap<>();
 +    originalFilters.put(theType, fr.getFeatureFilter(theType));
 +    originalColours = new HashMap<>();
 +    originalColours.put(theType, fr.getFeatureColours().get(theType));
 +    for (String child : subTypes)
 +    {
 +      originalFilters.put(child, fr.getFeatureFilter(child));
 +      originalColours.put(child, fr.getFeatureColours().get(child));
 +    }
 +
      adjusting = true;
      
      try
      String title = MessageManager
              .formatMessage("label.display_settings_for", new String[]
              { theType });
-     initDialogFrame(this, true, false, title, 500, 500);
-     
+     initDialogFrame(this, true, false, title, 580, 500);
      waitForInput();
    }
  
                          : BELOW_THRESHOLD_OPTION);
          slider.setEnabled(true);
          slider.setValue((int) (fc.getThreshold() * scaleFactor));
-         thresholdValue.setText(String.valueOf(getRoundedSliderValue()));
+         thresholdValue.setText(String.valueOf(fc.getThreshold()));
          thresholdValue.setEnabled(true);
          thresholdIsMin.setEnabled(true);
        }
      maxColour.setBorder(new LineBorder(Color.black));
  
      /*
-      * default max colour to last plain colour;
-      * make min colour a pale version of max colour
+      * if not set, default max colour to last plain colour,
+      * and make min colour a pale version of max colour
       */
-     FeatureColourI fc = fr.getFeatureColours().get(featureType);
-     Color bg = fc.getColour() == null ? Color.BLACK : fc.getColour();
-     maxColour.setBackground(bg);
-     minColour.setBackground(ColorUtils.bleachColour(bg, 0.9f));
++    FeatureColourI originalColour = originalColours.get(featureType);
+     Color max = originalColour.getMaxColour();
+     if (max == null)
+     {
+       max = originalColour.getColour();
+       minColour.setBackground(ColorUtils.bleachColour(max, 0.9f));
+     }
+     else
+     {
+       maxColour.setBackground(max);
+       minColour.setBackground(originalColour.getMinColour());
+     }
  
      noValueCombo = new JComboBox<>();
      noValueCombo.addItem(MessageManager.getString("label.no_colour"));
          {
            thresholdValue
                    .setText(String.valueOf(slider.getValue() / scaleFactor));
+           thresholdValue.setBackground(Color.white); // to reset red for invalid
            sliderValueChanged();
          }
        }
              MessageManager.getString("action.colour"), true);
  
      /*
 +     * option to apply colour to sub-types as well (if there are any)
 +     */
 +    if (!subTypes.isEmpty())
 +    {
 +      applyColourToSubtypes = false;
 +      colourByPanel.add(initSubtypesPanel(false));
 +    }
 +
 +    /*
       * simple colour radio button and colour picker
       */
      JPanel simpleColourPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
      singleColour.setFont(JvSwingUtils.getLabelFont());
      singleColour.setBorder(BorderFactory.createLineBorder(Color.black));
      singleColour.setPreferredSize(new Dimension(40, 20));
 -    // if (originalColour.isGraduatedColour())
 -    // {
 -    // singleColour.setBackground(originalColour.getMaxColour());
 -    // singleColour.setForeground(originalColour.getMaxColour());
 -    // }
 -    // else
 -    // {
 -      singleColour.setBackground(originalColour.getColour());
 -      singleColour.setForeground(originalColour.getColour());
 -    // }
++    FeatureColourI originalColour = originalColours.get(featureType);
++    singleColour.setBackground(originalColour.getColour());
++    singleColour.setForeground(originalColour.getColour());
++
      singleColour.addMouseListener(new MouseAdapter()
      {
        @Override
      return colourByPanel;
    }
  
 +  /**
 +   * Constructs and returns a panel with a checkbox for the option to apply any
 +   * changes also to sub-types of the feature type
 +   * 
 +   * @return
 +   */
 +  protected JPanel initSubtypesPanel(final boolean forFilters)
 +  {
 +    JPanel toSubtypes = new JPanel(new FlowLayout(FlowLayout.LEFT));
 +    toSubtypes.setBackground(Color.WHITE);
 +    JCheckBox applyToSubtypesCB = new JCheckBox(MessageManager
 +            .formatMessage("label.apply_to_subtypes", featureType));
 +    applyToSubtypesCB.setToolTipText(getSubtypesTooltip());
 +    applyToSubtypesCB.addActionListener(new ActionListener()
 +    {
 +      /*
 +       * reset and reapply settings on toggle of checkbox
 +       */
 +      @Override
 +      public void actionPerformed(ActionEvent e)
 +      {
 +        if (forFilters)
 +        {
 +          applyFiltersToSubtypes = applyToSubtypesCB.isSelected();
 +          restoreOriginalFilters();
 +          filtersChanged();
 +        }
 +        else
 +        {
 +          applyColourToSubtypes = applyToSubtypesCB.isSelected();
 +          restoreOriginalColours();
 +          colourChanged(true);
 +        }
 +      }
 +    });
 +    toSubtypes.add(applyToSubtypesCB);
 +
 +    return toSubtypes;
 +  }
 +
    private void showColourChooser(JPanel colourPanel, String key)
    {
      Color col = JColorChooser.showDialog(this,
      FeatureColourI acg = makeColourFromInputs();
  
      /*
 -     * save the colour, and repaint stuff
 +     * save the colour, and set on subtypes if selected
       */
      fr.setColour(featureType, acg);
 +    if (applyColourToSubtypes)
 +    {
 +      for (String child : subTypes)
 +      {
 +        fr.setColour(child, acg);
 +      }
 +    }
 +    refreshFeatureSettings();
      ap.paintAlignment(updateStructsAndOverview, updateStructsAndOverview);
  
      updateColoursTab();
    private FeatureColourI makeColourFromInputs()
    {
      /*
-      * easiest case - a single colour
-      */
-     if (simpleColour.isSelected())
-     {
-       return new FeatureColour(singleColour.getBackground());
-     }
-     /*
-      * next easiest case - colour by Label, or attribute text
-      */
-     if (byCategory.isSelected())
-     {
-       Color c = singleColour.getBackground();
-       FeatureColourI fc = new FeatureColour(c);
-       fc.setColourByLabel(true);
-       String byWhat = (String) colourByTextCombo.getSelectedItem();
-       if (!LABEL_18N.equals(byWhat))
-       {
-         fc.setAttributeName(
-                 FeatureMatcher.fromAttributeDisplayName(byWhat));
-       }
-       return fc;
-     }
-     /*
-      * remaining case - graduated colour by score, or attribute value
+      * min-max range is to (or from) threshold value if 
+      * 'threshold is min/max' is selected 
       */
-     Color noColour = null;
-     if (noValueCombo.getSelectedIndex() == MIN_COLOUR_OPTION)
-     {
-       noColour = minColour.getBackground();
-     }
-     else if (noValueCombo.getSelectedIndex() == MAX_COLOUR_OPTION)
-     {
-       noColour = maxColour.getBackground();
-     }
  
      float thresh = 0f;
      try
      {
        // invalid inputs are already handled on entry
      }
-     /*
-      * min-max range is to (or from) threshold value if 
-      * 'threshold is min/max' is selected 
-      */
      float minValue = min;
      float maxValue = max;
      final int thresholdOption = threshold.getSelectedIndex();
      {
        maxValue = thresh;
      }
+     Color noColour = null;
+     if (noValueCombo.getSelectedIndex() == MIN_COLOUR_OPTION)
+     {
+       noColour = minColour.getBackground();
+     }
+     else if (noValueCombo.getSelectedIndex() == MAX_COLOUR_OPTION)
+     {
+       noColour = maxColour.getBackground();
+     }
  
      /*
-      * make the graduated colour
+      * construct a colour that 'remembers' all the options, including
+      * those not currently selected
       */
-     FeatureColourI fc = new FeatureColour(minColour.getBackground(),
-             maxColour.getBackground(), noColour, minValue, maxValue);
+     FeatureColourI fc = new FeatureColour(singleColour.getBackground(),
+             minColour.getBackground(), maxColour.getBackground(), noColour,
+             minValue, maxValue);
  
      /*
+      * easiest case - a single colour
+      */
+     if (simpleColour.isSelected())
+     {
+       ((FeatureColour) fc).setGraduatedColour(false);
+       return fc;
+     }
+     /*
+      * next easiest case - colour by Label, or attribute text
+      */
+     if (byCategory.isSelected())
+     {
+       fc.setColourByLabel(true);
+       String byWhat = (String) colourByTextCombo.getSelectedItem();
+       if (!LABEL_18N.equals(byWhat))
+       {
+         fc.setAttributeName(
+                 FeatureMatcher.fromAttributeDisplayName(byWhat));
+       }
+       return fc;
+     }
+     /*
+      * remaining case - graduated colour by score, or attribute value;
       * set attribute to colour by if selected
       */
      String byWhat = (String) colourByRangeCombo.getSelectedItem();
    @Override
    protected void raiseClosed()
    {
 +    refreshFeatureSettings();
 +  }
 +
 +  protected void refreshFeatureSettings()
 +  {
      if (this.featureSettings != null)
      {
 -      featureSettings.actionPerformed(new ActionEvent(this, 0, "CLOSED"));
 +      featureSettings.actionPerformed(new ActionEvent(this, 0, "REFRESH"));
      }
    }
  
  
    /**
     * Action on Cancel is to restore colour scheme and filters as they were when
 -   * the dialog was opened
 +   * the dialog was opened (including any feature sub-types that may have been
 +   * changed)
     */
    @Override
    public void cancelPressed()
    {
 -    fr.setColour(featureType, originalColour);
 -    fr.setFeatureFilter(featureType, originalFilter);
 +    restoreOriginalColours();
 +    restoreOriginalFilters();
      ap.paintAlignment(true, true);
    }
  
 +  protected void restoreOriginalFilters()
 +  {
 +    for (Entry<String, FeatureMatcherSetI> entry : originalFilters
 +            .entrySet())
 +    {
 +      fr.setFeatureFilter(entry.getKey(), entry.getValue());
 +    }
 +  }
 +
 +  protected void restoreOriginalColours()
 +  {
 +    for (Entry<String, FeatureColourI> entry : originalColours.entrySet())
 +    {
 +      fr.setColour(entry.getKey(), entry.getValue());
 +    }
 +  }
 +
    /**
     * Action on text entry of a threshold value
     */
    {
      try
      {
+       /*
+        * set 'adjusting' flag while moving the slider, so it 
+        * doesn't then in turn change the value (with rounding)
+        */
        adjusting = true;
        float f = Float.parseFloat(thresholdValue.getText());
+       f = Float.max(f,  this.min);
+       f = Float.min(f, this.max);
+       thresholdValue.setText(String.valueOf(f));
        slider.setValue((int) (f * scaleFactor));
        threshline.value = f;
        thresholdValue.setBackground(Color.white); // ok
-       /*
-        * force repaint of any Overview window or structure
-        */
-       ap.paintAlignment(true, true);
+       adjusting = false;
+       colourChanged(true);
      } catch (NumberFormatException ex)
      {
        thresholdValue.setBackground(Color.red); // not ok
-     } finally
-     {
        adjusting = false;
      }
    }
    {
      filters = new ArrayList<>();
  
 +    JPanel outerPanel = new JPanel();
 +    outerPanel.setLayout(new BoxLayout(outerPanel, BoxLayout.Y_AXIS));
 +    outerPanel.setBackground(Color.white);
 +
 +    /*
 +     * option to apply colour to sub-types as well (if there are any)
 +     */
 +    if (!subTypes.isEmpty())
 +    {
 +      applyFiltersToSubtypes = false;
 +      outerPanel.add(initSubtypesPanel(true));
 +    }
 +
      JPanel filtersPanel = new JPanel();
      filtersPanel.setLayout(new BoxLayout(filtersPanel, BoxLayout.Y_AXIS));
      filtersPanel.setBackground(Color.white);
      JvSwingUtils.createTitledBorder(filtersPanel,
              MessageManager.getString("label.filters"), true);
 +    outerPanel.add(filtersPanel);
  
      JPanel andOrPanel = initialiseAndOrPanel();
      filtersPanel.add(andOrPanel);
      chooseFiltersPanel.setBackground(Color.white);
      filtersPanel.add(chooseFiltersPanel);
  
 -    return filtersPanel;
 +    return outerPanel;
    }
  
    /**
     */
    private JPanel initialiseAndOrPanel()
    {
 -    JPanel andOrPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
 +    JPanel andOrPanel = new JPanel(new BorderLayout());
      andOrPanel.setBackground(Color.white);
 +
 +//    JPanel panel1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
 +//    andOrPanel.add(panel1, BorderLayout.WEST);
 +//    panel1.setBackground(Color.white);
 +//    panel1.setBorder(BorderFactory.createLineBorder(debugBorderColour));
      andFilters = new JRadioButton(MessageManager.getString("label.and"));
      orFilters = new JRadioButton(MessageManager.getString("label.or"));
      ActionListener actionListener = new ActionListener()
              new JLabel(MessageManager.getString("label.join_conditions")));
      andOrPanel.add(andFilters);
      andOrPanel.add(orFilters);
 +
      return andOrPanel;
    }
  
    /**
 +   * Builds a tooltip for the 'Apply to subtypes' checkbox with a list of
 +   * subtypes of this feature type
 +   * 
 +   * @return
 +   */
 +  protected String getSubtypesTooltip()
 +  {
 +    StringBuilder sb = new StringBuilder(20 * subTypes.size());
 +    sb.append(MessageManager.getString("label.apply_also_to"));
 +    for (String child : subTypes)
 +    {
 +      sb.append("<br>").append(child);
 +    }
 +    String tooltip = JvSwingUtils.wrapTooltip(true, sb.toString());
 +    return tooltip;
 +  }
 +
 +  /**
     * Refreshes the display to show any filters currently configured for the
     * selected feature type (editable, with 'remove' option), plus one extra row
     * for adding a condition. This should be called after a filter has been
       * (note this might now be an empty filter with no conditions)
       */
      fr.setFeatureFilter(featureType, combined.isEmpty() ? null : combined);
 +    if (applyFiltersToSubtypes)
 +    {
 +      for (String child : subTypes)
 +      {
 +        fr.setFeatureFilter(child, combined.isEmpty() ? null : combined);
 +      }
 +    }
 +
 +    refreshFeatureSettings();
      ap.paintAlignment(true, true);
  
      updateFiltersTab();
@@@ -1029,7 -1029,7 +1029,7 @@@ public class SequenceFetcher extends JP
          }
          if (Cache.getDefault("HIDE_INTRONS", true))
          {
 -          af.hideFeatureColumns(SequenceOntologyI.EXON, false);
 +          af.hideFeatureColumns(false, SequenceOntologyI.EXON);
          }
          if (newAlframes != null)
          {
          Desktop.addInternalFrame(af, title, AlignFrame.DEFAULT_WIDTH,
                  AlignFrame.DEFAULT_HEIGHT);
  
-         af.statusBar.setText(MessageManager
+         af.setStatus(MessageManager
                  .getString("label.successfully_pasted_alignment_file"));
  
          try
@@@ -26,6 -26,7 +26,7 @@@ import static org.testng.AssertJUnit.as
  import jalview.analysis.Finder;
  import jalview.api.AlignViewControllerI;
  import jalview.api.FeatureColourI;
+ import jalview.api.FinderI;
  import jalview.datamodel.Alignment;
  import jalview.datamodel.SearchResults;
  import jalview.datamodel.SearchResultsI;
@@@ -60,24 -61,25 +61,24 @@@ public class AlignViewControllerTes
    public void testFindColumnsWithFeature()
    {
      SequenceI seq1 = new Sequence("seq1", "-a-MMMaaaaaaaaaaaaaaaa");
 -    SequenceI seq2 = new Sequence("seq2", "aa--aMM-MMMMMaaaaaaaaaa");
 +    SequenceI seq2 = new Sequence("seq2/11-30", "aa--aMM-MMMMMaaaaaaaaaa");
      SequenceI seq3 = new Sequence("seq3", "abcab-caD-aaMMMMMaaaaa");
      SequenceI seq4 = new Sequence("seq4", "abc--abcaaaaaaaaaaaaaa");
  
      /*
 -     * features start/end are base 1
 +     * features
       */
 -    seq1.addSequenceFeature(new SequenceFeature("Metal", "desc", 2, 4, 0f,
 -            null));
 -    seq1.addSequenceFeature(new SequenceFeature("Helix", "desc", 1, 15, 0f,
 -            null));
 -    seq2.addSequenceFeature(new SequenceFeature("Metal", "desc", 4, 10,
 -            10f,
 -            null));
 -    seq3.addSequenceFeature(new SequenceFeature("Metal", "desc", 11, 15,
 -            10f, null));
 +    seq1.addSequenceFeature(
 +            new SequenceFeature("Metal", "desc", 2, 4, 0f, null));
 +    seq1.addSequenceFeature(
 +            new SequenceFeature("Helix", "desc", 1, 15, 0f, null));
 +    seq2.addSequenceFeature(
 +            new SequenceFeature("Metal", "desc", 14, 20, 10f, null));
 +    seq3.addSequenceFeature(
 +            new SequenceFeature("Metal", "desc", 11, 15, 10f, null));
      // disulfide bond is a 'contact feature' - only select its 'start' and 'end'
 -    seq3.addSequenceFeature(new SequenceFeature("disulfide bond", "desc",
 -            8, 12, 0f, null));
 +    seq3.addSequenceFeature(
 +            new SequenceFeature("disulfide bond", "desc", 8, 12, 0f, null));
  
      /*
       * select the first five columns --> Metal in seq1 cols 4-5
      /*
       * set features visible on a viewport as only visible features are selected
       */
 -    AlignFrame af = new AlignFrame(new Alignment(new SequenceI[] { seq1,
 -        seq2, seq3, seq4 }), 100, 100);
 +    Alignment al = new Alignment(
 +            new SequenceI[]
 +            { seq1, seq2, seq3, seq4 });
 +    AlignFrame af = new AlignFrame(al, 100, 100);
      af.getFeatureRenderer().findAllFeatures(true);
  
      AlignViewController avc = new AlignViewController(af, af.getViewport(),
              af.alignPanel);
  
      BitSet bs = new BitSet();
 -    int seqCount = avc.findColumnsWithFeature("Metal", sg, bs);
 +    int seqCount = avc.findColumnsWithFeature(sg, bs, "Metal");
      assertEquals(1, seqCount);
      assertEquals(2, bs.cardinality());
      assertTrue(bs.get(3)); // base 0
       */
      sg.setEndRes(6);
      bs.clear();
 -    seqCount = avc.findColumnsWithFeature("Metal", sg, bs);
 +    seqCount = avc.findColumnsWithFeature(sg, bs, "Metal");
      assertEquals(2, seqCount);
      assertEquals(4, bs.cardinality());
      assertTrue(bs.get(3));
      sg.setStartRes(13);
      sg.setEndRes(13);
      bs.clear();
 -    seqCount = avc.findColumnsWithFeature("Metal", sg, bs);
 +    seqCount = avc.findColumnsWithFeature(sg, bs, "Metal");
      assertEquals(1, seqCount);
      assertEquals(1, bs.cardinality());
      assertTrue(bs.get(13));
      sg.setStartRes(17);
      sg.setEndRes(19);
      bs.clear();
 -    seqCount = avc.findColumnsWithFeature("Metal", sg, bs);
 +    seqCount = avc.findColumnsWithFeature(sg, bs, "Metal");
      assertEquals(0, seqCount);
      assertEquals(0, bs.cardinality());
  
       * seq1 feature in columns 4-6 is hidden
       * seq2 feature in columns 6-7 is shown
       */
-     FeatureColourI fc = new FeatureColour(Color.red, Color.blue, 0f, 10f);
+     FeatureColourI fc = new FeatureColour(null, Color.red, Color.blue, null,
+             0f, 10f);
      fc.setAboveThreshold(true);
      fc.setThreshold(5f);
      af.getFeatureRenderer().setColour("Metal", fc);
      sg.setStartRes(0);
      sg.setEndRes(6);
      bs.clear();
 -    seqCount = avc.findColumnsWithFeature("Metal", sg, bs);
 +    seqCount = avc.findColumnsWithFeature(sg, bs, "Metal");
      assertEquals(1, seqCount);
      assertEquals(2, bs.cardinality());
      assertTrue(bs.get(5));
      sg.setStartRes(10);
      sg.setEndRes(12);
      bs.clear();
 -    seqCount = avc.findColumnsWithFeature("disulfide bond", sg, bs);
 +    seqCount = avc.findColumnsWithFeature(sg, bs, "disulfide bond");
      assertEquals(0, seqCount);
      assertEquals(0, bs.cardinality());
  
      sg.setStartRes(5);
      sg.setEndRes(17);
      bs.clear();
 -    seqCount = avc.findColumnsWithFeature("disulfide bond", sg, bs);
 +    seqCount = avc.findColumnsWithFeature(sg, bs, "disulfide bond");
      assertEquals(1, seqCount);
      assertEquals(2, bs.cardinality());
      assertTrue(bs.get(8));
      assertTrue(bs.get(13));
  
      /*
 +     * look for multiple features; should match 
 +     * transcript_variant in seq3 positions 3-6, columns 3-7
 +     * sequence_variant in seq2 positions 15-18, columns 7-11
 +     * transcript_variant in seq3 positions 8 and 12, columns 9 and 14 
 +     */
 +    seq3.addSequenceFeature(new SequenceFeature("transcript_variant",
 +            "desc", 3, 6, 0f, null));
 +    seq2.addSequenceFeature(new SequenceFeature("sequence_variant", "desc",
 +            15, 18, 0f, null));
 +    sg.setStartRes(0);
 +    sg.setEndRes(20);
 +    bs.clear();
 +    seqCount = avc.findColumnsWithFeature(sg, bs, "transcript_variant",
 +            "sequence_variant", "disulfide bond", "junk");
 +    assertEquals(2, seqCount);
 +    assertEquals(10, bs.cardinality()); // 2-10 and 13, base 0
 +    for (int i = 2; i <= 10; i++)
 +    {
 +      assertTrue(bs.get(i));
 +    }
 +    assertTrue(bs.get(13));
 +
 +    /*
       * look for a feature that isn't there
       */
      sg.setStartRes(0);
      sg.setEndRes(19);
      bs.clear();
 -    seqCount = avc.findColumnsWithFeature("Pfam", sg, bs);
 +    seqCount = avc.findColumnsWithFeature(sg, bs, "Pfam");
      assertEquals(0, seqCount);
      assertEquals(0, bs.cardinality());
    }
      /*
       *  test Match/Find works first
       */
-     Finder f = new Finder(af.getViewport().getAlignment(), null);
-     f.setFindAll(true);
-     f.setCaseSensitive(true);
-     f.find("M+");
+     FinderI f = new Finder(af.getViewport());
+     f.findAll("M+", true, false);
      assertEquals(
              "Finder found different set of results to manually created SearchResults",
              sr, f.getSearchResults());
@@@ -20,6 -20,7 +20,7 @@@
   */
  package jalview.gui;
  
+ import static org.junit.Assert.assertNotEquals;
  import static org.testng.Assert.assertEquals;
  import static org.testng.Assert.assertFalse;
  import static org.testng.Assert.assertNotSame;
@@@ -38,7 -39,7 +39,7 @@@ import jalview.datamodel.SequenceGroup
  import jalview.datamodel.SequenceI;
  import jalview.io.DataSourceType;
  import jalview.io.FileLoader;
- import jalview.io.Jalview2xmlTests;
+ import jalview.project.Jalview2xmlTests;
  import jalview.renderer.ResidueShaderI;
  import jalview.schemes.BuriedColourScheme;
  import jalview.schemes.FeatureColour;
@@@ -70,18 -71,15 +71,18 @@@ public class AlignFrameTes
    @Test(groups = "Functional")
    public void testHideFeatureColumns()
    {
 -    SequenceI seq1 = new Sequence("Seq1", "ABCDEFGHIJ");
 -    SequenceI seq2 = new Sequence("Seq2", "ABCDEFGHIJ");
 -    seq1.addSequenceFeature(new SequenceFeature("Metal", "", 1, 5, 0f, null));
 -    seq2.addSequenceFeature(new SequenceFeature("Metal", "", 6, 10, 10f,
 -            null));
 -    seq1.addSequenceFeature(new SequenceFeature("Turn", "", 2, 4,
 -            Float.NaN, null));
 -    seq2.addSequenceFeature(new SequenceFeature("Turn", "", 7, 9,
 -            Float.NaN, null));
 +    SequenceI seq1 = new Sequence("Seq1/01-10", "A---BCDEFG-HIJ");
 +    SequenceI seq2 = new Sequence("Seq2/11-20", "-AB-CDEF--GHIJ");
 +    String METAL = "Metal";
 +    String TURN = "Turn";
 +    seq1.addSequenceFeature(
 +            new SequenceFeature(METAL, "", 1, 5, 0f, null));
 +    seq2.addSequenceFeature(
 +            new SequenceFeature(METAL, "", 16, 20, 10f, null));
 +    seq1.addSequenceFeature(
 +            new SequenceFeature(TURN, "", 2, 4, Float.NaN, null));
 +    seq2.addSequenceFeature(
 +            new SequenceFeature(TURN, "", 17, 19, Float.NaN, null));
      AlignmentI al = new Alignment(new SequenceI[] { seq1, seq2 });
      AlignFrame alignFrame = new AlignFrame(al, al.getWidth(),
              al.getHeight());
      /*
       * hiding a feature not present does nothing
       */
 -    assertFalse(alignFrame.hideFeatureColumns("exon", true));
 +    assertFalse(alignFrame.hideFeatureColumns(true, "exon"));
      assertTrue(alignFrame.getViewport().getColumnSelection().isEmpty());
      assertEquals(alignFrame.getViewport().getAlignment().getHiddenColumns()
              .getNumberOfRegions(), 0);
  
 -    assertFalse(alignFrame.hideFeatureColumns("exon", false));
 +    assertFalse(alignFrame.hideFeatureColumns(false, "exon"));
      assertTrue(alignFrame.getViewport().getColumnSelection().isEmpty());
 -
      assertEquals(alignFrame.getViewport().getAlignment().getHiddenColumns()
              .getNumberOfRegions(), 0);
  
      /*
       * hiding a feature in all columns does nothing
       */
 -    assertFalse(alignFrame.hideFeatureColumns("Metal", true));
 +    assertFalse(alignFrame.hideFeatureColumns(true, METAL));
      assertTrue(alignFrame.getViewport().getColumnSelection().isEmpty());
 -
      assertEquals(alignFrame.getViewport().getAlignment().getHiddenColumns()
              .getNumberOfRegions(), 0);
  
  
      /*
       * threshold Metal to hide features where score < 5
 -     * seq1 feature in columns 1-5 is hidden
 -     * seq2 feature in columns 6-10 is shown
 +     * seq1 feature in columns 1-8 is hidden
 +     * seq2 feature in columns 8-14 is shown
 +     * result: columns 8-14 are hidden
 +     * note this includes gapped columns spanned by the feature
       */
-     FeatureColourI fc = new FeatureColour(Color.red, Color.blue, 0f, 10f);
+     FeatureColourI fc = new FeatureColour(null, Color.red, Color.blue, null,
+             0f, 10f);
      fc.setAboveThreshold(true);
      fc.setThreshold(5f);
 -    alignFrame.getFeatureRenderer().setColour("Metal", fc);
 -    assertTrue(alignFrame.hideFeatureColumns("Metal", true));
 +    alignFrame.getFeatureRenderer().setColour(METAL, fc);
 +    assertTrue(alignFrame.hideFeatureColumns(true, METAL));
      HiddenColumns hidden = alignFrame.getViewport().getAlignment().getHiddenColumns();
      assertEquals(hidden.getNumberOfRegions(), 1);
      Iterator<int[]> regions = hidden.iterator();
 -    int[] next = regions.next();
 -    assertEquals(next[0], 5);
 -    assertEquals(next[1], 9);
 +    assertEquals(regions.next(), new int[] { 7, 13 }); // base 0
 +    assertFalse(regions.hasNext());
  
      /*
       * hide a feature present in some columns
 -     * sequence positions [2-4], [7-9] are column positions
 -     * [1-3], [6-8] base zero
 +     * seq1 positions [2-4] are column positions [4-6] base zero
 +     * seq2 positions [17-19] are column positions [10-12] base zero
       */
      alignFrame.getViewport().showAllHiddenColumns();
 -    assertTrue(alignFrame.hideFeatureColumns("Turn", true));
 +    assertTrue(alignFrame.hideFeatureColumns(true, TURN));
      regions = alignFrame.getViewport().getAlignment()
              .getHiddenColumns().iterator();
      assertEquals(alignFrame.getViewport().getAlignment().getHiddenColumns()
              .getNumberOfRegions(), 2);
 -    next = regions.next();
 -    assertEquals(next[0], 1);
 -    assertEquals(next[1], 3);
 -    next = regions.next();
 -    assertEquals(next[0], 6);
 -    assertEquals(next[1], 8);
 +    assertEquals(regions.next(), new int[] { 4, 6 });
 +    assertEquals(regions.next(), new int[] { 10, 12 });
 +    assertFalse(regions.hasNext());
 +    
 +    /*
 +     * hiding a contact feature should only hide start and end positions,
 +     * not the intermediate columns
 +     */
 +    String DISULFIDE = "Disulfide Bond";
 +    seq1.addSequenceFeature(
 +            new SequenceFeature(DISULFIDE, "", 1, 5, 0f, null));
 +    alignFrame.getViewport().showAllHiddenColumns();
 +    assertTrue(alignFrame.hideFeatureColumns(true, DISULFIDE));
 +    regions = alignFrame.getViewport().getAlignment().getHiddenColumns()
 +            .iterator();
 +    assertEquals(alignFrame.getViewport().getAlignment().getHiddenColumns()
 +            .getNumberOfRegions(), 2);
 +    assertEquals(regions.next(), new int[] { 0, 0 });
 +    assertEquals(regions.next(), new int[] { 7, 7 });
 +    assertFalse(regions.hasNext());
 +
 +    /*
 +     * hide multiple feature types:
 +     * TURN columns hides 4-6, 10-12
 +     * DISULFIDE columns hides 0, 7
 +     * combined is { 0-0, 4-7, 10-12 }
 +     */
 +    alignFrame.getViewport().showAllHiddenColumns();
 +    assertTrue(alignFrame.hideFeatureColumns(true, TURN, DISULFIDE));
 +    regions = alignFrame.getViewport().getAlignment().getHiddenColumns()
 +            .iterator();
 +    assertEquals(alignFrame.getViewport().getAlignment().getHiddenColumns()
 +            .getNumberOfRegions(), 3);
 +    assertEquals(regions.next(), new int[] { 0, 0 });
 +    assertEquals(regions.next(), new int[] { 4, 7 });
 +    assertEquals(regions.next(), new int[] { 10, 12 });
 +    assertFalse(regions.hasNext());
    }
  
    @BeforeClass(alwaysRun = true)
      /*
       * use read-only test properties file
       */
 -    Cache.loadProperties("test/jalview/io/testProps.jvprops");
 -    Jalview.main(new String[] { "-nonews" });
 +    Jalview.main(
 +            new String[]
 +            { "-nonews", "-props", "test/jalview/io/testProps.jvprops" });
    }
  
    @AfterMethod(alwaysRun = true)
      sp.valueChanged(22);
      assertEquals(av2.getResidueShading().getConservationInc(), 22);
    }
+   /**
+    * Verify that making a New View preserves the dataset reference for the
+    * alignment. Otherwise, see a 'duplicate jar entry' reference when trying to
+    * save alignments with multiple views, and codon mappings will not be shared
+    * across all panels in a split frame.
+    * 
+    * @see Jalview2xmlTests#testStoreAndRecoverColourThresholds()
+    */
+   @Test(groups = "Functional")
+   public void testNewView_dsRefPreserved()
+   {
+     AlignViewport av = af.getViewport();
+     AlignmentI al = av.getAlignment();
+     AlignmentI original_ds = al.getDataset();
+     af.newView_actionPerformed(null);
+     assertNotEquals("New view didn't select the a new panel", av,
+             af.getViewport());
+     org.testng.Assert.assertEquals(original_ds,
+             af.getViewport().getAlignment().getDataset(),
+             "Dataset was not preserved in new view");
+   }
  }