From: gmungoc Date: Tue, 19 May 2020 16:27:32 +0000 (+0100) Subject: Merge branch 'develop' into feature/JAL-3551Pymol X-Git-Tag: Release_2_11_2_0~37^2~13 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=4f30214e8098748469c6a4269ac2ed6c5750e4b0;hp=-c;p=jalview.git Merge branch 'develop' into feature/JAL-3551Pymol Conflicts: src/jalview/ext/jmol/JalviewJmolBinding.java src/jalview/ext/jmol/JmolCommands.java src/jalview/gui/AppJmol.java src/jalview/gui/AppJmolBinding.java src/jalview/gui/ChimeraViewFrame.java src/jalview/gui/StructureViewerBase.java src/jalview/jbgui/GPreferences.java src/jalview/jbgui/GStructureViewer.java src/jalview/project/Jalview2XML.java --- 4f30214e8098748469c6a4269ac2ed6c5750e4b0 diff --combined resources/lang/Messages.properties index 8747588,1762a06..3ba0649 --- a/resources/lang/Messages.properties +++ b/resources/lang/Messages.properties @@@ -268,11 -268,11 +268,11 @@@ label.autoadd_secstr = Add secondary st label.autoadd_temp = Add Temperature Factor annotation to alignment label.structure_viewer = Default structure viewer label.double_click_to_browse = Double-click to browse for file -label.chimera_path = Path to Chimera program -label.chimera_path_tip = Jalview will first try any path entered here, else standard installation locations.
Double-click to browse for file. -label.invalid_chimera_path = Chimera path not found or not executable -label.chimera_missing = Chimera structure viewer not found.
Please enter the path to Chimera (if installed),
or download and install UCSF Chimera. -label.chimera_failed = Error opening Chimera - is it installed?\nCheck path in Preferences, Structure +label.viewer_path = Path to {0} program +label.viewer_path_tip = Jalview will first try any path entered here, else standard installation locations.
Double-click to browse for file. +label.invalid_viewer_path = Path not found or not executable +label.viewer_missing = Structure viewer not found.
Please enter the path to the executable (if installed),
or download and install the program. +label.open_viewer_failed = Error opening {0} - is it installed?\nCheck path in Preferences, Structure label.min_colour = Minimum Colour label.max_colour = Maximum Colour label.no_colour = No Colour @@@ -363,7 -363,8 +363,8 @@@ label.open_saved_vamsas_session = Open label.groovy_console = Groovy Console... label.lineart = Lineart label.dont_ask_me_again = Don't ask me again - label.select_eps_character_rendering_style = Select EPS character rendering style + label.select_character_rendering_style = {0} character rendering style + label.select_character_style_title = {0} Rendering options label.invert_selection = Invert Selection label.optimise_order = Optimise Order label.seq_sort_by_score = Sequence sort by Score @@@ -412,7 -413,7 +413,7 @@@ label.input_alignment_from_url = Input 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 = Could not locate {0} + label.couldnt_locate = Couldn''t 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 @@@ -504,7 -505,7 +505,7 @@@ label.sequence_details = Sequence Detai label.jmol_help = Jmol Help label.chimera_help = Chimera Help label.close_viewer = Close Viewer -label.confirm_close_chimera = This will close Jalview''s connection to {0}.
Do you want to close the Chimera window as well? +label.confirm_close_viewer = This will close Jalview''s connection to {0}.
Do you want to close the {1} window as well? label.all = All label.sort_by = Sort alignment by label.sort_by_score = Sort by Score @@@ -598,7 -599,7 +599,7 @@@ label.check_for_questionnaires = Check label.check_for_latest_version = Check for latest version label.url_linkfrom_sequence_id = URL link from Sequence ID label.use_proxy_server = Use a proxy server - label.eps_rendering_style = EPS rendering style + label.rendering_style = {0} rendering style label.append_start_end = Append /start-end (/15-380) label.full_sequence_id = Full Sequence Id label.smooth_font = Smooth Font @@@ -623,6 -624,7 +624,6 @@@ label.editing = Editin 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 -label.let_chimera_manage_structure_colours = Let Chimera manage structure colours label.fetch_chimera_attributes = Fetch Chimera attributes label.fetch_chimera_attributes_tip = Copy Chimera attribute to Jalview feature label.marks_leaves_tree_not_associated_with_sequence = Marks leaves of tree not associated with a sequence @@@ -678,7 -680,7 +679,7 @@@ label.sequence_details_for = Sequence D label.sequence_name = Sequence Name label.sequence_description = Sequence Description label.edit_sequence_name_description = Edit Sequence Name/Description - label.spaces_converted_to_backslashes = Spaces have been converted to _ + label.spaces_converted_to_underscores = Spaces have been converted to _ label.no_spaces_allowed_sequence_name = No spaces allowed in Sequence Name label.select_outline_colour = Select Outline Colour label.web_browser_not_found_unix = Unixers\: Couldn't find default web browser.\nAdd the full path to your browser in Preferences." @@@ -709,8 -711,7 +710,8 @@@ label.associate_nodes_with = Associate label.link_name = Link Name label.pdb_file = PDB file label.colour_with_jmol = Colour with Jmol -label.colour_with_chimera = Colour with Chimera +label.let_viewer_manage_structure_colours = Let viewer manage structure colours +label.colour_with_viewer = Colour in structure viewer label.superpose_structures = Superpose Structures error.superposition_failed = Superposition failed: {0} label.insufficient_residues = Not enough aligned residues ({0}) to perform superposition @@@ -884,8 -885,6 +885,6 @@@ label.save_feature_colours = Save Featu label.select_startup_file = Select startup file label.select_default_browser = Select default web browser label.save_tree_as_newick = Save tree as newick file - label.create_eps_from_tree = Create EPS file from tree - label.create_png_from_tree = Create PNG image from tree label.save_colour_scheme = Save colour scheme label.edit_params_for = Edit parameters for {0} label.choose_filename_for_param_file = Choose a filename for this parameter file @@@ -941,8 -940,6 +940,6 @@@ error.call_setprogressbar_before_regist label.cancelled_params = Cancelled {0} error.implementation_error_cannot_show_view_alignment_frame = Implementation error: cannot show a view from another alignment in an AlignFrame. error.implementation_error_dont_know_about_threshold_setting = Implementation error: don't know about threshold setting for current AnnotationColourGradient. - error.eps_generation_not_implemented = EPS Generation not yet implemented - error.png_generation_not_implemented = PNG Generation not yet implemented error.try_join_vamsas_session_another = Trying to join a vamsas session when another is already connected error.invalid_vamsas_session_id = Invalid vamsas session id label.groovy_support_failed = Jalview Groovy Support Failed @@@ -1014,7 -1011,7 +1011,7 @@@ label.pca_recalculating = Recalculatin label.pca_calculating = Calculating PCA label.select_foreground_colour = Choose foreground colour label.select_colour_for_text = Select Colour for Text - label.adjunst_foreground_text_colour_threshold = Adjust Foreground Text Colour Threshold + label.adjust_foreground_text_colour_threshold = Adjust Foreground Text Colour Threshold label.select_subtree_colour = Select Sub-Tree Colour label.create_new_sequence_features = Create New Sequence Feature(s) label.amend_delete_features = Amend/Delete Features for {0} @@@ -1086,7 -1083,6 +1083,6 @@@ error.implementation_error_cannot_find_ exception.jobsubmission_invalid_params_set = Invalid parameter set. Check Jalview implementation exception.notvaliddata_group_contains_less_than_min_seqs = Group contains less than {0} sequences. exception.outofmemory_loading_pdb_file = Out of memory loading PDB File - exception.eps_coudnt_write_output_file = Could not write to the output file: {0} exception.eps_method_not_supported = Method not currently supported by EpsGraphics2D version {0} exception.eps_unable_to_get_inverse_matrix = Unable to get inverse of matrix: {0} warn.job_cannot_be_cancelled_close_window = This job cannot be cancelled.\nJust close the window. @@@ -1111,8 -1107,7 +1107,7 @@@ status.searching_for_sequences_from = S status.finished_searching_for_sequences_from = Finished searching for sequences from {0} label.eps_file = EPS file label.png_image = PNG image - status.saving_file = Saving {0} - status.export_complete = {0} Export completed. + status.export_complete = {0} Export completed status.fetching_pdb = Fetching PDB {0} status.refreshing_news = Refreshing news status.importing_vamsas_session_from = Importing VAMSAS session from {0} @@@ -1129,7 -1124,7 +1124,7 @@@ status.fetching_db_refs = Fetching db r status.loading_cached_pdb_entries = Loading Cached PDB Entries status.searching_for_pdb_structures = Searching for PDB Structures status.opening_file_for = opening file for -status.colouring_chimera = Colouring Chimera +status.colouring_structures = Colouring structures label.font_doesnt_have_letters_defined = Font doesn't have letters defined\nso cannot be used\nwith alignment data label.font_too_small = Font size is too small label.error_loading_file_params = Error loading file {0} @@@ -1236,7 -1231,6 +1231,6 @@@ exception.fts_server_unreachable = Jalv label.nw_mapping = Needleman & Wunsch Alignment label.sifts_mapping = SIFTs Mapping label.mapping_method = Sequence \u27f7 Structure mapping method - status.waiting_for_user_to_select_output_file = Waiting for user to select {0} file status.cancelled_image_export_operation = Cancelled {0} export operation info.error_creating_file = Error creating {0} file exception.outofmemory_loading_mmcif_file = Out of memory loading mmCIF File @@@ -1319,7 -1313,7 +1313,7 @@@ label.delete_condition = Delete this co label.score = Score label.colour_by_label = Colour by label label.variable_colour = Variable colour... - label.select_colour = Select colour + label.select_colour_for = Select colour for {0} option.enable_disable_autosearch = When ticked, search is performed automatically option.autosearch = Autosearch label.retrieve_ids = Retrieve IDs @@@ -1340,6 -1334,13 +1334,13 @@@ 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.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.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 diff --combined resources/lang/Messages_es.properties index 58f0223,d3c3355..1d9e5fd --- a/resources/lang/Messages_es.properties +++ b/resources/lang/Messages_es.properties @@@ -328,7 -328,8 +328,8 @@@ label.open_saved_vamsas_session = Abri label.groovy_console = Consola Groovy label.lineart = Lineart label.dont_ask_me_again = No volver a preguntar - label.select_eps_character_rendering_style = Seleccionar el carácter EPS como estilo de visualización + label.select_character_rendering_style = Estilo de visualización para carácter {0} + label.select_character_style_title = Opciones de visualización {0} label.invert_selection = Invertir selección label.optimise_order = Optimizar orden label.seq_sort_by_score = Ordenar las secuencias por puntuación @@@ -550,7 -551,7 +551,7 @@@ label.check_for_questionnaires = Compro label.check_for_latest_version = Comprobar la última versión label.url_linkfrom_sequence_id = URL del enlace del ID de la secuencia label.use_proxy_server = Utilizar un servidor proxy - label.eps_rendering_style = Estilo de visualización EPS + label.rendering_style = Estilo de visualización {0} label.append_start_end = Añadir /inicio-fin (/15-380) label.full_sequence_id = ID de la secuencia completo label.smooth_font = Fuente alargada @@@ -626,7 -627,7 +627,7 @@@ label.sequence_details_for = Detalles d label.sequence_name = Nombre de la secuencia label.sequence_description = Descripción de la secuencia label.edit_sequence_name_description = Editar el nombre/descripción de la secuencia - label.spaces_converted_to_backslashes = Los espacios se han convertido en _ + label.spaces_converted_to_underscores = Los espacios se han convertido en _ label.no_spaces_allowed_sequence_name = No se permiten espacios en el nombre de la secuencia label.select_outline_colour = Seleccionar el color del límite label.web_browser_not_found_unix = Unixers\: No es posible encontrar el navegador web por defecto.\nA\u00F1ada la ruta completa de su navegador en la pesta\u00F1a de Preferencias. @@@ -803,8 -804,6 +804,6 @@@ label.save_feature_colours = Guardar es label.select_startup_file = Seleccionar fichero de arranque label.select_default_browser = Seleccionar navegador web por defecto label.save_tree_as_newick = Guardar árbol como fichero newick - label.create_eps_from_tree = Crear un fichero EPS a partir de un árbol - label.create_png_from_tree = Crear una imagen PNG a partir de un árbol label.save_colour_scheme = Guardar esquema cromático label.edit_params_for = Editar los parámetros de {0} label.choose_filename_for_param_file = Escoja un nombre de fichero para este fichero de parámetros @@@ -860,8 -859,6 +859,6 @@@ error.call_setprogressbar_before_regist label.cancelled_params = {0} cancelado error.implementation_error_cannot_show_view_alignment_frame = Error de implementación: no es posible mostrar una vista de otro alineamiento en un AlignFrame. error.implementation_error_dont_know_about_threshold_setting = Error de implementación: no se conoce la configuración del umbral para el AnnotationColourGradient actual. - error.eps_generation_not_implemented = La generación de EPS no se ha implementado todavía - error.png_generation_not_implemented = La generación de PNG no se ha implementado todavía error.try_join_vamsas_session_another = Tratando de establecer una sesión VAMSAS cuando ya había otra conectada error.invalid_vamsas_session_id = Identificador de sesión VAMSAS no válido label.groovy_support_failed = El soporte Groovy de Jalview ha fallado @@@ -933,7 -930,7 +930,7 @@@ label.pca_recalculating = Recalculando label.pca_calculating = Calculando ACP label.select_foreground_colour = Escoger color del primer plano label.select_colour_for_text = Seleccione el color del texto - label.adjunst_foreground_text_colour_threshold = Ajustar el umbral del color del texto en primer plano + label.adjust_foreground_text_colour_threshold = Ajustar el umbral del color del texto en primer plano label.select_subtree_colour = Seleccioanr el color del sub-árbol label.create_new_sequence_features = Crear nueva(s) característica(s) de secuencia label.amend_delete_features = Arrelgar/Borrar características de {0} @@@ -1005,7 -1002,6 +1002,6 @@@ error.implementation_error_cannot_find_ exception.jobsubmission_invalid_params_set = Conjunto de parámetros no válido. Comprueba la implementación de Jalview exception.notvaliddata_group_contains_less_than_min_seqs = El grupo contiene menos de {0} secuencias. exception.outofmemory_loading_pdb_file = Sin memoria al cargar el fichero PDB - exception.eps_coudnt_write_output_file = No es posible escribir el fichero de salida: {0} exception.eps_method_not_supported = Método actualmente no suportado por la versión {0} de EpsGraphics2D exception.eps_unable_to_get_inverse_matrix = Imposible obtener la inversa de la matrix: {0} warn.job_cannot_be_cancelled_close_window = Este trabajo no se puede cancelar.\nSimplemente, cierre la ventana. @@@ -1027,8 -1023,7 +1023,7 @@@ status.searching_for_sequences_from = B status.finished_searching_for_sequences_from = Finalizada la búsqueda de secuencias en {0} label.eps_file = Fichero EPS label.png_image = Imagen PNG - status.saving_file = Guardando {0} - status.export_complete = Exportación completada. + status.export_complete = Exportación completada status.fetching_pdb = Recuperando PDB {0} status.refreshing_news = Refrescando noticias status.importing_vamsas_session_from = Importando sesión VAMSAS de {0} @@@ -1145,7 -1140,7 +1140,7 @@@ label.invalid_search=Texto de búsqueda action.export_annotations=Exportar Anotaciones action.set_as_reference=Marcar como Referencia action.unmark_as_reference=Desmarcar como Referencia -label.chimera_failed=Error al abrir Chimera - está instalado?\nCompruebe ruta en Preferencias, Estructura +label.open_viewer_failed=Error al abrir {0} - está instalado?\nCompruebe ruta en Preferencias, Estructura label.find=Buscar label.select_pdb_file=Seleccionar Fichero PDB label.structures_filter=Filtro de Estructuras @@@ -1158,6 -1153,7 +1153,6 @@@ action.export_features=Exportar Caracte error.invalid_regex=Expresión regular inválida label.autoadd_temp=Añadir anotación factor de temperatura al alineamiento label.double_click_to_browse = Haga doble clic para buscar fichero -label.chimera_path_tip=Jalview intentará primero las rutas introducidas aquí, Y si no las rutas usuales de instalación label.structure_chooser=Selector de Estructuras label.structure_chooser_manual_association=Selector de Estructuras - asociación manual label.threshold_filter=Filtro de Umbral @@@ -1165,11 -1161,11 +1160,11 @@@ label.add_reference_annotations=Añadir label.hide_insertions=Ocultar Inserciones info.change_threshold_mode_to_enable=Cambiar Modo de Umbral para Habilitar label.separate_multiple_query_values=Introducir uno o mas {0}s separados por punto y coma ";" label.fetch_chimera_attributes = Buscar atributos desde Chimera label.fetch_chimera_attributes_tip = Copiar atributo de Chimera a característica de Jalview label.view_rna_structure=Estructura 2D VARNA -label.colour_with_chimera=Colorear con Chimera +label.colour_with_viewer = Colorear con visualizador de estructuras +label.let_viewer_manage_structure_colours = Deja que el visualizador maneje los colores de estructuras label.superpose_structures = Superponer estructuras error.superposition_failed = Superposición fallido: {0} label.insufficient_residues = Residuos alineados ({0}) insuficentes para superponer @@@ -1180,6 -1176,7 +1175,6 @@@ tooltip.aacon_settings=Cambiar ajustes label.mark_as_representative=Marcar como representativa label.include_description=Incluir Descripción label.for=para -label.invalid_chimera_path=Ruta de Chimera no encontrada o no ejecutable info.search_in_annotation_label=Buscar en etiqueta de {0} info.search_in_annotation_description=Buscar en descripción de {0} label.select_many_views=Seleccionar múltiples vistas @@@ -1192,19 -1189,16 +1187,19 @@@ label.protein=Proteín warn.oneseq_msainput_selection=La selección actual sólo contiene una única secuencia. ¿Quieres enviar todas las secuencias para la alineación en su lugar? label.use_rnaview=Usar RNAView para estructura secondaria label.search_all=Introducir uno o más valores de búsqueda separados por punto y coma ";" (Nota: buscará en toda la base de datos PDB) -label.confirm_close_chimera=Cerrará la conexión de Jalview a {0}.
¿Quieres cerrar la ventana Chimera también? +label.confirm_close_viewer=Cerrará la conexión de Jalview a {0}.
¿Quieres cerrar la ventana {1} también? tooltip.rnalifold_calculations=Se calcularán predicciones de estructura secondaria de RNA para el alineaminento, y se actualizarán si se efectuan cambios tooltip.rnalifold_settings=Modificar la configuración de la predicción RNAAlifold. Úselo para ocultar o mostrar resultados del cálculo de RNA, o cambiar parámetros de el plegado de RNA. label.show_selected_annotations=Mostrar anotaciones seleccionadas -status.colouring_chimera=Coloreando Chimera +status.colouring_structures=Coloreando estructuras label.configure_displayed_columns=Configurar Columnas Mostradas label.aacon_calculations=cálculos AACon label.pdb_web-service_error=Error de servicio web PDB exception.unable_to_detect_internet_connection=Jalview no puede detectar una conexión a Internet -label.chimera_path=Ruta de acceso a Chimera +label.viewer_path=Ruta de acceso a {0} +label.viewer_path_tip=Jalview intentará primero las rutas introducidas aquí, Y si no las rutas usuales de instalación +label.invalid_viewer_path=Ruta no encontrada o no ejecutable +label.viewer_missing=Visualizador de estructura no encontrado.
Por favor, introduzca la ruta de la ejecutable,
o descargar e instalar el programa. warn.delete_all=Borrar todas las secuencias cerrará la ventana del alineamiento.
Confirmar o Cancelar. label.select_all=Seleccionar Todos label.alpha_helix=Hélice Alfa @@@ -1220,6 -1214,7 +1215,6 @@@ label.aacon_settings=Cambiar Ajustes AA tooltip.aacon_calculations=Actualizar cálculos AACon automáticamente. info.select_filter_option=Escoger Opción de Filtro / Entrada Manual info.invalid_msa_input_mininfo=Necesita por lo menos dos secuencias con al menos 3 residuos cada una, sin regiones ocultas entre ellas. -label.chimera_missing=Visualizador de estructura Chimera no encontrado.
Por favor, introduzca la ruta de Chimera,
o descargar e instalar la UCSF Chimera. exception.fts_server_unreachable=Jalview no puede conectar con el servidor {0}. \nPor favor asegúrese de que está conectado a Internet y vuelva a intentarlo. exception.outofmemory_loading_mmcif_file=Sin memoria al cargar el fichero mmCIF label.hide_columns_not_containing=Ocultar las columnas que no contengan @@@ -1314,7 -1309,7 +1309,7 @@@ label.join_conditions = Combinar condic label.score = Puntuación label.colour_by_label = Colorear por texto label.variable_colour = Color variable... - label.select_colour = Seleccionar color + label.select_colour_for = Seleccionar color para {0} option.enable_disable_autosearch = Marcar para buscar automáticamente option.autosearch = Auto búsqueda label.retrieve_ids = Recuperar IDs @@@ -1335,6 -1330,13 +1330,13 @@@ 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.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.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 diff --combined src/jalview/appletgui/AlignFrame.java index f4abd3d,1a46585..0fd0945 --- a/src/jalview/appletgui/AlignFrame.java +++ b/src/jalview/appletgui/AlignFrame.java @@@ -418,7 -418,7 +418,7 @@@ public class AlignFrame extends Embmenu viewport.featureSettings.refreshTable(); } alignPanel.paintAlignment(true, true); - statusBar.setText(MessageManager + setStatus(MessageManager .getString("label.successfully_added_features_alignment")); } return featuresFile; @@@ -576,7 -576,7 +576,7 @@@ case KeyEvent.VK_F2: viewport.cursorMode = !viewport.cursorMode; - statusBar.setText(MessageManager + setStatus(MessageManager .formatMessage("label.keyboard_editing_mode", new String[] { (viewport.cursorMode ? "on" : "off") })); if (viewport.cursorMode) @@@ -2081,7 -2081,8 +2081,8 @@@ seqs, 0, viewport.getAlignment().getWidth(), viewport.getAlignment())); - viewport.getRanges().setEndSeq(viewport.getAlignment().getHeight()); + viewport.getRanges().setEndSeq(viewport.getAlignment().getHeight() - 1); // BH + // 2019.04.18 viewport.getAlignment().getWidth(); viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences()); @@@ -2357,7 -2358,7 +2358,7 @@@ column, al); } - statusBar.setText(MessageManager + setStatus(MessageManager .formatMessage("label.removed_columns", new String[] { Integer.valueOf(trimRegion.getSize()).toString() })); addHistoryItem(trimRegion); @@@ -2401,7 -2402,7 +2402,7 @@@ addHistoryItem(removeGapCols); - statusBar.setText(MessageManager + setStatus(MessageManager .formatMessage("label.removed_empty_columns", new String[] { Integer.valueOf(removeGapCols.getSize()).toString() })); @@@ -3823,7 -3824,7 +3824,7 @@@ */ statusBar.setBackground(Color.white); statusBar.setFont(new java.awt.Font("Verdana", 0, 11)); - statusBar.setText(MessageManager.getString("label.status_bar")); + setStatus(MessageManager.getString("label.status_bar")); this.add(statusBar, BorderLayout.SOUTH); } @@@ -3963,7 -3964,7 +3964,7 @@@ * without an additional javascript library to exchange messages between the * distinct applets. See http://issues.jalview.org/browse/JAL-621 * - * @param viewer + * @param jmolViewer * JmolViewer instance * @param sequenceIds * - sequence Ids to search for associations @@@ -4191,7 -4192,7 +4192,7 @@@ } else { - new MCview.AppletPDBViewer(pdb, seqs, chains, alignPanel, protocol); + new mc_view.AppletPDBViewer(pdb, seqs, chains, alignPanel, protocol); } } diff --combined src/jalview/appletgui/AppletJmol.java index 6e95633,7fda3c4..6665ec8 --- a/src/jalview/appletgui/AppletJmol.java +++ b/src/jalview/appletgui/AppletJmol.java @@@ -20,6 -20,25 +20,6 @@@ */ package jalview.appletgui; -import jalview.bin.JalviewLite; -import jalview.datamodel.AlignmentI; -import jalview.datamodel.PDBEntry; -import jalview.datamodel.SequenceI; -import jalview.io.DataSourceType; -import jalview.io.FileParse; -import jalview.io.StructureFile; -import jalview.schemes.BuriedColourScheme; -import jalview.schemes.HelixColourScheme; -import jalview.schemes.HydrophobicColourScheme; -import jalview.schemes.PurinePyrimidineColourScheme; -import jalview.schemes.StrandColourScheme; -import jalview.schemes.TaylorColourScheme; -import jalview.schemes.TurnColourScheme; -import jalview.schemes.UserColourScheme; -import jalview.schemes.ZappoColourScheme; -import jalview.structure.StructureSelectionManager; -import jalview.util.MessageManager; - import java.awt.BorderLayout; import java.awt.CheckboxMenuItem; import java.awt.Color; @@@ -45,25 -64,6 +45,25 @@@ import java.util.ArrayList import java.util.List; import java.util.Vector; +import jalview.bin.JalviewLite; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.PDBEntry; +import jalview.datamodel.SequenceI; +import jalview.io.DataSourceType; +import jalview.io.FileParse; +import jalview.io.StructureFile; +import jalview.schemes.BuriedColourScheme; +import jalview.schemes.HelixColourScheme; +import jalview.schemes.HydrophobicColourScheme; +import jalview.schemes.PurinePyrimidineColourScheme; +import jalview.schemes.StrandColourScheme; +import jalview.schemes.TaylorColourScheme; +import jalview.schemes.TurnColourScheme; +import jalview.schemes.UserColourScheme; +import jalview.schemes.ZappoColourScheme; +import jalview.structure.StructureSelectionManager; +import jalview.util.MessageManager; + public class AppletJmol extends EmbmenuFrame implements // StructureListener, KeyListener, ActionListener, ItemListener @@@ -307,7 -307,7 +307,7 @@@ else if (protocol == DataSourceType.FILE || protocol == DataSourceType.URL) { - jmb.viewer.openFile(pdbentry.getFile()); + jmb.jmolViewer.openFile(pdbentry.getFile()); } else { @@@ -335,7 -335,7 +335,7 @@@ } FileParse fp = new FileParse(pdbentry.getFile(), protocol); fp.mark(); - // reader = new MCview.PDBfile(fp); + // reader = new mc_view.PDBfile(fp); // could set ID, etc. // if (!reader.isValid()) // { @@@ -350,7 -350,7 +350,7 @@@ throw new Exception(MessageManager.getString( "exception.invalid_datasource_couldnt_obtain_reader")); } - jmb.viewer.openReader(pdbentry.getFile(), pdbentry.getId(), + jmb.jmolViewer.openReader(pdbentry.getFile(), pdbentry.getId(), freader); } catch (Exception e) { @@@ -406,12 -406,12 +406,12 @@@ } } } - jmb.centerViewer(toshow); + jmb.showChains(toshow); } void closeViewer() { - jmb.closeViewer(); + jmb.closeViewer(true); jmb = null; this.setVisible(false); } @@@ -455,41 -455,41 +455,41 @@@ else if (evt.getSource() == zappo) { setEnabled(zappo); - jmb.setJalviewColourScheme(new ZappoColourScheme()); + jmb.colourByJalviewColourScheme(new ZappoColourScheme()); } else if (evt.getSource() == taylor) { setEnabled(taylor); - jmb.setJalviewColourScheme(new TaylorColourScheme()); + jmb.colourByJalviewColourScheme(new TaylorColourScheme()); } else if (evt.getSource() == hydro) { setEnabled(hydro); - jmb.setJalviewColourScheme(new HydrophobicColourScheme()); + jmb.colourByJalviewColourScheme(new HydrophobicColourScheme()); } else if (evt.getSource() == helix) { setEnabled(helix); - jmb.setJalviewColourScheme(new HelixColourScheme()); + jmb.colourByJalviewColourScheme(new HelixColourScheme()); } else if (evt.getSource() == strand) { setEnabled(strand); - jmb.setJalviewColourScheme(new StrandColourScheme()); + jmb.colourByJalviewColourScheme(new StrandColourScheme()); } else if (evt.getSource() == turn) { setEnabled(turn); - jmb.setJalviewColourScheme(new TurnColourScheme()); + jmb.colourByJalviewColourScheme(new TurnColourScheme()); } else if (evt.getSource() == buried) { setEnabled(buried); - jmb.setJalviewColourScheme(new BuriedColourScheme()); + jmb.colourByJalviewColourScheme(new BuriedColourScheme()); } else if (evt.getSource() == purinepyrimidine) { - jmb.setJalviewColourScheme(new PurinePyrimidineColourScheme()); + jmb.colourByJalviewColourScheme(new PurinePyrimidineColourScheme()); } else if (evt.getSource() == user) { @@@ -658,7 -658,7 +658,7 @@@ { currentSize = this.getSize(); - if (jmb.viewer == null) + if (jmb.jmolViewer == null) { g.setColor(Color.black); g.fillRect(0, 0, currentSize.width, currentSize.height); @@@ -669,7 -669,7 +669,7 @@@ } else { - jmb.viewer.renderScreenImage(g, currentSize.width, + jmb.jmolViewer.renderScreenImage(g, currentSize.width, currentSize.height); } } @@@ -693,9 -693,9 +693,9 @@@ * * } */ - public void setJalviewColourScheme(UserColourScheme ucs) + public void colourByJalviewColourScheme(UserColourScheme ucs) { - jmb.setJalviewColourScheme(ucs); + jmb.colourByJalviewColourScheme(ucs); } public AlignmentPanel getAlignmentPanelFor(AlignmentI alignment) diff --combined src/jalview/appletgui/AppletJmolBinding.java index dd6dea3,f1c494e..c7ce994 --- a/src/jalview/appletgui/AppletJmolBinding.java +++ b/src/jalview/appletgui/AppletJmolBinding.java @@@ -32,7 -32,7 +32,7 @@@ import java.util.Map import org.jmol.api.JmolAppConsoleInterface; import org.jmol.console.AppletConsole; - import org.jmol.java.BS; + import javajs.util.BS; class AppletJmolBinding extends JalviewJmolBinding { @@@ -51,6 -51,13 +51,6 @@@ } @Override - public jalview.api.FeatureRenderer getFeatureRenderer( - AlignmentViewPanel alignment) - { - return appletJmolBinding.ap.getFeatureRenderer(); - } - - @Override public jalview.api.SequenceRenderer getSequenceRenderer( AlignmentViewPanel alignment) { @@@ -147,7 -154,7 +147,7 @@@ Container consolePanel, String buttonsToShow) { JmolAppConsoleInterface appc = new AppletConsole(); - appc.start(viewer); + appc.start(jmolViewer); return appc; } diff --combined src/jalview/appletgui/ExtJmol.java index 5c20136,5a6d0d0..47f9df0 --- a/src/jalview/appletgui/ExtJmol.java +++ b/src/jalview/appletgui/ExtJmol.java @@@ -21,6 -21,7 +21,6 @@@ package jalview.appletgui; import jalview.api.AlignmentViewPanel; -import jalview.api.FeatureRenderer; import jalview.api.SequenceRenderer; import jalview.datamodel.PDBEntry; import jalview.datamodel.SequenceI; @@@ -34,7 -35,7 +34,7 @@@ import java.util.Map import java.util.Vector; import org.jmol.api.JmolAppConsoleInterface; - import org.jmol.java.BS; + import javajs.util.BS; import org.jmol.viewer.Viewer; /** @@@ -75,6 -76,21 +75,6 @@@ public class ExtJmol extends JalviewJmo } @Override - public FeatureRenderer getFeatureRenderer(AlignmentViewPanel alignment) - { - AlignmentPanel alignPanel = (AlignmentPanel) alignment; - if (alignPanel.av.isShowSequenceFeatures()) - { - return alignPanel.getFeatureRenderer(); - } - else - { - return null; - } - } - - - @Override public SequenceRenderer getSequenceRenderer(AlignmentViewPanel alignment) { return ((AlignmentPanel) alignment).getSequenceRenderer(); @@@ -175,8 -191,14 +175,8 @@@ } @Override - public void releaseReferences(Object svl) - { - } - - @Override public Map getJSpecViewProperty(String arg0) { return null; } - } diff --combined src/jalview/appletgui/UserDefinedColours.java index bfce880,febe5f8..83d6fd6 --- a/src/jalview/appletgui/UserDefinedColours.java +++ b/src/jalview/appletgui/UserDefinedColours.java @@@ -70,7 -70,7 +70,7 @@@ public class UserDefinedColours extend Frame frame; - MCview.AppletPDBCanvas pdbcanvas; + mc_view.AppletPDBCanvas pdbcanvas; AppletJmol jmol; @@@ -107,7 -107,7 +107,7 @@@ init(); } - public UserDefinedColours(MCview.AppletPDBCanvas pdb) + public UserDefinedColours(mc_view.AppletPDBCanvas pdb) { this.pdbcanvas = pdb; init(); @@@ -524,7 -524,7 +524,7 @@@ } else if (jmol != null) { - jmol.setJalviewColourScheme(ucs); + jmol.colourByJalviewColourScheme(ucs); } else if (pdbcanvas != null) { diff --combined src/jalview/datamodel/features/SequenceFeatures.java index db2f0e1,70485b6..8ac4991 --- a/src/jalview/datamodel/features/SequenceFeatures.java +++ b/src/jalview/datamodel/features/SequenceFeatures.java @@@ -20,11 -20,8 +20,8 @@@ */ package jalview.datamodel.features; - import jalview.datamodel.SequenceFeature; - import jalview.io.gff.SequenceOntologyFactory; - import jalview.io.gff.SequenceOntologyI; - import java.util.ArrayList; + import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; @@@ -33,6 -30,9 +30,9 @@@ import java.util.Set import java.util.TreeMap; import intervalstore.api.IntervalI; + import jalview.datamodel.SequenceFeature; + import jalview.io.gff.SequenceOntologyFactory; + import jalview.io.gff.SequenceOntologyI; /** * A class that stores sequence features in a way that supports efficient @@@ -44,7 -44,6 +44,6 @@@ */ public class SequenceFeatures implements SequenceFeaturesI { - /* * map from feature type to structured store of features for that type * null types are permitted (but not a good idea!) @@@ -414,7 -413,9 +413,10 @@@ public static void sortFeatures(List features, final boolean forwardStrand) { - IntervalI.sortIntervals(features, forwardStrand); + Collections.sort(features, - forwardStrand ? IntervalI.COMPARE_BEGIN_ASC_END_ASC ++ forwardStrand ++ ? IntervalI.COMPARE_BEGIN_ASC_END_DESC + : IntervalI.COMPARE_END_DESC); } /** diff --combined src/jalview/ext/jmol/JalviewJmolBinding.java index c3a22fb,453152e..54eb599 --- a/src/jalview/ext/jmol/JalviewJmolBinding.java +++ b/src/jalview/ext/jmol/JalviewJmolBinding.java @@@ -20,12 -20,33 +20,12 @@@ */ package jalview.ext.jmol; -import jalview.api.AlignmentViewPanel; -import jalview.api.FeatureRenderer; -import jalview.api.SequenceRenderer; -import jalview.datamodel.AlignmentI; -import jalview.datamodel.HiddenColumns; -import jalview.datamodel.PDBEntry; -import jalview.datamodel.SequenceI; -import jalview.gui.IProgressIndicator; -import jalview.io.DataSourceType; -import jalview.io.StructureFile; -import jalview.schemes.ColourSchemeI; -import jalview.schemes.ResidueProperties; -import jalview.structure.AtomSpec; -import jalview.structure.StructureMappingcommandSet; -import jalview.structure.StructureSelectionManager; -import jalview.structures.models.AAStructureBindingModel; -import jalview.util.MessageManager; - -import java.awt.Color; import java.awt.Container; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.io.File; import java.net.URL; import java.util.ArrayList; -import java.util.BitSet; -import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.StringTokenizer; @@@ -37,49 -58,50 +37,50 @@@ import org.jmol.api.JmolSelectionListen import org.jmol.api.JmolStatusListener; import org.jmol.api.JmolViewer; import org.jmol.c.CBK; -import org.jmol.script.T; import org.jmol.viewer.Viewer; +import jalview.api.FeatureRenderer; ++import jalview.bin.Cache; +import jalview.datamodel.PDBEntry; +import jalview.datamodel.SequenceI; +import jalview.gui.IProgressIndicator; +import jalview.gui.StructureViewer.ViewerType; +import jalview.io.DataSourceType; +import jalview.io.StructureFile; +import jalview.structure.AtomSpec; +import jalview.structure.StructureCommand; +import jalview.structure.StructureCommandI; +import jalview.structure.StructureSelectionManager; +import jalview.structures.models.AAStructureBindingModel; + public abstract class JalviewJmolBinding extends AAStructureBindingModel implements JmolStatusListener, JmolSelectionListener, ComponentListener { private String lastMessage; - boolean allChainsSelected = false; - /* * when true, try to search the associated datamodel for sequences that are * associated with any unknown structures in the Jmol view. */ private boolean associateNewStructs = false; - Vector atomsPicked = new Vector<>(); - - private List chainNames; - - Hashtable chainFile; - - /* - * the default or current model displayed if the model cannot be identified - * from the selection message - */ - int frameNo = 0; + private Vector atomsPicked = new Vector<>(); - // protected JmolGenericPopup jmolpopup; // not used - remove? + private String lastCommand; - String lastCommand; + private boolean loadedInline; - boolean loadedInline; + private StringBuffer resetLastRes = new StringBuffer(); - StringBuffer resetLastRes = new StringBuffer(); - - public Viewer viewer; + public Viewer jmolViewer; public JalviewJmolBinding(StructureSelectionManager ssm, PDBEntry[] pdbentry, SequenceI[][] sequenceIs, DataSourceType protocol) { super(ssm, pdbentry, sequenceIs, protocol); + setStructureCommands(new JmolCommands()); /* * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(), * "jalviewJmol", ap.av.applet .getDocumentBase(), @@@ -94,10 -116,9 +95,10 @@@ { super(ssm, seqs); - viewer = theViewer; - viewer.setJmolStatusListener(this); - viewer.addSelectionListener(this); + jmolViewer = theViewer; + jmolViewer.setJmolStatusListener(this); + jmolViewer.addSelectionListener(this); + setStructureCommands(new JmolCommands()); } /** @@@ -111,23 -132,409 +112,32 @@@ return getViewerTitle("Jmol", true); } - /** - * prepare the view for a given set of models/chains. chainList contains - * strings of the form 'pdbfilename:Chaincode' - * - * @param chainList - * list of chains to make visible - */ - public void centerViewer(Vector chainList) - { - StringBuilder cmd = new StringBuilder(128); - int mlength, p; - for (String lbl : chainList) - { - mlength = 0; - do - { - p = mlength; - mlength = lbl.indexOf(":", p); - } while (p < mlength && mlength < (lbl.length() - 2)); - // TODO: lookup each pdb id and recover proper model number for it. - cmd.append(":" + lbl.substring(mlength + 1) + " /" - + (1 + getModelNum(chainFile.get(lbl))) + " or "); - } - if (cmd.length() > 0) - { - cmd.setLength(cmd.length() - 4); - } - evalStateCommand("select *;restrict " + cmd + ";cartoon;center " + cmd); - } - - public void closeViewer() - { - // remove listeners for all structures in viewer - getSsm().removeStructureViewerListener(this, this.getStructureFiles()); - if (viewer != null) - { - viewer.dispose(); - } - lastCommand = null; - viewer = null; - releaseUIResources(); - } - - @Override - public void colourByChain() - { - colourBySequence = false; - // TODO: colour by chain should colour each chain distinctly across all - // visible models - // TODO: http://issues.jalview.org/browse/JAL-628 - evalStateCommand("select *;color chain"); - } - - @Override - public void colourByCharge() - { - colourBySequence = false; - evalStateCommand("select *;color white;select ASP,GLU;color red;" - + "select LYS,ARG;color blue;select CYS;color yellow"); - } - - /** - * superpose the structures associated with sequences in the alignment - * according to their corresponding positions. - */ - public void superposeStructures(AlignmentI alignment) ++ private String jmolScript(String script) + { - superposeStructures(alignment, -1, null); - } ++ Cache.log.debug(">>Jmol>> " + script); ++ String s = jmolViewer.evalStringQuiet(script); ++ Cache.log.debug("< executeCommand(StructureCommandI command, + boolean getReply) { - while (viewer.isScriptExecuting()) - { - try - { - Thread.sleep(10); - } catch (InterruptedException i) - { - } - } - - /* - * get the distinct structure files modelled - * (a file with multiple chains may map to multiple sequences) - */ - String[] files = getStructureFiles(); - if (!waitForFileLoad(files)) + if (command == null) { return null; } - - StringBuilder selectioncom = new StringBuilder(256); - // In principle - nSeconds specifies the speed of animation for each - // superposition - but is seems to behave weirdly, so we don't specify it. - String nSeconds = " "; - if (files.length > 10) - { - nSeconds = " 0.005 "; - } - else - { - nSeconds = " " + (2.0 / files.length) + " "; - // if (nSeconds).substring(0,5)+" "; - } - - // see JAL-1345 - should really automatically turn off the animation for - // large numbers of structures, but Jmol doesn't seem to allow that. - // nSeconds = " "; - // union of all aligned positions are collected together. - for (int a = 0; a < _alignment.length; a++) - { - int refStructure = _refStructure[a]; - AlignmentI alignment = _alignment[a]; - HiddenColumns hiddenCols = _hiddenCols[a]; - if (a > 0 && selectioncom.length() > 0 && !selectioncom - .substring(selectioncom.length() - 1).equals("|")) - { - selectioncom.append("|"); - } - // process this alignment - if (refStructure >= files.length) - { - System.err.println( - "Invalid reference structure value " + refStructure); - refStructure = -1; - } - - /* - * 'matched' bit j will be set for visible alignment columns j where - * all sequences have a residue with a mapping to the PDB structure - */ - BitSet matched = new BitSet(); - for (int m = 0; m < alignment.getWidth(); m++) - { - if (hiddenCols == null || hiddenCols.isVisible(m)) - { - matched.set(m); - } - } - - SuperposeData[] structures = new SuperposeData[files.length]; - for (int f = 0; f < files.length; f++) - { - structures[f] = new SuperposeData(alignment.getWidth()); - } - - /* - * Calculate the superposable alignment columns ('matched'), and the - * corresponding structure residue positions (structures.pdbResNo) - */ - int candidateRefStructure = findSuperposableResidues(alignment, - matched, structures); - if (refStructure < 0) - { - /* - * If no reference structure was specified, pick the first one that has - * a mapping in the alignment - */ - refStructure = candidateRefStructure; - } - - String[] selcom = new String[files.length]; - int nmatched = matched.cardinality(); - if (nmatched < 4) - { - return (MessageManager.formatMessage("label.insufficient_residues", - nmatched)); - } - - /* - * generate select statements to select regions to superimpose structures - */ - { - // TODO extract method to construct selection statements - for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++) - { - String chainCd = ":" + structures[pdbfnum].chain; - int lpos = -1; - boolean run = false; - StringBuilder molsel = new StringBuilder(); - molsel.append("{"); - - int nextColumnMatch = matched.nextSetBit(0); - while (nextColumnMatch != -1) - { - int pdbResNo = structures[pdbfnum].pdbResNo[nextColumnMatch]; - if (lpos != pdbResNo - 1) - { - // discontinuity - if (lpos != -1) - { - molsel.append(lpos); - molsel.append(chainCd); - molsel.append("|"); - } - run = false; - } - else - { - // continuous run - and lpos >-1 - if (!run) - { - // at the beginning, so add dash - molsel.append(lpos); - molsel.append("-"); - } - run = true; - } - lpos = pdbResNo; - nextColumnMatch = matched.nextSetBit(nextColumnMatch + 1); - } - /* - * add final selection phrase - */ - if (lpos != -1) - { - molsel.append(lpos); - molsel.append(chainCd); - molsel.append("}"); - } - if (molsel.length() > 1) - { - selcom[pdbfnum] = molsel.toString(); - selectioncom.append("(("); - selectioncom.append(selcom[pdbfnum].substring(1, - selcom[pdbfnum].length() - 1)); - selectioncom.append(" )& "); - selectioncom.append(pdbfnum + 1); - selectioncom.append(".1)"); - if (pdbfnum < files.length - 1) - { - selectioncom.append("|"); - } - } - else - { - selcom[pdbfnum] = null; - } - } - } - StringBuilder command = new StringBuilder(256); - // command.append("set spinFps 10;\n"); - - for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++) - { - if (pdbfnum == refStructure || selcom[pdbfnum] == null - || selcom[refStructure] == null) - { - continue; - } - command.append("echo "); - command.append("\"Superposing ("); - command.append(structures[pdbfnum].pdbId); - command.append(") against reference ("); - command.append(structures[refStructure].pdbId); - command.append(")\";\ncompare " + nSeconds); - command.append("{"); - command.append(Integer.toString(1 + pdbfnum)); - command.append(".1} {"); - command.append(Integer.toString(1 + refStructure)); - // conformation=1 excludes alternate locations for CA (JAL-1757) - command.append( - ".1} SUBSET {(*.CA | *.P) and conformation=1} ATOMS "); - - // for (int s = 0; s < 2; s++) - // { - // command.append(selcom[(s == 0 ? pdbfnum : refStructure)]); - // } - command.append(selcom[pdbfnum]); - command.append(selcom[refStructure]); - command.append(" ROTATE TRANSLATE;\n"); - } - if (selectioncom.length() > 0) - { - // TODO is performing selectioncom redundant here? is done later on - // System.out.println("Select regions:\n" + selectioncom.toString()); - evalStateCommand("select *; cartoons off; backbone; select (" - + selectioncom.toString() + "); cartoons; "); - // selcom.append("; ribbons; "); - String cmdString = command.toString(); - // System.out.println("Superimpose command(s):\n" + cmdString); - - evalStateCommand(cmdString); - } - } - if (selectioncom.length() > 0) - {// finally, mark all regions that were superposed. - if (selectioncom.substring(selectioncom.length() - 1).equals("|")) - { - selectioncom.setLength(selectioncom.length() - 1); - } - // System.out.println("Select regions:\n" + selectioncom.toString()); - evalStateCommand("select *; cartoons off; backbone; select (" - + selectioncom.toString() + "); cartoons; "); - // evalStateCommand("select *; backbone; select "+selcom.toString()+"; - // cartoons; center "+selcom.toString()); - } - - return null; - } - - public void evalStateCommand(String command) - { + String cmd = command.getCommand(); jmolHistory(false); - if (lastCommand == null || !lastCommand.equals(command)) + if (lastCommand == null || !lastCommand.equals(cmd)) { - jmolViewer.evalStringQuiet(cmd + "\n"); - jmolScript(command + "\n"); ++ jmolScript(cmd + "\n"); } jmolHistory(true); - lastCommand = command; - } - - Thread colourby = null; - - /** - * Sends a set of colour commands to the structure viewer - * - * @param colourBySequenceCommands - */ - @Override - protected void colourBySequence( - final StructureMappingcommandSet[] colourBySequenceCommands) - { - if (colourby != null) - { - colourby.interrupt(); - colourby = null; - } - Thread colourby = new Thread(new Runnable() - { - @Override - public void run() - { - for (StructureMappingcommandSet cpdbbyseq : colourBySequenceCommands) - { - for (String cbyseq : cpdbbyseq.commands) - { - executeWhenReady(cbyseq); - } - } - } - }); - colourby.start(); - this.colourby = colourby; - } - - /** - * @param files - * @param sr - * @param viewPanel - * @return - */ - @Override - protected StructureMappingcommandSet[] getColourBySequenceCommands( - String[] files, SequenceRenderer sr, AlignmentViewPanel viewPanel) - { - return JmolCommands.getColourBySequenceCommand(getSsm(), files, - getSequence(), sr, viewPanel); - } - - /** - * @param command - */ - protected void executeWhenReady(String command) - { - evalStateCommand(command); + lastCommand = cmd; + return null; } public void createImage(String file, String type, int quality) @@@ -168,6 -575,43 +178,6 @@@ return null; } - public Color getColour(int atomIndex, int pdbResNum, String chain, - String pdbfile) - { - if (getModelNum(pdbfile) < 0) - { - return null; - } - // TODO: verify atomIndex is selecting correct model. - // return new Color(viewer.getAtomArgb(atomIndex)); Jmol 12.2.4 - int colour = viewer.ms.at[atomIndex].atomPropertyInt(T.color); - return new Color(colour); - } - - /** - * instruct the Jalview binding to update the pdbentries vector if necessary - * prior to matching the jmol view's contents to the list of structure files - * Jalview knows about. - */ - public abstract void refreshPdbEntries(); - - private int getModelNum(String modelFileName) - { - String[] mfn = getStructureFiles(); - if (mfn == null) - { - return -1; - } - for (int i = 0; i < mfn.length; i++) - { - if (mfn[i].equalsIgnoreCase(modelFileName)) - { - return i; - } - } - return -1; - } - /** * map between index of model filename returned from getPdbFile and the first * index of models from this file in the viewer. Note - this is not trimmed - @@@ -178,24 -622,20 +188,24 @@@ @Override public synchronized String[] getStructureFiles() { - List mset = new ArrayList<>(); - if (viewer == null) + if (jmolViewer == null) { return new String[0]; } if (modelFileNames == null) { - int modelCount = viewer.ms.mc; + int modelCount = jmolViewer.ms.mc; String filePath = null; + List mset = new ArrayList<>(); for (int i = 0; i < modelCount; ++i) { - filePath = viewer.ms.getModelFileName(i); - if (!mset.contains(filePath)) + /* + * defensive check for null as getModelFileName can return null + * even when model count ms.mc is > 0 + */ + filePath = jmolViewer.ms.getModelFileName(i); + if (filePath != null && !mset.contains(filePath)) { mset.add(filePath); } @@@ -235,7 -675,7 +245,7 @@@ { if (resetLastRes.length() > 0) { - jmolViewer.evalStringQuiet(resetLastRes.toString()); + jmolScript(resetLastRes.toString()); resetLastRes.setLength(0); } for (AtomSpec atom : atoms) @@@ -250,39 -690,59 +260,39 @@@ public void highlightAtom(int atomIndex, int pdbResNum, String chain, String pdbfile) { - if (modelFileNames == null) - { - return; - } - - // look up file model number for this pdbfile - int mdlNum = 0; - // may need to adjust for URLencoding here - we don't worry about that yet. - while (mdlNum < modelFileNames.length - && !pdbfile.equals(modelFileNames[mdlNum])) - { - mdlNum++; - } - if (mdlNum == modelFileNames.length) + String modelId = getModelIdForFile(pdbfile); + if (modelId.isEmpty()) { return; } jmolHistory(false); + StringBuilder selection = new StringBuilder(32); StringBuilder cmd = new StringBuilder(64); - cmd.append("select " + pdbResNum); // +modelNum - - resetLastRes.append("select " + pdbResNum); // +modelNum - - cmd.append(":"); - resetLastRes.append(":"); + selection.append("select ").append(String.valueOf(pdbResNum)); + selection.append(":"); if (!chain.equals(" ")) { - cmd.append(chain); - resetLastRes.append(chain); - } - { - cmd.append(" /" + (mdlNum + 1)); - resetLastRes.append("/" + (mdlNum + 1)); + selection.append(chain); } - cmd.append(";wireframe 100;" + cmd.toString() + " and not hetero;"); + selection.append(" /").append(modelId); - resetLastRes.append(";wireframe 0;" + resetLastRes.toString() - + " and not hetero; spacefill 0;"); + cmd.append(selection).append(";wireframe 100;").append(selection) + .append(" and not hetero;").append("spacefill 200;select none"); - cmd.append("spacefill 200;select none"); + resetLastRes.append(selection).append(";wireframe 0;").append(selection) + .append(" and not hetero; spacefill 0;"); - jmolViewer.evalStringQuiet(cmd.toString()); + jmolScript(cmd.toString()); jmolHistory(true); - } - boolean debug = true; + private boolean debug = true; private void jmolHistory(boolean enable) { - jmolViewer.evalStringQuiet("History " + ((debug || enable) ? "on" : "off")); + jmolScript("History " + ((debug || enable) ? "on" : "off")); } public void loadInline(String string) @@@ -296,7 -756,7 +306,7 @@@ // Then, construct pass a reader for the string to Jmol. // ((org.jmol.Viewer.Viewer) viewer).loadModelFromFile(fullPathName, // fileName, null, reader, false, null, null, 0); - viewer.openStringInline(string); + jmolViewer.openStringInline(string); } protected void mouseOverStructure(int atomIndex, final String strInfo) @@@ -339,7 -799,8 +349,7 @@@ chainId = " "; } - String pdbfilename = modelFileNames[frameNo]; // default is first or current - // model + String pdbfilename = modelFileNames[0]; // default is first model if (mdlSep > -1) { if (chainSeparator1 == -1) @@@ -372,7 -833,7 +382,7 @@@ if (pdbfilename == null) { - pdbfilename = new File(viewer.ms.getModelFileName(mnumber)) + pdbfilename = new File(jmolViewer.ms.getModelFileName(mnumber)) .getAbsolutePath(); } } @@@ -398,7 -859,7 +408,7 @@@ sb.append(";set hoverLabel \"").append(toks.nextToken()).append(" ") .append(toks.nextToken()); sb.append("|").append(label).append("\""); - evalStateCommand(sb.toString()); + executeCommand(new StructureCommand(sb.toString()), false); } } @@@ -428,7 -889,7 +438,7 @@@ { /** * this implements the toggle label behaviour copied from the original - * structure viewer, MCView + * structure viewer, mc_view */ if (strData != null) { @@@ -459,12 -920,12 +469,12 @@@ if (!atomsPicked.contains(picked)) { - jmolViewer.evalStringQuiet("select " + picked + ";label %n %r:%c"); + jmolScript("select " + picked + ";label %n %r:%c"); atomsPicked.addElement(picked); } else { - viewer.evalString("select " + picked + ";label off"); + jmolViewer.evalString("select " + picked + ";label off"); atomsPicked.removeElement(picked); } jmolHistory(true); @@@ -580,6 -1041,8 +590,6 @@@ fileLoadingError = null; String[] oldmodels = modelFileNames; modelFileNames = null; - chainNames = new ArrayList<>(); - chainFile = new Hashtable<>(); boolean notifyLoaded = false; String[] modelfilenames = getStructureFiles(); // first check if we've lost any structures @@@ -630,7 -1093,7 +640,7 @@@ // calculate essential attributes for the pdb data imported inline. // prolly need to resolve modelnumber properly - for now just use our // 'best guess' - pdbfile = viewer.getData( + pdbfile = jmolViewer.getData( "" + (1 + _modelFileNameMap[modelnum]) + ".0", "PDB"); } // search pdbentries and sequences to find correct pdbentry for this @@@ -645,8 -1108,7 +655,7 @@@ // see JAL-623 - need method of matching pasted data up { pdb = getSsm().setMapping(getSequence()[pe], getChains()[pe], - pdbfile, DataSourceType.PASTE, - getIProgressIndicator()); + pdbfile, DataSourceType.PASTE, getIProgressIndicator()); getPdbEntry(modelnum).setFile("INLINE" + pdb.getId()); matches = true; foundEntry = true; @@@ -685,7 -1147,14 +694,7 @@@ } if (matches) { - // add an entry for every chain in the model - for (int i = 0; i < pdb.getChains().size(); i++) - { - String chid = new String( - pdb.getId() + ":" + pdb.getChains().elementAt(i).id); - chainFile.put(chid, fileName); - chainNames.add(chid); - } + stashFoundChains(pdb, fileName); notifyLoaded = true; } } @@@ -695,7 -1164,7 +704,7 @@@ // this is a foreign pdb file that jalview doesn't know about - add // it to the dataset and try to find a home - either on a matching // sequence or as a new sequence. - String pdbcontent = viewer.getData("/" + (modelnum + 1) + ".1", + String pdbcontent = jmolViewer.getData("/" + (modelnum + 1) + ".1", "PDB"); // parse pdb file into a chain, etc. // locate best match for pdb in associated views and add mapping to @@@ -714,7 -1183,7 +723,7 @@@ // } if (!isLoadingFromArchive()) { - jmolViewer.evalStringQuiet( + jmolScript( "model *; select backbone;restrict;cartoon;wireframe off;spacefill off"); } // register ourselves as a listener and notify the gui that it needs to @@@ -733,6 -1202,12 +742,6 @@@ setLoadingFromArchive(false); } - @Override - public List getChainNames() - { - return chainNames; - } - protected IProgressIndicator getIProgressIndicator() { return null; @@@ -777,9 -1252,40 +786,11 @@@ } - @Override - public void setJalviewColourScheme(ColourSchemeI cs) - { - colourBySequence = false; - - if (cs == null) - { - return; - } - - jmolHistory(false); - StringBuilder command = new StringBuilder(128); - command.append("select *;color white;"); - List residueSet = ResidueProperties.getResidues(isNucleotide(), - false); - for (String resName : residueSet) - { - char res = resName.length() == 3 - ? ResidueProperties.getSingleCharacterCode(resName) - : resName.charAt(0); - Color col = cs.findColour(res, 0, null, null, 0f); - command.append("select " + resName + ";color[" + col.getRed() + "," - + col.getGreen() + "," + col.getBlue() + "];"); - } - - evalStateCommand(command.toString()); - jmolHistory(true); - } - public void showHelp() { - showUrl("http://jmol.sourceforge.net/docs/JmolUserGuide/", "jmolHelp"); + showUrl("http://wiki.jmol.org" + // BH 2018 "http://jmol.sourceforge.net/docs/JmolUserGuide/" + , "jmolHelp"); } /** @@@ -790,13 -1296,29 +801,22 @@@ public abstract void showUrl(String url, String target); /** - * called when the binding thinks the UI needs to be refreshed after a Jmol - * state change. this could be because structures were loaded, or because an - * error has occured. - */ - public abstract void refreshGUI(); - - /** * called to show or hide the associated console window container. * * @param show */ public abstract void showConsole(boolean show); + public static Viewer getJmolData(JmolParser jmolParser) + { + return (Viewer) JmolViewer.allocateViewer(null, null, null, null, null, + "-x -o -n", jmolParser); + } + /** + * + * + * * @param renderPanel * @param jmolfileio * - when true will initialise jmol's file IO system (should be false @@@ -827,25 -1349,36 +847,36 @@@ * @param consolePanel * - panel to contain Jmol console * @param buttonsToShow - * - buttons to show on the console, in ordr + * - buttons to show on the console, in order */ public void allocateViewer(Container renderPanel, boolean jmolfileio, String htmlName, URL documentBase, URL codeBase, String commandOptions, final Container consolePanel, String buttonsToShow) { + + System.err.println("Allocating Jmol Viewer: " + commandOptions); + if (commandOptions == null) { commandOptions = ""; } - viewer = (Viewer) JmolViewer.allocateViewer(renderPanel, + jmolViewer = (Viewer) JmolViewer.allocateViewer(renderPanel, (jmolfileio ? new SmarterJmolAdapter() : null), htmlName + ((Object) this).toString(), documentBase, codeBase, commandOptions, this); - viewer.setJmolStatusListener(this); // extends JmolCallbackListener + jmolViewer.setJmolStatusListener(this); // extends JmolCallbackListener - console = createJmolConsole(consolePanel, buttonsToShow); + try + { + console = createJmolConsole(consolePanel, buttonsToShow); + } catch (Throwable e) + { + System.err.println("Could not create Jmol application console. " + + e.getMessage()); + e.printStackTrace(); + } if (consolePanel != null) { consolePanel.addComponentListener(this); @@@ -857,9 -1390,33 +888,12 @@@ protected abstract JmolAppConsoleInterface createJmolConsole( Container consolePanel, String buttonsToShow); + // BH 2018 -- Jmol console is not working due to problems with styled + // documents. + protected org.jmol.api.JmolAppConsoleInterface console = null; @Override - public void setBackgroundColour(java.awt.Color col) - { - jmolHistory(false); - jmolScript("background [" + col.getRed() + "," + col.getGreen() + "," - + col.getBlue() + "];"); - jmolHistory(true); - } - - private String jmolScript(String script) - { - - System.err.println(">>Jmol>> " + script); - - String s = viewer.scriptWait(script); - - System.err.println("< cset = new ArrayList<>(); - - for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++) - { - StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]); - StringBuilder command = new StringBuilder(128); - List str = new ArrayList<>(); - - if (mapping == null || mapping.length < 1) - { - continue; - } - - for (int s = 0; s < sequence[pdbfnum].length; s++) - { - for (int sp, m = 0; m < mapping.length; m++) - { - if (mapping[m].getSequence() == sequence[pdbfnum][s] - && (sp = al.findIndex(sequence[pdbfnum][s])) > -1) - { - int lastPos = StructureMapping.UNASSIGNED_VALUE; - SequenceI asp = al.getSequenceAt(sp); - for (int r = 0; r < asp.getLength(); r++) - { - // no mapping to gaps in sequence - if (Comparison.isGap(asp.getCharAt(r))) - { - continue; - } - int pos = mapping[m].getPDBResNum(asp.findPosition(r)); - - if (pos == lastPos) - { - continue; - } - if (pos == StructureMapping.UNASSIGNED_VALUE) - { - // terminate current colour op - if (command.length() > 0 - && command.charAt(command.length() - 1) != ';') - { - command.append(";"); - } - // reset lastPos - lastPos = StructureMapping.UNASSIGNED_VALUE; - continue; - } - - lastPos = pos; - - Color col = sr.getResidueColour(sequence[pdbfnum][s], r, - finder); - - /* - * shade hidden regions darker - */ - if (!cs.isVisible(r)) - { - col = Color.GRAY; - } - - String newSelcom = (mapping[m].getChain() != " " - ? ":" + mapping[m].getChain() - : "") + "/" + (pdbfnum + 1) + ".1" + ";color" - + getColourString(col); - if (command.length() > newSelcom.length() && command - .substring(command.length() - newSelcom.length()) - .equals(newSelcom)) - { - command = JmolCommands.condenseCommand(command, pos); - continue; - } - // TODO: deal with case when buffer is too large for Jmol to parse - // - execute command and flush - - if (command.length() > 0 - && command.charAt(command.length() - 1) != ';') - { - command.append(";"); - } - - if (command.length() > 51200) - { - // add another chunk - str.add(command.toString()); - command.setLength(0); - } - command.append("select " + pos); - command.append(newSelcom); - } - // break; - } - } - } - { - // add final chunk - str.add(command.toString()); - command.setLength(0); - } - cset.addAll(str); - - } - return cset.toArray(new String[cset.size()]); - } - - public static StringBuilder condenseCommand(StringBuilder command, - int pos) - { - - // work back to last 'select' - int p = command.length(), q = p; - do - { - p -= 6; - if (p < 1) - { - p = 0; - } - ; - } while ((q = command.indexOf("select", p)) == -1 && p > 0); - - StringBuilder sb = new StringBuilder(command.substring(0, q + 7)); - - command = command.delete(0, q + 7); - - String start; - - if (command.indexOf("-") > -1) - { - start = command.substring(0, command.indexOf("-")); - } - else - { - start = command.substring(0, command.indexOf(":")); - } - - sb.append(start + "-" + pos + command.substring(command.indexOf(":"))); - - return sb; - } - + @Override + public StructureCommandI colourByChain() + { + return COLOUR_BY_CHAIN; + } + + @Override + public List colourByCharge() + { + return Arrays.asList(COLOUR_BY_CHARGE); + } + + @Override + public List colourByResidues(Map colours) + { + List cmds = super.colourByResidues(colours); + cmds.add(0, COLOUR_ALL_WHITE); + return cmds; + } + + @Override + public StructureCommandI setBackgroundColour(Color col) + { + return new StructureCommand("background " + getColourString(col)); + } + + @Override + public StructureCommandI focusView() + { + return FOCUS_VIEW; + } + + @Override + public List showChains(List toShow) + { + StringBuilder atomSpec = new StringBuilder(128); + boolean first = true; + for (String chain : toShow) + { + String[] tokens = chain.split(":"); + if (tokens.length == 2) + { + if (!first) + { + atomSpec.append(" or "); + } + first = false; + atomSpec.append(":").append(tokens[1]).append(" /").append(tokens[0]); + } + } + + String spec = atomSpec.toString(); + String command = "select *;restrict " + spec + ";cartoon;center " + + spec; + return Arrays.asList(new StructureCommand(command)); + } /** - * Jmol utility which constructs the commands to colour chains by the given - * alignment + * Returns a command to superpose atoms in {@code atomSpec} to those in + * {@code refAtoms}, restricted to alpha carbons only (Phosphorous for rna). + * For example + * + *
 +   * compare {2.1} {1.1} SUBSET {(*.CA | *.P) and conformation=1} 
 +   *         ATOMS {1-87:A}{2-54:A|61-94:A} ROTATE TRANSLATE 1.0;
 +   * 
* - * @returns Object[] { Object[] { , + * where {@code conformation=1} excludes ALTLOC atom locations, and 1.0 is the + * time in seconds to animate the action. For this example, atoms in model 2 + * are moved towards atoms in model 1. + *

+ * The two atomspecs should each be for one model only, but may have more than + * one chain. The number of atoms specified should be the same for both + * models, though if not, Jmol may make a 'best effort' at superposition. * + * @see https://chemapps.stolaf.edu/jmol/docs/#compare */ - public static StructureMappingcommandSet[] getColourBySequenceCommand( - StructureSelectionManager ssm, String[] files, - SequenceI[][] sequence, SequenceRenderer sr, + @Override + public List superposeStructures(AtomSpecModel refAtoms, + AtomSpecModel atomSpec) + { + StringBuilder sb = new StringBuilder(64); + String refModel = refAtoms.getModels().iterator().next(); + String model2 = atomSpec.getModels().iterator().next(); + sb.append(String.format("compare {%s.1} {%s.1}", model2, refModel)); + sb.append(" SUBSET {(*.CA | *.P) and conformation=1} ATOMS {"); + + /* + * command examples don't include modelspec with atoms, getAtomSpec does; + * it works, so leave it as it is for simplicity + */ + sb.append(getAtomSpec(atomSpec, true)).append("}{"); + sb.append(getAtomSpec(refAtoms, true)).append("}"); + sb.append(" ROTATE TRANSLATE "); + sb.append(getCommandSeparator()); + + /* + * show residues used for superposition as ribbon + */ + sb.append("select ").append(getAtomSpec(atomSpec, false)).append("|"); + sb.append(getAtomSpec(refAtoms, false)).append(getCommandSeparator()) + .append("cartoons"); + + return Arrays.asList(new StructureCommand(sb.toString())); + } + + @Override + public StructureCommandI openCommandFile(String path) + { + /* + * https://chemapps.stolaf.edu/jmol/docs/#script + * not currently used in Jalview + */ + return new StructureCommand("script " + path); + } + + @Override + public StructureCommandI saveSession(String filepath) + { + /* + * https://chemapps.stolaf.edu/jmol/docs/#writemodel + */ + return new StructureCommand("write STATE \"" + filepath + "\""); + } + + @Override + protected StructureCommandI getColourCommand(String atomSpec, Color colour) + { + StringBuilder sb = new StringBuilder(atomSpec.length()+20); + sb.append("select ").append(atomSpec).append(getCommandSeparator()) + .append("color").append(getColourString(colour)); + return new StructureCommand(sb.toString()); + } + + @Override + protected String getResidueSpec(String residue) + { + return residue; + } + + /** + * Generates a Jmol atomspec string like + * + *

 +   * 2-5:A/1.1,8:A/1.1,5-10:B/2.1
 +   * 
+ * + * Parameter {@code alphaOnly} is not used here - this restriction is made by + * a separate clause in the {@code compare} (superposition) command. + */ + @Override + public String getAtomSpec(AtomSpecModel model, boolean alphaOnly) + { + StringBuilder sb = new StringBuilder(128); + + boolean first = true; + for (String modelNo : model.getModels()) + { + for (String chain : model.getChains(modelNo)) + { + for (int[] range : model.getRanges(modelNo, chain)) + { + if (!first) + { + sb.append(PIPE); + } + first = false; + if (range[0] == range[1]) + { + sb.append(range[0]); + } + else + { + sb.append(range[0]).append(HYPHEN).append(range[1]); + } + sb.append(COLON).append(chain.trim()).append(SLASH); + sb.append(String.valueOf(modelNo)).append(".1"); + } + } + } + + return sb.toString(); + } + + @Override + public List showBackbone() + { + return Arrays.asList(SHOW_BACKBONE); + } + + @Override + public StructureCommandI loadFile(String file) + { + return null; + } ++ ++ /** ++ * Obsolete method, only referenced from ++ * jalview.javascript.MouseOverStructureListener ++ * ++ * @param ssm ++ * @param files ++ * @param sequence ++ * @param sr ++ * @param viewPanel ++ * @return ++ */ ++ @Deprecated ++ public String[] colourBySequence(StructureSelectionManager ssm, ++ String[] files, SequenceI[][] sequence, SequenceRenderer sr, + AlignmentViewPanel viewPanel) + { ++ // TODO delete method ++ + FeatureRenderer fr = viewPanel.getFeatureRenderer(); + FeatureColourFinder finder = new FeatureColourFinder(fr); + AlignViewportI viewport = viewPanel.getAlignViewport(); + HiddenColumns cs = viewport.getAlignment().getHiddenColumns(); + AlignmentI al = viewport.getAlignment(); - List cset = new ArrayList(); ++ List cset = new ArrayList<>(); + + for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++) + { + StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]); - StringBuilder command = new StringBuilder(); - StructureMappingcommandSet smc; - ArrayList str = new ArrayList(); ++ StringBuilder command = new StringBuilder(128); ++ List str = new ArrayList<>(); + + if (mapping == null || mapping.length < 1) + { + continue; + } + + for (int s = 0; s < sequence[pdbfnum].length; s++) + { + for (int sp, m = 0; m < mapping.length; m++) + { + if (mapping[m].getSequence() == sequence[pdbfnum][s] + && (sp = al.findIndex(sequence[pdbfnum][s])) > -1) + { + int lastPos = StructureMapping.UNASSIGNED_VALUE; + SequenceI asp = al.getSequenceAt(sp); + for (int r = 0; r < asp.getLength(); r++) + { + // no mapping to gaps in sequence - if (jalview.util.Comparison.isGap(asp.getCharAt(r))) ++ if (Comparison.isGap(asp.getCharAt(r))) + { + continue; + } + int pos = mapping[m].getPDBResNum(asp.findPosition(r)); + + if (pos == lastPos) + { + continue; + } + if (pos == StructureMapping.UNASSIGNED_VALUE) + { + // terminate current colour op + if (command.length() > 0 + && command.charAt(command.length() - 1) != ';') + { + command.append(";"); + } + // reset lastPos + lastPos = StructureMapping.UNASSIGNED_VALUE; + continue; + } + + lastPos = pos; + + Color col = sr.getResidueColour(sequence[pdbfnum][s], r, + finder); + + /* + * shade hidden regions darker + */ + if (!cs.isVisible(r)) + { + col = Color.GRAY; + } + - // todo JAL-3152 handle 'no chain' case without errors - boolean hasChain = true || mapping[m].getChain() != " "; - String chainSpec = hasChain ++ String newSelcom = (mapping[m].getChain() != " " + ? ":" + mapping[m].getChain() - : ""; - String newSelcom = chainSpec + "/" + (pdbfnum + 1) + ".1" + ";color[" - + col.getRed() + "," + col.getGreen() + "," - + col.getBlue() + "]"; ++ : "") + "/" + (pdbfnum + 1) + ".1" + ";color" ++ + getColourString(col); + if (command.length() > newSelcom.length() && command + .substring(command.length() - newSelcom.length()) + .equals(newSelcom)) + { + command = JmolCommands.condenseCommand(command, pos); + continue; + } + // TODO: deal with case when buffer is too large for Jmol to parse + // - execute command and flush + + if (command.length() > 0 + && command.charAt(command.length() - 1) != ';') + { + command.append(";"); + } + + if (command.length() > 51200) + { + // add another chunk + str.add(command.toString()); + command.setLength(0); + } + command.append("select " + pos); + command.append(newSelcom); + } + // break; + } + } + } + { + // add final chunk + str.add(command.toString()); + command.setLength(0); + } - // Finally, add the command set ready to be returned. - cset.add(new StructureMappingcommandSet(JmolCommands.class, - files[pdbfnum], str.toArray(new String[str.size()]))); ++ cset.addAll(str); + + } - return cset.toArray(new StructureMappingcommandSet[cset.size()]); ++ return cset.toArray(new String[cset.size()]); + } + - public static StringBuilder condenseCommand(StringBuilder command, int pos) ++ /** ++ * Helper method ++ * ++ * @param command ++ * @param pos ++ * @return ++ */ ++ @Deprecated ++ private static StringBuilder condenseCommand( ++ StringBuilder command, ++ int pos) + { + + // work back to last 'select' + int p = command.length(), q = p; + do + { + p -= 6; + if (p < 1) + { + p = 0; + } + ; + } while ((q = command.indexOf("select", p)) == -1 && p > 0); + + StringBuilder sb = new StringBuilder(command.substring(0, q + 7)); + + command = command.delete(0, q + 7); + + String start; + + if (command.indexOf("-") > -1) + { + start = command.substring(0, command.indexOf("-")); + } + else + { + start = command.substring(0, command.indexOf(":")); + } + + sb.append(start + "-" + pos + command.substring(command.indexOf(":"))); + + return sb; + } - } diff --combined src/jalview/gui/AlignFrame.java index 51c9e09,7818748..ef40261 --- a/src/jalview/gui/AlignFrame.java +++ b/src/jalview/gui/AlignFrame.java @@@ -20,6 -20,58 +20,58 @@@ */ package jalview.gui; + import java.awt.BorderLayout; + import java.awt.Color; + import java.awt.Component; + import java.awt.Rectangle; + import java.awt.Toolkit; + import java.awt.datatransfer.Clipboard; + import java.awt.datatransfer.DataFlavor; + import java.awt.datatransfer.StringSelection; + import java.awt.datatransfer.Transferable; + import java.awt.dnd.DnDConstants; + import java.awt.dnd.DropTargetDragEvent; + import java.awt.dnd.DropTargetDropEvent; + import java.awt.dnd.DropTargetEvent; + import java.awt.dnd.DropTargetListener; + import java.awt.event.ActionEvent; + import java.awt.event.ActionListener; + import java.awt.event.FocusAdapter; + import java.awt.event.FocusEvent; + import java.awt.event.ItemEvent; + import java.awt.event.ItemListener; + import java.awt.event.KeyAdapter; + import java.awt.event.KeyEvent; + import java.awt.event.MouseEvent; + import java.awt.print.PageFormat; + import java.awt.print.PrinterJob; + import java.beans.PropertyChangeEvent; + import java.io.File; + import java.io.FileWriter; + import java.io.PrintWriter; + import java.net.URL; + import java.util.ArrayList; + import java.util.Arrays; + import java.util.Deque; + import java.util.Enumeration; + import java.util.Hashtable; + import java.util.List; + import java.util.Vector; + + import javax.swing.ButtonGroup; + import javax.swing.JCheckBoxMenuItem; + import javax.swing.JComponent; + import javax.swing.JEditorPane; + import javax.swing.JInternalFrame; + import javax.swing.JLabel; + import javax.swing.JLayeredPane; + import javax.swing.JMenu; + import javax.swing.JMenuItem; + import javax.swing.JPanel; + import javax.swing.JScrollPane; + import javax.swing.SwingUtilities; + + import ext.vamsas.ServiceHandle; import jalview.analysis.AlignmentSorter; import jalview.analysis.AlignmentUtils; import jalview.analysis.CrossRef; @@@ -27,7 -79,7 +79,7 @@@ import jalview.analysis.Dna import jalview.analysis.GeneticCodeI; import jalview.analysis.ParseProperties; import jalview.analysis.SequenceIdMatcher; - import jalview.api.AlignExportSettingI; + import jalview.api.AlignExportSettingsI; import jalview.api.AlignViewControllerGuiI; import jalview.api.AlignViewControllerI; import jalview.api.AlignViewportI; @@@ -47,6 -99,7 +99,7 @@@ import jalview.commands.RemoveGapColCom import jalview.commands.RemoveGapsCommand; import jalview.commands.SlideSequencesCommand; import jalview.commands.TrimRegionCommand; + import jalview.datamodel.AlignExportSettingsAdapter; import jalview.datamodel.AlignedCodonFrame; import jalview.datamodel.Alignment; import jalview.datamodel.AlignmentAnnotation; @@@ -56,7 -109,6 +109,6 @@@ import jalview.datamodel.AlignmentOrder import jalview.datamodel.AlignmentView; import jalview.datamodel.ColumnSelection; import jalview.datamodel.HiddenColumns; - import jalview.datamodel.HiddenSequences; import jalview.datamodel.PDBEntry; import jalview.datamodel.SeqCigar; import jalview.datamodel.Sequence; @@@ -86,11 -138,14 +138,14 @@@ import jalview.io.ScoreMatrixFile import jalview.io.TCoffeeScoreFile; import jalview.io.vcf.VCFLoader; import jalview.jbgui.GAlignFrame; + import jalview.project.Jalview2XML; import jalview.schemes.ColourSchemeI; import jalview.schemes.ColourSchemes; import jalview.schemes.ResidueColourScheme; import jalview.schemes.TCoffeeColourScheme; + import jalview.util.ImageMaker.TYPE; import jalview.util.MessageManager; + import jalview.util.Platform; import jalview.viewmodel.AlignmentViewport; import jalview.viewmodel.ViewportRanges; import jalview.ws.DBRefFetcher; @@@ -100,59 -155,13 +155,13 @@@ import jalview.ws.jws2.Jws2Discoverer import jalview.ws.jws2.jabaws2.Jws2Instance; import jalview.ws.seqfetcher.DbSourceProxy; - import java.awt.BorderLayout; - import java.awt.Component; - import java.awt.Rectangle; - import java.awt.Toolkit; - import java.awt.datatransfer.Clipboard; - import java.awt.datatransfer.DataFlavor; - import java.awt.datatransfer.StringSelection; - import java.awt.datatransfer.Transferable; - import java.awt.dnd.DnDConstants; - import java.awt.dnd.DropTargetDragEvent; - import java.awt.dnd.DropTargetDropEvent; - import java.awt.dnd.DropTargetEvent; - import java.awt.dnd.DropTargetListener; - import java.awt.event.ActionEvent; - import java.awt.event.ActionListener; - import java.awt.event.FocusAdapter; - import java.awt.event.FocusEvent; - import java.awt.event.ItemEvent; - import java.awt.event.ItemListener; - import java.awt.event.KeyAdapter; - import java.awt.event.KeyEvent; - import java.awt.event.MouseEvent; - import java.awt.print.PageFormat; - import java.awt.print.PrinterJob; - import java.beans.PropertyChangeEvent; - import java.io.File; - import java.io.FileWriter; - import java.io.PrintWriter; - import java.net.URL; - import java.util.ArrayList; - import java.util.Arrays; - import java.util.Deque; - import java.util.Enumeration; - 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; - import javax.swing.JLayeredPane; - import javax.swing.JMenu; - import javax.swing.JMenuItem; - import javax.swing.JScrollPane; - import javax.swing.SwingUtilities; - /** * DOCUMENT ME! * * @author $author$ * @version $Revision$ */ + @SuppressWarnings("serial") public class AlignFrame extends GAlignFrame implements DropTargetListener, IProgressIndicator, AlignViewControllerGuiI, ColourChangeListener { @@@ -182,6 -191,8 +191,8 @@@ */ String fileName = null; + File fileObject; + /** * Creates a new AlignFrame object with specific width and height. * @@@ -334,6 -345,8 +345,8 @@@ */ void init() { + // setBackground(Color.white); // BH 2019 + if (!Jalview.isHeadlessMode()) { progressBar = new ProgressBar(this.statusPanel, this.statusBar); @@@ -382,7 -395,10 +395,10 @@@ if (Desktop.desktop != null) { this.setDropTarget(new java.awt.dnd.DropTarget(this, this)); - addServiceListeners(); + if (!Platform.isJS()) + { + addServiceListeners(); + } setGUINucleotide(); } @@@ -398,7 -414,7 +414,7 @@@ addKeyListener(); - final List selviews = new ArrayList<>(); + final List selviews = new ArrayList<>(); final List origview = new ArrayList<>(); final String menuLabel = MessageManager .getString("label.copy_format_from"); @@@ -501,6 -517,17 +517,17 @@@ } /** + * JavaScript will have this, maybe others. More dependable than a file name + * and maintains a reference to the actual bytes loaded. + * + * @param file + */ + public void setFileObject(File file) + { + this.fileObject = file; + } + + /** * Add a KeyListener with handlers for various KeyPressed and KeyReleased * events */ @@@ -599,7 -626,7 +626,7 @@@ case KeyEvent.VK_BACK_SPACE: if (!viewport.cursorMode) { - cut_actionPerformed(null); + cut_actionPerformed(); } else { @@@ -651,7 -678,7 +678,7 @@@ case KeyEvent.VK_F2: viewport.cursorMode = !viewport.cursorMode; - statusBar.setText(MessageManager + setStatus(MessageManager .formatMessage("label.keyboard_editing_mode", new String[] { (viewport.cursorMode ? "on" : "off") })); if (viewport.cursorMode) @@@ -822,7 -849,7 +849,7 @@@ Desktop.instance.removeJalviewPropertyChangeListener("services", thisListener); closeMenuItem_actionPerformed(true); - }; + } }); // Finally, build the menu once to get current service state new Thread(new Runnable() @@@ -992,9 -1019,9 +1019,9 @@@ } @Override - public void fetchSequence_actionPerformed(ActionEvent e) + public void fetchSequence_actionPerformed() { - new jalview.gui.SequenceFetcher(this); + new SequenceFetcher(this); } @Override @@@ -1044,11 -1071,23 +1071,23 @@@ Rectangle bounds = this.getBounds(); FileLoader loader = new FileLoader(); - DataSourceType protocol = fileName.startsWith("http:") - ? DataSourceType.URL - : DataSourceType.FILE; - AlignFrame newframe = loader.LoadFileWaitTillLoaded(fileName, - protocol, currentFileFormat); + + AlignFrame newframe = null; + + if (fileObject == null) + { + + DataSourceType protocol = (fileName.startsWith("http:") + ? DataSourceType.URL + : DataSourceType.FILE); + newframe = loader.LoadFileWaitTillLoaded(fileName, protocol, + currentFileFormat); + } + else + { + newframe = loader.LoadFileWaitTillLoaded(fileObject, + DataSourceType.FILE, currentFileFormat); + } newframe.setBounds(bounds); if (featureSettings != null && featureSettings.isShowing()) @@@ -1093,7 -1132,7 +1132,7 @@@ if (fileName == null || (currentFileFormat == null) || fileName.startsWith("http")) { - saveAs_actionPerformed(null); + saveAs_actionPerformed(); } else { @@@ -1102,13 -1141,11 +1141,11 @@@ } /** - * DOCUMENT ME! - * - * @param e - * DOCUMENT ME! + * Saves the alignment to a file with a name chosen by the user, if necessary + * warning if a file would be overwritten */ @Override - public void saveAs_actionPerformed(ActionEvent e) + public void saveAs_actionPerformed() { String format = currentFileFormat == null ? null : currentFileFormat.getName(); @@@ -1122,214 -1159,234 +1159,234 @@@ int value = chooser.showSaveDialog(this); - if (value == JalviewFileChooser.APPROVE_OPTION) + if (value != JalviewFileChooser.APPROVE_OPTION) + { + return; + } + currentFileFormat = chooser.getSelectedFormat(); + // todo is this (2005) test now obsolete - value is never null? + while (currentFileFormat == null) { + JvOptionPane.showInternalMessageDialog(Desktop.desktop, + MessageManager + .getString("label.select_file_format_before_saving"), + MessageManager.getString("label.file_format_not_specified"), + JvOptionPane.WARNING_MESSAGE); currentFileFormat = chooser.getSelectedFormat(); - while (currentFileFormat == null) + value = chooser.showSaveDialog(this); + if (value != JalviewFileChooser.APPROVE_OPTION) { - JvOptionPane.showInternalMessageDialog(Desktop.desktop, - MessageManager.getString( - "label.select_file_format_before_saving"), - MessageManager.getString("label.file_format_not_specified"), - JvOptionPane.WARNING_MESSAGE); - currentFileFormat = chooser.getSelectedFormat(); - value = chooser.showSaveDialog(this); - if (value != JalviewFileChooser.APPROVE_OPTION) - { - return; - } + return; } + } - fileName = chooser.getSelectedFile().getPath(); + fileName = chooser.getSelectedFile().getPath(); - Cache.setProperty("DEFAULT_FILE_FORMAT", currentFileFormat.getName()); + Cache.setProperty("DEFAULT_FILE_FORMAT", currentFileFormat.getName()); + Cache.setProperty("LAST_DIRECTORY", fileName); + saveAlignment(fileName, currentFileFormat); + } + + boolean lastSaveSuccessful = false; + + FileFormatI lastFormatSaved; + + String lastFilenameSaved; + + /** + * Raise a dialog or status message for the last call to saveAlignment. + * + * @return true if last call to saveAlignment(file, format) was successful. + */ + public boolean isSaveAlignmentSuccessful() + { + + if (!lastSaveSuccessful) + { + JvOptionPane.showInternalMessageDialog(this, MessageManager + .formatMessage("label.couldnt_save_file", new Object[] + { lastFilenameSaved }), + MessageManager.getString("label.error_saving_file"), + JvOptionPane.WARNING_MESSAGE); + } + else + { + + setStatus(MessageManager.formatMessage( + "label.successfully_saved_to_file_in_format", new Object[] + { lastFilenameSaved, lastFormatSaved })); - Cache.setProperty("LAST_DIRECTORY", fileName); - saveAlignment(fileName, currentFileFormat); } + return lastSaveSuccessful; } - public boolean saveAlignment(String file, FileFormatI format) + /** + * Saves the alignment to the specified file path, in the specified format, + * which may be an alignment format, or Jalview project format. If the + * alignment has hidden regions, or the format is one capable of including + * non-sequence data (features, annotations, groups), then the user may be + * prompted to specify what to include in the output. + * + * @param file + * @param format + */ + public void saveAlignment(String file, FileFormatI format) { - boolean success = true; + lastSaveSuccessful = true; + lastFilenameSaved = file; + lastFormatSaved = format; if (FileFormat.Jalview.equals(format)) { String shortName = title; - - if (shortName.indexOf(java.io.File.separatorChar) > -1) + if (shortName.indexOf(File.separatorChar) > -1) { shortName = shortName.substring( - shortName.lastIndexOf(java.io.File.separatorChar) + 1); + shortName.lastIndexOf(File.separatorChar) + 1); } - - success = new jalview.project.Jalview2XML().saveAlignment(this, file, - shortName); - + lastSaveSuccessful = new Jalview2XML().saveAlignment(this, file, shortName); + statusBar.setText(MessageManager.formatMessage( "label.successfully_saved_to_file_in_format", new Object[] { fileName, format })); - + + return; } - else + + AlignExportSettingsI options = new AlignExportSettingsAdapter(false); + Runnable cancelAction = new Runnable() { - AlignmentExportData exportData = getAlignmentForExport(format, - viewport, null); - if (exportData.getSettings().isCancelled()) - { - return false; - } - FormatAdapter f = new FormatAdapter(alignPanel, - exportData.getSettings()); - String output = f.formatSequences(format, exportData.getAlignment(), // class - // cast - // exceptions - // will - // occur in the distant future - exportData.getOmitHidden(), exportData.getStartEndPostions(), - f.getCacheSuffixDefault(format), - viewport.getAlignment().getHiddenColumns()); - - if (output == null) + @Override + public void run() { - success = false; + lastSaveSuccessful = false; } - else + }; + Runnable outputAction = new Runnable() + { + @Override + public void run() { - // create backupfiles object and get new temp filename destination - BackupFiles backupfiles = new BackupFiles(file); - - try + // todo defer this to inside formatSequences (or later) + AlignmentExportData exportData = viewport + .getAlignExportData(options); + String output = new FormatAdapter(alignPanel, options) + .formatSequences(format, exportData.getAlignment(), + exportData.getOmitHidden(), + exportData.getStartEndPostions(), + viewport.getAlignment().getHiddenColumns()); + if (output == null) + { + lastSaveSuccessful = false; + } + else { - PrintWriter out = new PrintWriter( - new FileWriter(backupfiles.getTempFilePath())); + // create backupfiles object and get new temp filename destination + boolean doBackup = BackupFiles.getEnabled(); + BackupFiles backupfiles = doBackup ? new BackupFiles(file) : null; + try + { + String tempFilePath = doBackup ? backupfiles.getTempFilePath() : file; + PrintWriter out = new PrintWriter( + new FileWriter(tempFilePath)); - out.print(output); - out.close(); - this.setTitle(file); - statusBar.setText(MessageManager.formatMessage( + out.print(output); + out.close(); + AlignFrame.this.setTitle(file); + statusBar.setText(MessageManager.formatMessage( "label.successfully_saved_to_file_in_format", new Object[] { fileName, format.getName() })); - } catch (Exception ex) - { - success = false; - ex.printStackTrace(); - } - - backupfiles.setWriteSuccess(success); - // do the backup file roll and rename the temp file to actual file - success = backupfiles.rollBackupsAndRenameTempFile(); + lastSaveSuccessful = true; + } catch (Exception ex) + { + lastSaveSuccessful = false; + ex.printStackTrace(); + } + if (doBackup) + { + backupfiles.setWriteSuccess(lastSaveSuccessful); + // do the backup file roll and rename the temp file to actual file + lastSaveSuccessful = backupfiles.rollBackupsAndRenameTempFile(); + } + } } - } + }; - if (!success) - { - JvOptionPane.showInternalMessageDialog(this, MessageManager - .formatMessage("label.couldnt_save_file", new Object[] - { fileName }), - MessageManager.getString("label.error_saving_file"), - JvOptionPane.WARNING_MESSAGE); - } - - return success; - } - - private void warningMessage(String warning, String title) - { - if (new jalview.util.Platform().isHeadless()) + /* + * show dialog with export options if applicable; else just do it + */ + if (AlignExportOptions.isNeeded(viewport, format)) { - System.err.println("Warning: " + title + "\nWarning: " + warning); - + AlignExportOptions choices = new AlignExportOptions( + alignPanel.getAlignViewport(), format, options); + choices.setResponseAction(0, outputAction); + choices.setResponseAction(1, cancelAction); + choices.showDialog(); } else { - JvOptionPane.showInternalMessageDialog(this, warning, title, - JvOptionPane.WARNING_MESSAGE); + outputAction.run(); } } /** - * DOCUMENT ME! + * Outputs the alignment to textbox in the requested format, if necessary + * first prompting the user for whether to include hidden regions or + * non-sequence data * - * @param e - * DOCUMENT ME! + * @param fileFormatName */ @Override - protected void outputText_actionPerformed(ActionEvent e) + protected void outputText_actionPerformed(String fileFormatName) { FileFormatI fileFormat = FileFormats.getInstance() - .forName(e.getActionCommand()); - AlignmentExportData exportData = getAlignmentForExport(fileFormat, - viewport, null); - if (exportData.getSettings().isCancelled()) - { - return; - } - CutAndPasteTransfer cap = new CutAndPasteTransfer(); - cap.setForInput(null); - try - { - FileFormatI format = fileFormat; - cap.setText(new FormatAdapter(alignPanel, exportData.getSettings()) - .formatSequences(format, exportData.getAlignment(), - exportData.getOmitHidden(), - exportData.getStartEndPostions(), - viewport.getAlignment().getHiddenColumns())); - Desktop.addInternalFrame(cap, MessageManager - .formatMessage("label.alignment_output_command", new Object[] - { e.getActionCommand() }), 600, 500); - } catch (OutOfMemoryError oom) + .forName(fileFormatName); + AlignExportSettingsI options = new AlignExportSettingsAdapter(false); + Runnable outputAction = new Runnable() { - new OOMWarning("Outputting alignment as " + e.getActionCommand(), - oom); - cap.dispose(); - } - - } - - public static AlignmentExportData getAlignmentForExport( - FileFormatI format, AlignViewportI viewport, - AlignExportSettingI exportSettings) - { - AlignmentI alignmentToExport = null; - AlignExportSettingI settings = exportSettings; - String[] omitHidden = null; - - HiddenSequences hiddenSeqs = viewport.getAlignment() - .getHiddenSequences(); - - alignmentToExport = viewport.getAlignment(); - - boolean hasHiddenSeqs = hiddenSeqs.getSize() > 0; - if (settings == null) - { - settings = new AlignExportSettings(hasHiddenSeqs, - viewport.hasHiddenColumns(), format); - } - // settings.isExportAnnotations(); - - if (viewport.hasHiddenColumns() && !settings.isExportHiddenColumns()) - { - omitHidden = viewport.getViewAsString(false, - settings.isExportHiddenSequences()); - } + @Override + public void run() + { + // todo defer this to inside formatSequences (or later) + AlignmentExportData exportData = viewport + .getAlignExportData(options); + CutAndPasteTransfer cap = new CutAndPasteTransfer(); + cap.setForInput(null); + try + { + FileFormatI format = fileFormat; + cap.setText(new FormatAdapter(alignPanel, options) + .formatSequences(format, exportData.getAlignment(), + exportData.getOmitHidden(), + exportData.getStartEndPostions(), + viewport.getAlignment().getHiddenColumns())); + Desktop.addInternalFrame(cap, MessageManager.formatMessage( + "label.alignment_output_command", new Object[] + { fileFormat.getName() }), 600, 500); + } catch (OutOfMemoryError oom) + { + new OOMWarning("Outputting alignment as " + fileFormat.getName(), + oom); + cap.dispose(); + } + } + }; - int[] alignmentStartEnd = new int[2]; - if (hasHiddenSeqs && settings.isExportHiddenSequences()) + /* + * show dialog with export options if applicable; else just do it + */ + if (AlignExportOptions.isNeeded(viewport, fileFormat)) { - alignmentToExport = hiddenSeqs.getFullAlignment(); + AlignExportOptions choices = new AlignExportOptions( + alignPanel.getAlignViewport(), fileFormat, options); + choices.setResponseAction(0, outputAction); + choices.showDialog(); } else { - alignmentToExport = viewport.getAlignment(); + outputAction.run(); } - alignmentStartEnd = viewport.getAlignment().getHiddenColumns() - .getVisibleStartAndEndIndex(alignmentToExport.getWidth()); - AlignmentExportData ed = new AlignmentExportData(alignmentToExport, - omitHidden, alignmentStartEnd, settings); - return ed; } /** @@@ -1358,33 -1415,39 +1415,39 @@@ } /** - * DOCUMENT ME! + * Creates a PNG image of the alignment and writes it to the given file. If + * the file is null, the user is prompted to choose a file. * - * @param e - * DOCUMENT ME! + * @param f */ @Override public void createPNG(File f) { - alignPanel.makePNG(f); + alignPanel.makeAlignmentImage(TYPE.PNG, f); } /** - * DOCUMENT ME! + * Creates an EPS image of the alignment and writes it to the given file. If + * the file is null, the user is prompted to choose a file. * - * @param e - * DOCUMENT ME! + * @param f */ @Override public void createEPS(File f) { - alignPanel.makeEPS(f); + alignPanel.makeAlignmentImage(TYPE.EPS, f); } + /** + * Creates an SVG image of the alignment and writes it to the given file. If + * the file is null, the user is prompted to choose a file. + * + * @param f + */ @Override public void createSVG(File f) { - alignPanel.makeSVG(f); + alignPanel.makeAlignmentImage(TYPE.SVG, f); } @Override @@@ -1423,24 -1486,24 +1486,24 @@@ @Override public void associatedData_actionPerformed(ActionEvent e) { - // Pick the tree file - JalviewFileChooser chooser = new JalviewFileChooser( + final JalviewFileChooser chooser = new JalviewFileChooser( jalview.bin.Cache.getProperty("LAST_DIRECTORY")); chooser.setFileView(new JalviewFileView()); - chooser.setDialogTitle( - MessageManager.getString("label.load_jalview_annotations")); - chooser.setToolTipText( - MessageManager.getString("label.load_jalview_annotations")); - - int value = chooser.showOpenDialog(null); - - if (value == JalviewFileChooser.APPROVE_OPTION) + String tooltip = MessageManager.getString("label.load_jalview_annotations"); + chooser.setDialogTitle(tooltip); + chooser.setToolTipText(tooltip); + chooser.setResponseHandler(0, new Runnable() { - String choice = chooser.getSelectedFile().getPath(); - jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice); - loadJalviewDataFile(choice, null, null, null); - } + @Override + public void run() + { + String choice = chooser.getSelectedFile().getPath(); + jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice); + loadJalviewDataFile(chooser.getSelectedFile(), null, null, null); + } + }); + chooser.showOpenDialog(this); } /** @@@ -1849,7 -1912,7 +1912,7 @@@ * DOCUMENT ME! */ @Override - protected void copy_actionPerformed(ActionEvent e) + protected void copy_actionPerformed() { if (viewport.getSelectionGroup() == null) { @@@ -1901,7 -1964,7 +1964,7 @@@ Desktop.jalviewClipboard = new Object[] { seqs, viewport.getAlignment().getDataset(), hiddenColumns }; - statusBar.setText(MessageManager.formatMessage( + setStatus(MessageManager.formatMessage( "label.copied_sequences_to_clipboard", new Object[] { Integer.valueOf(seqs.length).toString() })); } @@@ -2024,7 -2087,8 +2087,8 @@@ && Desktop.jalviewClipboard[1] != alignment.getDataset(); // importDs==true instructs us to copy over new dataset sequences from // an existing alignment - Vector newDs = (importDs) ? new Vector() : null; // used to create + Vector newDs = (importDs) ? new Vector<>() : null; // used to + // create // minimum dataset set for (int i = 0; i < sequences.length; i++) @@@ -2163,7 -2227,7 +2227,7 @@@ { // propagate alignment changed. - viewport.getRanges().setEndSeq(alignment.getHeight()); + viewport.getRanges().setEndSeq(alignment.getHeight() - 1); if (annotationAdded) { // Duplicate sequence annotation in all views. @@@ -2318,26 -2382,20 +2382,20 @@@ } /** - * DOCUMENT ME! - * - * @param e - * DOCUMENT ME! + * Action Cut (delete and copy) the selected region */ @Override - protected void cut_actionPerformed(ActionEvent e) + protected void cut_actionPerformed() { - copy_actionPerformed(null); - delete_actionPerformed(null); + copy_actionPerformed(); + delete_actionPerformed(); } /** - * DOCUMENT ME! - * - * @param e - * DOCUMENT ME! + * Performs menu option to Delete the currently selected region */ @Override - protected void delete_actionPerformed(ActionEvent evt) + protected void delete_actionPerformed() { SequenceGroup sg = viewport.getSelectionGroup(); @@@ -2346,52 -2404,56 +2404,56 @@@ return; } + Runnable okAction = new Runnable() + { + @Override + public void run() + { + SequenceI[] cut = sg.getSequences() + .toArray(new SequenceI[sg.getSize()]); + + addHistoryItem(new EditCommand( + MessageManager.getString("label.cut_sequences"), Action.CUT, + cut, sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1, + viewport.getAlignment())); + + viewport.setSelectionGroup(null); + viewport.sendSelection(); + viewport.getAlignment().deleteGroup(sg); + + viewport.firePropertyChange("alignment", null, + viewport.getAlignment().getSequences()); + if (viewport.getAlignment().getHeight() < 1) + { + try + { + AlignFrame.this.setClosed(true); + } catch (Exception ex) + { + } + } + }}; + /* - * If the cut affects all sequences, warn, remove highlighted columns + * If the cut affects all sequences, prompt for confirmation */ - if (sg.getSize() == viewport.getAlignment().getHeight()) - { - boolean isEntireAlignWidth = (((sg.getEndRes() - sg.getStartRes()) - + 1) == viewport.getAlignment().getWidth()) ? true : false; - if (isEntireAlignWidth) - { - int confirm = JvOptionPane.showConfirmDialog(this, - MessageManager.getString("warn.delete_all"), // $NON-NLS-1$ - MessageManager.getString("label.delete_all"), // $NON-NLS-1$ - JvOptionPane.OK_CANCEL_OPTION); - - if (confirm == JvOptionPane.CANCEL_OPTION - || confirm == JvOptionPane.CLOSED_OPTION) - { - return; - } - } - viewport.getColumnSelection().removeElements(sg.getStartRes(), - sg.getEndRes() + 1); - } - SequenceI[] cut = sg.getSequences() - .toArray(new SequenceI[sg.getSize()]); - - addHistoryItem(new EditCommand( - MessageManager.getString("label.cut_sequences"), Action.CUT, - cut, sg.getStartRes(), sg.getEndRes() - sg.getStartRes() + 1, - viewport.getAlignment())); - - viewport.setSelectionGroup(null); - viewport.sendSelection(); - viewport.getAlignment().deleteGroup(sg); - - viewport.firePropertyChange("alignment", null, - viewport.getAlignment().getSequences()); - if (viewport.getAlignment().getHeight() < 1) - { - try - { - this.setClosed(true); - } catch (Exception ex) - { - } - } + boolean wholeHeight = sg.getSize() == viewport.getAlignment().getHeight(); + boolean wholeWidth = (((sg.getEndRes() - sg.getStartRes()) + + 1) == viewport.getAlignment().getWidth()) ? true : false; + if (wholeHeight && wholeWidth) + { + JvOptionPane dialog = JvOptionPane.newOptionDialog(Desktop.desktop); + dialog.setResponseHandler(0, okAction); // 0 = OK_OPTION + Object[] options = new Object[] { MessageManager.getString("action.ok"), + MessageManager.getString("action.cancel") }; + dialog.showDialog(MessageManager.getString("warn.delete_all"), + MessageManager.getString("label.delete_all"), + JvOptionPane.DEFAULT_OPTION, JvOptionPane.PLAIN_MESSAGE, null, + options, options[0]); + } else + { + okAction.run(); + } } /** @@@ -2563,7 -2625,7 +2625,7 @@@ column, viewport.getAlignment()); } - statusBar.setText(MessageManager + setStatus(MessageManager .formatMessage("label.removed_columns", new String[] { Integer.valueOf(trimRegion.getSize()).toString() })); @@@ -2613,7 -2675,7 +2675,7 @@@ addHistoryItem(removeGapCols); - statusBar.setText(MessageManager + setStatus(MessageManager .formatMessage("label.removed_empty_columns", new Object[] { Integer.valueOf(removeGapCols.getSize()).toString() })); @@@ -2974,7 -3036,7 +3036,7 @@@ * @param toggleSeqs * @param toggleCols */ - private void toggleHiddenRegions(boolean toggleSeqs, boolean toggleCols) + protected void toggleHiddenRegions(boolean toggleSeqs, boolean toggleCols) { boolean hide = false; @@@ -3249,15 -3311,42 +3311,42 @@@ @Override public void alignmentProperties() { - JEditorPane editPane = new JEditorPane("text/html", ""); - editPane.setEditable(false); + JComponent pane; StringBuffer contents = new AlignmentProperties(viewport.getAlignment()) + .formatAsHtml(); - editPane.setText( - MessageManager.formatMessage("label.html_content", new Object[] - { contents.toString() })); + String content = MessageManager.formatMessage("label.html_content", + new Object[] + { contents.toString() }); + contents = null; + + if (Platform.isJS()) + { + JLabel textLabel = new JLabel(); + textLabel.setText(content); + textLabel.setBackground(Color.WHITE); + + pane = new JPanel(new BorderLayout()); + ((JPanel) pane).setOpaque(true); + pane.setBackground(Color.WHITE); + ((JPanel) pane).add(textLabel, BorderLayout.NORTH); + } + else + /** + * Java only + * + * @j2sIgnore + */ + { + JEditorPane editPane = new JEditorPane("text/html", ""); + editPane.setEditable(false); + editPane.setText(content); + pane = editPane; + } + JInternalFrame frame = new JInternalFrame(); - frame.getContentPane().add(new JScrollPane(editPane)); + + frame.getContentPane().add(new JScrollPane(pane)); Desktop.addInternalFrame(frame, MessageManager .formatMessage("label.alignment_properties", new Object[] @@@ -3296,7 -3385,7 +3385,7 @@@ { overview.dispose(); alignPanel.setOverviewPanel(null); - }; + } }); if (getKeyListeners().length > 0) { @@@ -3734,7 -3823,7 +3823,7 @@@ { sortByAnnotScore.removeAll(); // almost certainly a quicker way to do this - but we keep it simple - Hashtable scoreSorts = new Hashtable(); + Hashtable scoreSorts = new Hashtable<>(); AlignmentAnnotation aann[]; for (SequenceI sqa : viewport.getAlignment().getSequences()) { @@@ -3747,11 -3836,11 +3836,11 @@@ } } } - Enumeration labels = scoreSorts.keys(); + Enumeration labels = scoreSorts.keys(); while (labels.hasMoreElements()) { addSortByAnnotScoreMenuItem(sortByAnnotScore, - (String) labels.nextElement()); + labels.nextElement()); } sortByAnnotScore.setVisible(scoreSorts.size() > 0); scoreSorts.clear(); @@@ -3918,33 -4007,38 +4007,38 @@@ chooser.setToolTipText( MessageManager.getString("label.load_tree_file")); - int value = chooser.showOpenDialog(null); - - if (value == JalviewFileChooser.APPROVE_OPTION) + chooser.setResponseHandler(0,new Runnable() { - String filePath = chooser.getSelectedFile().getPath(); - Cache.setProperty("LAST_DIRECTORY", filePath); - NewickFile fin = null; - try - { - fin = new NewickFile(filePath, DataSourceType.FILE); - viewport.setCurrentTree(showNewickTree(fin, filePath).getTree()); - } catch (Exception ex) - { - JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(), - MessageManager.getString("label.problem_reading_tree_file"), - JvOptionPane.WARNING_MESSAGE); - ex.printStackTrace(); - } - if (fin != null && fin.hasWarningMessage()) + @Override + public void run() { - JvOptionPane.showMessageDialog(Desktop.desktop, - fin.getWarningMessage(), - MessageManager - .getString("label.possible_problem_with_tree_file"), - JvOptionPane.WARNING_MESSAGE); + String filePath = chooser.getSelectedFile().getPath(); + Cache.setProperty("LAST_DIRECTORY", filePath); + NewickFile fin = null; + try + { + fin = new NewickFile(new FileParse(chooser.getSelectedFile(), + DataSourceType.FILE)); + viewport.setCurrentTree(showNewickTree(fin, filePath).getTree()); + } catch (Exception ex) + { + JvOptionPane.showMessageDialog(Desktop.desktop, ex.getMessage(), + MessageManager + .getString("label.problem_reading_tree_file"), + JvOptionPane.WARNING_MESSAGE); + ex.printStackTrace(); + } + if (fin != null && fin.hasWarningMessage()) + { + JvOptionPane.showMessageDialog(Desktop.desktop, + fin.getWarningMessage(), + MessageManager.getString( + "label.possible_problem_with_tree_file"), + JvOptionPane.WARNING_MESSAGE); + } } - } + }); + chooser.showOpenDialog(this); } public TreePanel showNewickTree(NewickFile nf, String treeTitle) @@@ -4074,14 -4168,14 +4168,14 @@@ // No MSAWS used any more: // Vector msaws = null; // (Vector) // Discoverer.services.get("MsaWS"); - Vector secstrpr = (Vector) Discoverer.services + Vector secstrpr = Discoverer.services .get("SecStrPred"); if (secstrpr != null) { // Add any secondary structure prediction services for (int i = 0, j = secstrpr.size(); i < j; i++) { - final ext.vamsas.ServiceHandle sh = (ext.vamsas.ServiceHandle) secstrpr + final ext.vamsas.ServiceHandle sh = secstrpr .get(i); jalview.ws.WSMenuEntryProviderI impl = jalview.ws.jws1.Discoverer .getServiceClient(sh); @@@ -4191,7 -4285,7 +4285,7 @@@ * * @param webService */ - private void build_urlServiceMenu(JMenu webService) + protected void build_urlServiceMenu(JMenu webService) { // TODO: remove this code when 2.7 is released // DEBUG - alignmentView @@@ -4364,13 -4458,14 +4458,14 @@@ * Try to load a features file onto the alignment. * * @param file - * contents or path to retrieve file + * contents or path to retrieve file or a File object * @param sourceType * access mode of file (see jalview.io.AlignFile) * @return true if features file was parsed correctly. */ - public boolean parseFeaturesFile(String file, DataSourceType sourceType) + public boolean parseFeaturesFile(Object file, DataSourceType sourceType) { + // BH 2018 return avc.parseFeaturesFile(file, sourceType, Cache.getDefault("RELAXEDSEQIDMATCHING", false)); @@@ -4417,8 -4512,9 +4512,9 @@@ // Java's Transferable for native dnd evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); Transferable t = evt.getTransferable(); + final AlignFrame thisaf = this; - final List files = new ArrayList<>(); + final List files = new ArrayList<>(); List protocols = new ArrayList<>(); try @@@ -4446,20 -4542,30 +4542,30 @@@ * Object[] { String,SequenceI} */ ArrayList filesmatched = new ArrayList<>(); - ArrayList filesnotmatched = new ArrayList<>(); + ArrayList filesnotmatched = new ArrayList<>(); for (int i = 0; i < files.size(); i++) { - String file = files.get(i).toString(); + // BH 2018 + Object file = files.get(i); + String fileName = file.toString(); String pdbfn = ""; - DataSourceType protocol = FormatAdapter.checkProtocol(file); + DataSourceType protocol = (file instanceof File + ? DataSourceType.FILE + : FormatAdapter.checkProtocol(fileName)); if (protocol == DataSourceType.FILE) { - File fl = new File(file); + File fl; + if (file instanceof File) { + fl = (File) file; + Platform.cacheFileData(fl); + } else { + fl = new File(fileName); + } pdbfn = fl.getName(); } else if (protocol == DataSourceType.URL) { - URL url = new URL(file); + URL url = new URL(fileName); pdbfn = url.getFile(); } if (pdbfn.length() > 0) @@@ -4481,7 -4587,7 +4587,7 @@@ } if (mtch != null) { - FileFormatI type = null; + FileFormatI type; try { type = new IdentifyFile().identify(file, protocol); @@@ -4528,13 -4634,13 +4634,13 @@@ for (SequenceI toassoc : (SequenceI[]) fm[2]) { PDBEntry pe = new AssociatePdbFileWithSeq() - .associatePdbWithSeq((String) fm[0], + .associatePdbWithSeq(fm[0].toString(), (DataSourceType) fm[1], toassoc, false, Desktop.instance); if (pe != null) { System.err.println("Associated file : " - + ((String) fm[0]) + " with " + + (fm[0].toString()) + " with " + toassoc.getDisplayId(true)); assocfiles++; } @@@ -4551,7 -4657,7 +4657,7 @@@ */ for (Object[] o : filesmatched) { - filesnotmatched.add((String) o[0]); + filesnotmatched.add(o[0]); } } } @@@ -4573,7 -4679,7 +4679,7 @@@ { return; } - for (String fn : filesnotmatched) + for (Object fn : filesnotmatched) { loadJalviewDataFile(fn, null, null, null); } @@@ -4600,9 -4706,10 +4706,10 @@@ * @param file * either a filename or a URL string. */ - public void loadJalviewDataFile(String file, DataSourceType sourceType, + public void loadJalviewDataFile(Object file, DataSourceType sourceType, FileFormatI format, SequenceI assocSeq) { + // BH 2018 was String file try { if (sourceType == null) @@@ -4633,7 -4740,7 +4740,7 @@@ changeColour( new TCoffeeColourScheme(viewport.getAlignment())); isAnnotation = true; - statusBar.setText(MessageManager.getString( + setStatus(MessageManager.getString( "label.successfully_pasted_tcoffee_scores_to_alignment")); } else @@@ -4676,7 -4783,7 +4783,7 @@@ new FileParse(file, sourceType)); sm.parse(); // todo: i18n this message - statusBar.setText(MessageManager.formatMessage( + setStatus(MessageManager.formatMessage( "label.successfully_loaded_matrix", sm.getMatrixName())); } @@@ -4825,8 -4932,8 +4932,8 @@@ if (e.isPopupTrigger()) { String msg = MessageManager.getString("label.enter_view_name"); - String reply = JvOptionPane.showInternalInputDialog(this, msg, msg, - JvOptionPane.QUESTION_MESSAGE); + String ttl = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex()); + String reply = JvOptionPane.showInputDialog(msg, ttl); if (reply != null) { @@@ -4941,7 -5048,7 +5048,7 @@@ trimrs.setSelected(trimrs.isSelected()); Cache.setProperty(DBRefFetcher.TRIM_RETRIEVED_SEQUENCES, Boolean.valueOf(trimrs.isSelected()).toString()); - }; + } }); rfetch.add(trimrs); JMenuItem fetchr = new JMenuItem( @@@ -4988,22 -5095,19 +5095,19 @@@ }); rfetch.add(fetchr); - final AlignFrame me = this; new Thread(new Runnable() { @Override public void run() { final jalview.ws.SequenceFetcher sf = jalview.gui.SequenceFetcher - .getSequenceFetcherSingleton(me); + .getSequenceFetcherSingleton(); javax.swing.SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - String[] dbclasses = sf.getOrderedSupportedSources(); - // sf.getDbInstances(jalview.ws.dbsources.DasSequenceSource.class); - // jalview.util.QuickSort.sort(otherdb, otherdb); + String[] dbclasses = sf.getNonAlignmentSources(); List otherdb; JMenu dfetch = new JMenu(); JMenu ifetch = new JMenu(); @@@ -5020,12 -5124,6 +5124,6 @@@ { continue; } - // List dbs=otherdb; - // otherdb=new ArrayList(); - // for (DbSourceProxy db:dbs) - // { - // if (!db.isA(DBRefSource.ALIGNMENTDB) - // } if (mname == null) { mname = "From " + dbclass; @@@ -5680,16 -5778,19 +5778,19 @@@ chooser.setFileView(new JalviewFileView()); chooser.setDialogTitle(MessageManager.getString("label.load_vcf_file")); chooser.setToolTipText(MessageManager.getString("label.load_vcf_file")); - - int value = chooser.showOpenDialog(null); - - if (value == JalviewFileChooser.APPROVE_OPTION) + final AlignFrame us = this; + chooser.setResponseHandler(0, new Runnable() { - String choice = chooser.getSelectedFile().getPath(); - Cache.setProperty("LAST_DIRECTORY", choice); - SequenceI[] seqs = viewport.getAlignment().getSequencesArray(); - new VCFLoader(choice).loadVCF(seqs, this); - } + @Override + public void run() + { + String choice = chooser.getSelectedFile().getPath(); + Cache.setProperty("LAST_DIRECTORY", choice); + SequenceI[] seqs = viewport.getAlignment().getSequencesArray(); + new VCFLoader(choice).loadVCF(seqs, us); + } + }); + chooser.showOpenDialog(null); } diff --combined src/jalview/gui/AppJmol.java index 0610239,e13df4a..4058cda --- a/src/jalview/gui/AppJmol.java +++ b/src/jalview/gui/AppJmol.java @@@ -20,36 -20,38 +20,37 @@@ */ package jalview.gui; -import jalview.bin.Cache; -import jalview.datamodel.AlignmentI; -import jalview.datamodel.PDBEntry; -import jalview.datamodel.SequenceI; -import jalview.gui.ImageExporter.ImageWriterI; -import jalview.gui.StructureViewer.ViewerType; -import jalview.structures.models.AAStructureBindingModel; -import jalview.util.BrowserLauncher; -import jalview.util.ImageMaker; -import jalview.util.MessageManager; -import jalview.util.Platform; -import jalview.ws.dbsources.Pdb; - import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Rectangle; import java.io.File; import java.util.ArrayList; import java.util.List; -import java.util.Vector; -import javax.swing.JCheckBoxMenuItem; import javax.swing.JPanel; import javax.swing.JSplitPane; import javax.swing.SwingUtilities; import javax.swing.event.InternalFrameAdapter; import javax.swing.event.InternalFrameEvent; +import jalview.api.AlignmentViewPanel; +import jalview.bin.Cache; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.PDBEntry; +import jalview.datamodel.SequenceI; ++import jalview.gui.ImageExporter.ImageWriterI; +import jalview.gui.StructureViewer.ViewerType; +import jalview.structure.StructureCommand; +import jalview.structures.models.AAStructureBindingModel; +import jalview.util.BrowserLauncher; +import jalview.util.ImageMaker; +import jalview.util.MessageManager; +import jalview.util.Platform; +import jalview.ws.dbsources.Pdb; + public class AppJmol extends StructureViewerBase { // ms to wait for Jmol to load files @@@ -154,6 -156,14 +155,6 @@@ .getString("label.let_jmol_manage_structure_colours")); } - IProgressIndicator progressBar = null; - - @Override - protected IProgressIndicator getIProgressIndicator() - { - return progressBar; - } - /** * display a single PDB structure in a new Jmol view * @@@ -165,7 -175,7 +166,7 @@@ public AppJmol(PDBEntry pdbentry, SequenceI[] seq, String[] chains, final AlignmentPanel ap) { - progressBar = ap.alignFrame; + setProgressIndicator(ap.alignFrame); openNewJmol(ap, alignAddedStructures, new PDBEntry[] { pdbentry }, new SequenceI[][] @@@ -176,17 -186,14 +177,17 @@@ PDBEntry[] pdbentrys, SequenceI[][] seqs) { - progressBar = ap.alignFrame; + setProgressIndicator(ap.alignFrame); jmb = new AppJmolBinding(this, ap.getStructureSelectionManager(), pdbentrys, seqs, null); addAlignmentPanel(ap); useAlignmentPanelForColourbyseq(ap); alignAddedStructures = alignAdded; - useAlignmentPanelForSuperposition(ap); + if (pdbentrys.length > 1) + { + useAlignmentPanelForSuperposition(ap); + } jmb.setColourBySequence(true); setSize(400, 400); // probably should be a configurable/dynamic default here @@@ -249,12 -256,47 +250,12 @@@ { command = ""; } - jmb.evalStateCommand(command); - jmb.evalStateCommand("set hoverDelay=0.1"); + jmb.executeCommand(new StructureCommand(command), false); + jmb.executeCommand(new StructureCommand("set hoverDelay=0.1"), false); jmb.setFinishedInit(true); } @Override - void showSelectedChains() - { - Vector toshow = new Vector<>(); - for (int i = 0; i < chainMenu.getItemCount(); i++) - { - if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem) - { - JCheckBoxMenuItem item = (JCheckBoxMenuItem) chainMenu.getItem(i); - if (item.isSelected()) - { - toshow.addElement(item.getText()); - } - } - } - jmb.centerViewer(toshow); - } - - @Override - public void closeViewer(boolean closeExternalViewer) - { - // Jmol does not use an external viewer - if (jmb != null) - { - jmb.closeViewer(); - } - setAlignmentPanel(null); - _aps.clear(); - _alignwith.clear(); - _colourwith.clear(); - // TODO: check for memory leaks where instance isn't finalised because jmb - // holds a reference to the window - jmb = null; - } - - @Override public void run() { _started = true; @@@ -302,6 -344,8 +303,8 @@@ } catch (Exception ex) { Cache.log.error("Couldn't open Jmol viewer!", ex); + ex.printStackTrace(); + return; } } else @@@ -310,20 -354,23 +313,23 @@@ cmd.append("loadingJalviewdata=true\nload APPEND "); cmd.append(filesString); cmd.append("\nloadingJalviewdata=null"); - final String command = cmd.toString(); + final StructureCommand command = new StructureCommand(cmd.toString()); lastnotify = jmb.getLoadNotifiesHandled(); try { - jmb.evalStateCommand(command); + jmb.executeCommand(command, false); } catch (OutOfMemoryError oomerror) { new OOMWarning("When trying to add structures to the Jmol viewer!", oomerror); Cache.log.debug("File locations are " + filesString); + return; } catch (Exception ex) { Cache.log.error("Couldn't add files to Jmol viewer!", ex); + ex.printStackTrace(); + return; } } @@@ -356,7 -403,7 +362,7 @@@ } // refresh the sequence colours for the new structure(s) - for (AlignmentPanel ap : _colourwith) + for (AlignmentViewPanel ap : _colourwith) { jmb.updateColours(ap); } @@@ -378,7 -425,7 +384,7 @@@ @Override public void run() { - if (jmb.viewer.isScriptExecuting()) + if (jmb.jmolViewer.isScriptExecuting()) { SwingUtilities.invokeLater(this); try @@@ -391,7 -438,7 +397,7 @@@ } else { - alignStructs_withAllAlignPanels(); + alignStructsWithAllAlignPanels(); } } }); @@@ -429,9 -476,12 +435,9 @@@ AlignmentI pdbseq = null; pdbid = jmb.getPdbEntry(pi).getId(); long hdl = pdbid.hashCode() - System.currentTimeMillis(); - if (progressBar != null) - { - progressBar.setProgressBar(MessageManager - .formatMessage("status.fetching_pdb", new String[] - { pdbid }), hdl); - } + setProgressMessage(MessageManager + .formatMessage("status.fetching_pdb", new String[] + { pdbid }), hdl); try { pdbseq = pdbclient.getSequenceRecords(pdbid); @@@ -444,8 -494,12 +450,8 @@@ errormsgs.append("'").append(pdbid).append("'"); } finally { - if (progressBar != null) - { - progressBar.setProgressBar( - MessageManager.getString("label.state_completed"), - hdl); - } + setProgressMessage( + MessageManager.getString("label.state_completed"), hdl); } if (pdbseq != null) { @@@ -502,67 -556,46 +508,48 @@@ return files; } + /** + * Outputs the Jmol viewer image as an image file, after prompting the user to + * choose a file and (for EPS) choice of Text or Lineart character rendering + * (unless a preference for this is set) + * + * @param type + */ + @Override - public void eps_actionPerformed() - { - makePDBImage(ImageMaker.TYPE.EPS); - } - - @Override - public void png_actionPerformed() - { - makePDBImage(ImageMaker.TYPE.PNG); - } - - void makePDBImage(ImageMaker.TYPE type) + public void makePDBImage(ImageMaker.TYPE type) { int width = getWidth(); int height = getHeight(); - - ImageMaker im; - - if (type == ImageMaker.TYPE.PNG) + ImageWriterI writer = new ImageWriterI() { - im = new ImageMaker(this, ImageMaker.TYPE.PNG, - "Make PNG image from view", - width, height, null, null, null, 0, false); - } - else if (type == ImageMaker.TYPE.EPS) - { - im = new ImageMaker(this, ImageMaker.TYPE.EPS, - "Make EPS file from view", - width, height, null, this.getTitle(), null, 0, false); - } - else - { - im = new jalview.util.ImageMaker(this, - ImageMaker.TYPE.SVG, "Make SVG file from PCA", - width, height, null, this.getTitle(), null, 0, false); - } - - if (im.getGraphics() != null) - { - jmb.jmolViewer.renderScreenImage(im.getGraphics(), width, height); - im.writeImage(); - } + @Override + public void exportImage(Graphics g) throws Exception + { - jmb.viewer.renderScreenImage(g, width, height); ++ jmb.jmolViewer.renderScreenImage(g, width, height); + } + }; + String view = MessageManager.getString("action.view").toLowerCase(); + ImageExporter exporter = new ImageExporter(writer, - jmb.getIProgressIndicator(), type, getTitle()); ++ getProgressIndicator(), type, getTitle()); + exporter.doExport(null, this, width, height, view); } @Override - public void showHelp_actionPerformed(ActionEvent actionEvent) + public void showHelp_actionPerformed() { try { - BrowserLauncher - .openURL("http://jmol.sourceforge.net/docs/JmolUserGuide/"); + BrowserLauncher // BH 2018 + .openURL("http://wiki.jmol.org");//http://jmol.sourceforge.net/docs/JmolUserGuide/"); } catch (Exception ex) { + System.err.println("Show Jmol help failed with: " + ex.getMessage()); } } + @Override public void showConsole(boolean showConsole) { - if (showConsole) { if (splitPane == null) @@@ -628,7 -661,7 +615,7 @@@ } } } - else if (jmb == null || jmb.viewer == null || !jmb.isFinishedInit()) + else if (jmb == null || jmb.jmolViewer == null || !jmb.isFinishedInit()) { g.setColor(Color.black); g.fillRect(0, 0, currentSize.width, currentSize.height); @@@ -639,7 -672,7 +626,7 @@@ } else { - jmb.viewer.renderScreenImage(g, currentSize.width, + jmb.jmolViewer.renderScreenImage(g, currentSize.width, currentSize.height); } } @@@ -652,6 -685,12 +639,6 @@@ } @Override - public String getStateInfo() - { - return jmb == null ? null : jmb.viewer.getStateInfo(); - } - - @Override public ViewerType getViewerType() { return ViewerType.JMOL; diff --combined src/jalview/gui/AppJmolBinding.java index 34ff7b3,75b98bc..3298509 --- a/src/jalview/gui/AppJmolBinding.java +++ b/src/jalview/gui/AppJmolBinding.java @@@ -20,18 -20,6 +20,16 @@@ */ package jalview.gui; +import java.awt.Container; +import java.io.File; - import java.io.FileWriter; - import java.io.IOException; ++import java.util.List; +import java.util.Map; + +import javax.swing.JComponent; + +import org.jmol.api.JmolAppConsoleInterface; - import org.jmol.java.BS; +import org.openscience.jmol.app.jmolpanel.console.AppConsole; + import jalview.api.AlignmentViewPanel; import jalview.api.structures.JalviewStructureDisplayI; import jalview.bin.Cache; @@@ -40,15 -28,33 +38,17 @@@ import jalview.datamodel.SequenceI import jalview.ext.jmol.JalviewJmolBinding; import jalview.io.DataSourceType; import jalview.structure.StructureSelectionManager; + import jalview.util.Platform; - -import java.awt.Container; -import java.io.File; -import java.util.List; -import java.util.Map; - -import org.jmol.api.JmolAppConsoleInterface; - + import javajs.util.BS; public class AppJmolBinding extends JalviewJmolBinding { - protected AppJmol appJmolWindow; - public AppJmolBinding(AppJmol appJmol, StructureSelectionManager sSm, PDBEntry[] pdbentry, SequenceI[][] sequenceIs, DataSourceType protocol) { super(sSm, pdbentry, sequenceIs, protocol); - appJmolWindow = appJmol; - } - - @Override - protected IProgressIndicator getIProgressIndicator() - { - return appJmolWindow.progressBar; + setViewer(appJmol); } @Override @@@ -99,14 -105,30 +99,15 @@@ @Override public void run() { - appJmolWindow.updateTitleAndMenus(); - // initiates a colourbySequence - // via seqColour_ActionPerformed. - appJmolWindow.revalidate(); + JalviewStructureDisplayI theViewer = getViewer(); ++ // invokes colourbySequence() via seqColour_ActionPerformed() + theViewer.updateTitleAndMenus(); + ((JComponent) theViewer).revalidate(); } }); } @Override - public void updateColours(Object source) - { - AlignmentPanel ap = (AlignmentPanel) source; - // ignore events from panels not used to colour this view - if (!appJmolWindow.isUsedforcolourby(ap)) - { - return; - } - if (!isLoadingFromArchive()) - { - colourBySequence(ap); - } - } - - @Override public void notifyScriptTermination(String strStatus, int msWalltime) { // todo - script termination doesn't happen ? @@@ -130,26 -152,35 +131,28 @@@ @Override public void selectionChanged(BS arg0) { - // TODO Auto-generated method stub - - } - - @Override - public void refreshPdbEntries() - { - // TODO Auto-generated method stub - } @Override public void showConsole(boolean b) { - appJmolWindow.showConsole(b); + getViewer().showConsole(b); } @Override protected JmolAppConsoleInterface createJmolConsole( Container consolePanel, String buttonsToShow) { - viewer.setJmolCallbackListener(this); - return null;//BH can't do this yet. new AppConsole(viewer, consolePanel, buttonsToShow); + jmolViewer.setJmolCallbackListener(this); - return new AppConsole(jmolViewer, consolePanel, buttonsToShow); ++ // BH comment: can't do this yet [for JS only, or generally?] ++ return Platform.isJS() ? null ++ : new AppConsole(jmolViewer, consolePanel, buttonsToShow); } @Override protected void releaseUIResources() { - appJmolWindow = null; + setViewer(null); closeConsole(); } @@@ -158,7 -189,7 +161,7 @@@ { if (svl instanceof SeqPanel) { - appJmolWindow.removeAlignmentPanel(((SeqPanel) svl).ap); + getViewer().removeAlignmentPanel(((SeqPanel) svl).ap); } } @@@ -169,31 -200,37 +172,16 @@@ return null; } - /** - * Overrides the default method to save a session to file, in order to - * guarantee it is done synchronously. Jmol command 'write STATE path' would - * execute asynchronously, so instead we get the state and write it directly - * here. - */ -- @Override - protected void saveSession(File f) - public JalviewStructureDisplayI getViewer() - { - return appJmolWindow; - } - - @Override - public jalview.api.FeatureRenderer getFeatureRenderer( - AlignmentViewPanel alignment) - { - AlignmentPanel ap = (alignment == null) - ? appJmolWindow.getAlignmentPanel() - : (AlignmentPanel) alignment; - if (ap.av.isShowSequenceFeatures()) - { - return ap.av.getAlignPanel().getSeqPanel().seqCanvas.fr; - } - - return null; - } - + @SuppressWarnings("unused") + public void cacheFiles(List files) { - String state = jmolViewer.getStateInfo(); - if (state != null) + if (files == null) { - try - { - FileWriter fw = new FileWriter(f); - fw.write(state); - fw.close(); - } catch (IOException e) - { - Cache.log.error("Error writing Jmol state: " + e.toString()); - } + return; } - else + for (File f : files) { - Cache.log.error("Error requesting Jmol state to save"); + Platform.cacheFileData(f); } } } diff --combined src/jalview/gui/ChimeraViewFrame.java index 8fcea0c,c6d6e97..45ab9a9 --- a/src/jalview/gui/ChimeraViewFrame.java +++ b/src/jalview/gui/ChimeraViewFrame.java @@@ -20,36 -20,43 +20,37 @@@ */ package jalview.gui; -import jalview.api.FeatureRenderer; -import jalview.bin.Cache; -import jalview.datamodel.AlignmentI; -import jalview.datamodel.PDBEntry; -import jalview.datamodel.SequenceI; -import jalview.ext.rbvi.chimera.ChimeraCommands; -import jalview.ext.rbvi.chimera.JalviewChimeraBinding; -import jalview.gui.StructureViewer.ViewerType; -import jalview.io.DataSourceType; -import jalview.io.StructureFile; -import jalview.structures.models.AAStructureBindingModel; -import jalview.util.BrowserLauncher; -import jalview.util.ImageMaker.TYPE; -import jalview.util.MessageManager; -import jalview.util.Platform; -import jalview.ws.dbsources.Pdb; - import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Random; -import javax.swing.JCheckBoxMenuItem; import javax.swing.JInternalFrame; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.event.InternalFrameAdapter; import javax.swing.event.InternalFrameEvent; +import jalview.api.AlignmentViewPanel; +import jalview.api.FeatureRenderer; +import jalview.bin.Cache; +import jalview.datamodel.PDBEntry; +import jalview.datamodel.SequenceI; +import jalview.ext.rbvi.chimera.JalviewChimeraBinding; +import jalview.gui.StructureViewer.ViewerType; +import jalview.io.DataSourceType; +import jalview.io.StructureFile; +import jalview.structures.models.AAStructureBindingModel; +import jalview.util.BrowserLauncher; ++import jalview.util.ImageMaker.TYPE; +import jalview.util.MessageManager; +import jalview.util.Platform; + /** * GUI elements for handling an external chimera display * @@@ -60,6 -67,8 +61,6 @@@ public class ChimeraViewFrame extends S { private JalviewChimeraBinding jmb; - private IProgressIndicator progressBar = null; - /* * Path to Chimera session file. This is set when an open Jalview/Chimera * session is saved, or on restore from a Jalview project (if it holds the @@@ -67,6 -76,8 +68,6 @@@ */ private String chimeraSessionFile = null; - private Random random = new Random(); - private int myWidth = 500; private int myHeight = 150; @@@ -81,6 -92,11 +82,6 @@@ viewerActionMenu.setText(MessageManager.getString("label.chimera")); - viewerColour - .setText(MessageManager.getString("label.colour_with_chimera")); - viewerColour.setToolTipText(MessageManager - .getString("label.let_chimera_manage_structure_colours")); - helpItem.setText(MessageManager.getString("label.chimera_help")); savemenu.setVisible(false); // not yet implemented viewMenu.add(fitToWindow); @@@ -123,21 -139,34 +124,21 @@@ */ protected void buildAttributesMenu(JMenu attributesMenu) { - List atts = jmb.sendChimeraCommand("list resattr", true); - if (atts == null) - { - return; - } + List atts = jmb.getChimeraAttributes(); attributesMenu.removeAll(); Collections.sort(atts); - for (String att : atts) + for (String attName : atts) { - final String attName = att.split(" ")[1]; - - /* - * ignore 'jv_*' attributes, as these are Jalview features that have - * been transferred to residue attributes in Chimera! - */ - if (!attName.startsWith(ChimeraCommands.NAMESPACE_PREFIX)) + JMenuItem menuItem = new JMenuItem(attName); + menuItem.addActionListener(new ActionListener() { - JMenuItem menuItem = new JMenuItem(attName); - menuItem.addActionListener(new ActionListener() + @Override + public void actionPerformed(ActionEvent e) { - @Override - public void actionPerformed(ActionEvent e) - { - getChimeraAttributes(attName); - } - }); - attributesMenu.add(menuItem); - } + getChimeraAttributes(attName); + } + }); + attributesMenu.add(menuItem); } } @@@ -155,9 -184,9 +156,9 @@@ /** * Send a command to Chimera to create residue attributes for Jalview features *

- * The syntax is: setattr r + * The syntax is: setattr r <attName> <attValue> <atomSpec> *

- * For example: setattr r jv:chain "Ferredoxin-1, Chloroplastic" #0:94.A + * For example: setattr r jv_chain "Ferredoxin-1, Chloroplastic" #0:94.A */ protected void sendFeaturesToChimera() { @@@ -189,9 -218,9 +190,9 @@@ */ protected void createProgressBar() { - if (progressBar == null) + if (getProgressIndicator() == null) { - progressBar = new ProgressBar(statusPanel, statusBar); + setProgressIndicator(new ProgressBar(statusPanel, statusBar)); } } @@@ -199,7 -228,8 +200,7 @@@ SequenceI[][] seqs) { createProgressBar(); - jmb = new JalviewChimeraBindingModel(this, - ap.getStructureSelectionManager(), pdbentrys, seqs, null); + jmb = newBindingModel(ap, pdbentrys, seqs); addAlignmentPanel(ap); useAlignmentPanelForColourbyseq(ap); @@@ -227,13 -257,6 +228,13 @@@ } + protected JalviewChimeraBindingModel newBindingModel(AlignmentPanel ap, + PDBEntry[] pdbentrys, SequenceI[][] seqs) + { + return new JalviewChimeraBindingModel(this, + ap.getStructureSelectionManager(), pdbentrys, seqs, null); + } + /** * Create a new viewer from saved session state data including Chimera session * file @@@ -314,8 -337,7 +315,8 @@@ if (!jmb.launchChimera()) { JvOptionPane.showMessageDialog(Desktop.desktop, - MessageManager.getString("label.chimera_failed"), + MessageManager.formatMessage("label.open_viewer_failed", + getViewerName()), MessageManager.getString("label.error_loading_file"), JvOptionPane.ERROR_MESSAGE); this.dispose(); @@@ -336,6 -358,71 +337,6 @@@ } /** - * Show only the selected chain(s) in the viewer - */ - @Override - void showSelectedChains() - { - List toshow = new ArrayList<>(); - for (int i = 0; i < chainMenu.getItemCount(); i++) - { - if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem) - { - JCheckBoxMenuItem item = (JCheckBoxMenuItem) chainMenu.getItem(i); - if (item.isSelected()) - { - toshow.add(item.getText()); - } - } - } - jmb.showChains(toshow); - } - - /** - * Close down this instance of Jalview's Chimera viewer, giving the user the - * option to close the associated Chimera window (process). They may wish to - * keep it open until they have had an opportunity to save any work. - * - * @param closeChimera - * if true, close any linked Chimera process; if false, prompt first - */ - @Override - public void closeViewer(boolean closeChimera) - { - if (jmb != null && jmb.isChimeraRunning()) - { - if (!closeChimera) - { - String prompt = MessageManager - .formatMessage("label.confirm_close_chimera", new Object[] - { jmb.getViewerTitle(getViewerName(), false) }); - prompt = JvSwingUtils.wrapTooltip(true, prompt); - int confirm = JvOptionPane.showConfirmDialog(this, prompt, - MessageManager.getString("label.close_viewer"), - JvOptionPane.YES_NO_CANCEL_OPTION); - /* - * abort closure if user hits escape or Cancel - */ - if (confirm == JvOptionPane.CANCEL_OPTION - || confirm == JvOptionPane.CLOSED_OPTION) - { - return; - } - closeChimera = confirm == JvOptionPane.YES_OPTION; - } - jmb.closeViewer(closeChimera); - } - setAlignmentPanel(null); - _aps.clear(); - _alignwith.clear(); - _colourwith.clear(); - // TODO: check for memory leaks where instance isn't finalised because jmb - // holds a reference to the window - jmb = null; - dispose(); - } - - /** * Open any newly added PDB structures in Chimera, having first fetched data * from PDB (if not already saved). */ @@@ -463,8 -550,8 +464,8 @@@ pdb = jmb.getSsm().setMapping(jmb.getSequence()[pos], jmb.getChains()[pos], pe.getFile(), protocol, - progressBar); - stashFoundChains(pdb, pe.getFile()); + getProgressIndicator()); + jmb.stashFoundChains(pdb, pe.getFile()); } catch (OutOfMemoryError oomerror) { @@@ -498,7 -585,7 +499,7 @@@ } // refresh the sequence colours for the new structure(s) - for (AlignmentPanel ap : _colourwith) + for (AlignmentViewPanel ap : _colourwith) { jmb.updateColours(ap); } @@@ -510,7 -597,7 +511,7 @@@ @Override public void run() { - alignStructs_withAllAlignPanels(); + alignStructsWithAllAlignPanels(); } }).start(); } @@@ -520,31 -607,121 +521,24 @@@ worker = null; } - /** - * Fetch PDB data and save to a local file. Returns the full path to the file, - * or null if fetch fails. TODO: refactor to common with Jmol ? duplication - * - * @param processingEntry - * @return - * @throws Exception - */ - - private void stashFoundChains(StructureFile pdb, String file) - { - for (int i = 0; i < pdb.getChains().size(); i++) - { - String chid = new String( - pdb.getId() + ":" + pdb.getChains().elementAt(i).id); - jmb.getChainNames().add(chid); - jmb.getChainFile().put(chid, file); - } - } - - private String fetchPdbFile(PDBEntry processingEntry) throws Exception - { - String filePath = null; - Pdb pdbclient = new Pdb(); - AlignmentI pdbseq = null; - String pdbid = processingEntry.getId(); - long handle = System.currentTimeMillis() - + Thread.currentThread().hashCode(); - - /* - * Write 'fetching PDB' progress on AlignFrame as we are not yet visible - */ - String msg = MessageManager.formatMessage("status.fetching_pdb", - new Object[] - { pdbid }); - getAlignmentPanel().alignFrame.setProgressBar(msg, handle); - // long hdl = startProgressBar(MessageManager.formatMessage( - // "status.fetching_pdb", new Object[] - // { pdbid })); - try - { - pdbseq = pdbclient.getSequenceRecords(pdbid); - } catch (OutOfMemoryError oomerror) - { - new OOMWarning("Retrieving PDB id " + pdbid, oomerror); - } finally - { - msg = pdbid + " " + MessageManager.getString("label.state_completed"); - getAlignmentPanel().alignFrame.setProgressBar(msg, handle); - // stopProgressBar(msg, hdl); - } - /* - * If PDB data were saved and are not invalid (empty alignment), return the - * file path. - */ - if (pdbseq != null && pdbseq.getHeight() > 0) - { - // just use the file name from the first sequence's first PDBEntry - filePath = new File(pdbseq.getSequenceAt(0).getAllPDBEntries() - .elementAt(0).getFile()).getAbsolutePath(); - processingEntry.setFile(filePath); - } - return filePath; - } - - /** - * Convenience method to update the progress bar if there is one. Be sure to - * call stopProgressBar with the returned handle to remove the message. - * - * @param msg - * @param handle - */ - public long startProgressBar(String msg) - { - // TODO would rather have startProgress/stopProgress as the - // IProgressIndicator interface - long tm = random.nextLong(); - if (progressBar != null) - { - progressBar.setProgressBar(msg, tm); - } - return tm; - } - - /** - * End the progress bar with the specified handle, leaving a message (if not - * null) on the status bar - * - * @param msg - * @param handle - */ - public void stopProgressBar(String msg, long handle) - { - if (progressBar != null) - { - progressBar.setProgressBar(msg, handle); - } - } - @Override - public void eps_actionPerformed() + public void makePDBImage(TYPE imageType) { - throw new Error(MessageManager - .getString("error.eps_generation_not_implemented")); - } - - @Override - public void png_actionPerformed() - { - throw new Error(MessageManager - .getString("error.png_generation_not_implemented")); + throw new UnsupportedOperationException( + "Image export for Chimera is not implemented"); } @Override - public void showHelp_actionPerformed(ActionEvent actionEvent) + public void showHelp_actionPerformed() { try { - BrowserLauncher - .openURL("https://www.cgl.ucsf.edu/chimera/docs/UsersGuide"); + String url = jmb.getHelpURL(); + BrowserLauncher.openURL(url); } catch (IOException ex) { + System.err + .println("Show Chimera help failed with: " + ex.getMessage()); } } @@@ -554,6 -731,76 +548,6 @@@ return jmb; } - /** - * Ask Chimera to save its session to the designated file path, or to a - * temporary file if the path is null. Returns the file path if successful, - * else null. - * - * @param filepath - * @see getStateInfo - */ - protected String saveSession(String filepath) - { - String pathUsed = filepath; - try - { - if (pathUsed == null) - { - File tempFile = File.createTempFile("chimera", ".py"); - tempFile.deleteOnExit(); - pathUsed = tempFile.getPath(); - } - boolean result = jmb.saveSession(pathUsed); - if (result) - { - this.chimeraSessionFile = pathUsed; - return pathUsed; - } - } catch (IOException e) - { - } - return null; - } - - /** - * Returns a string representing the state of the Chimera session. This is - * done by requesting Chimera to save its session to a temporary file, then - * reading the file contents. Returns an empty string on any error. - */ - @Override - public String getStateInfo() - { - String sessionFile = saveSession(null); - if (sessionFile == null) - { - return ""; - } - InputStream is = null; - try - { - File f = new File(sessionFile); - byte[] bytes = new byte[(int) f.length()]; - is = new FileInputStream(sessionFile); - is.read(bytes); - return new String(bytes); - } catch (IOException e) - { - return ""; - } finally - { - if (is != null) - { - try - { - is.close(); - } catch (IOException e) - { - // ignore - } - } - } - } - @Override protected void fitToWindow_actionPerformed() { @@@ -571,4 -818,26 +565,4 @@@ { return "Chimera"; } - - /** - * Sends commands to align structures according to associated alignment(s). - * - * @return - */ - @Override - protected String alignStructs_withAllAlignPanels() - { - String reply = super.alignStructs_withAllAlignPanels(); - if (reply != null) - { - statusBar.setText("Superposition failed: " + reply); - } - return reply; - } - - @Override - protected IProgressIndicator getIProgressIndicator() - { - return progressBar; - } } diff --combined src/jalview/gui/Preferences.java index 6fa63fe,04b83a3..c4dcc6c --- a/src/jalview/gui/Preferences.java +++ b/src/jalview/gui/Preferences.java @@@ -20,6 -20,29 +20,6 @@@ */ package jalview.gui; -import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder; -import jalview.bin.Cache; -import jalview.gui.Help.HelpId; -import jalview.gui.StructureViewer.ViewerType; -import jalview.io.BackupFiles; -import jalview.io.BackupFilesPresetEntry; -import jalview.io.FileFormatI; -import jalview.io.JalviewFileChooser; -import jalview.io.JalviewFileView; -import jalview.jbgui.GPreferences; -import jalview.jbgui.GSequenceLink; -import jalview.schemes.ColourSchemeI; -import jalview.schemes.ColourSchemes; -import jalview.schemes.ResidueColourScheme; -import jalview.urls.UrlLinkTableModel; -import jalview.urls.api.UrlProviderFactoryI; -import jalview.urls.api.UrlProviderI; -import jalview.urls.desktop.DesktopUrlProviderFactory; -import jalview.util.MessageManager; -import jalview.util.Platform; -import jalview.util.UrlConstants; -import jalview.ws.sifts.SiftsSettings; - import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; @@@ -33,7 -56,7 +33,7 @@@ import java.util.ArrayList import java.util.List; import javax.help.HelpSetException; - import javax.swing.JColorChooser; + import javax.swing.JComboBox; import javax.swing.JFileChooser; import javax.swing.JInternalFrame; import javax.swing.JPanel; @@@ -51,29 -74,6 +51,29 @@@ import javax.swing.table.TableModel import javax.swing.table.TableRowSorter; import ext.edu.ucsf.rbvi.strucviz2.StructureManager; +import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder; +import jalview.bin.Cache; +import jalview.ext.pymol.PymolManager; +import jalview.gui.Help.HelpId; +import jalview.gui.StructureViewer.ViewerType; +import jalview.io.BackupFiles; +import jalview.io.BackupFilesPresetEntry; +import jalview.io.FileFormatI; +import jalview.io.JalviewFileChooser; +import jalview.io.JalviewFileView; +import jalview.jbgui.GPreferences; +import jalview.jbgui.GSequenceLink; +import jalview.schemes.ColourSchemeI; +import jalview.schemes.ColourSchemes; +import jalview.schemes.ResidueColourScheme; +import jalview.urls.UrlLinkTableModel; +import jalview.urls.api.UrlProviderFactoryI; +import jalview.urls.api.UrlProviderI; +import jalview.urls.desktop.DesktopUrlProviderFactory; +import jalview.util.MessageManager; +import jalview.util.Platform; +import jalview.util.UrlConstants; +import jalview.ws.sifts.SiftsSettings; /** * DOCUMENT ME! @@@ -105,10 -105,6 +105,10 @@@ public class Preferences extends GPrefe public static final String CHIMERA_PATH = "CHIMERA_PATH"; + public static final String CHIMERAX_PATH = "CHIMERAX_PATH"; + + public static final String PYMOL_PATH = "PYMOL_PATH"; + public static final String SORT_ANNOTATIONS = "SORT_ANNOTATIONS"; public static final String SHOW_AUTOCALC_ABOVE = "SHOW_AUTOCALC_ABOVE"; @@@ -194,11 -190,18 +194,18 @@@ super(); frame = new JInternalFrame(); frame.setContentPane(this); - wsPrefs = new WsPreferences(); - wsTab.add(wsPrefs, BorderLayout.CENTER); + if (!Platform.isJS()) + /** + * Java only + * + * @j2sIgnore + */ + { + wsPrefs = new WsPreferences(); + wsTab.add(wsPrefs, BorderLayout.CENTER); + } int width = 500, height = 450; - new jalview.util.Platform(); - if (Platform.isAMac()) + if (Platform.isAMacAndNotJS()) { width = 570; height = 480; @@@ -334,7 -337,7 +341,7 @@@ .setSelected(Cache.getDefault(SHOW_OV_HIDDEN_AT_START, false)); /* - * Set Structure tab defaults. + * Set Structure tab defaults */ final boolean structSelected = Cache.getDefault(STRUCT_FROM_PDB, false); structFromPdb.setSelected(structSelected); @@@ -344,52 -347,15 +351,52 @@@ addSecondaryStructure.setEnabled(structSelected); addTempFactor.setSelected(Cache.getDefault(ADD_TEMPFACT_ANN, false)); addTempFactor.setEnabled(structSelected); - structViewer.setSelectedItem( - Cache.getDefault(STRUCTURE_DISPLAY, ViewerType.JMOL.name())); - chimeraPath.setText(Cache.getDefault(CHIMERA_PATH, "")); - chimeraPath.addActionListener(new ActionListener() + + /* + * set choice of structure viewer, and path if saved as a preference; + * default to Jmol (first choice) if an unexpected value is found + */ + String viewerType = Cache.getDefault(STRUCTURE_DISPLAY, ViewerType.JMOL.name()); + structViewer.setSelectedItem(viewerType); + String viewerPath = ""; + ViewerType type = null; + try + { + type = ViewerType.valueOf(viewerType); + switch (type) + { + case JMOL: + break; + case CHIMERA: + viewerPath = Cache.getDefault(CHIMERA_PATH, ""); + break; + case CHIMERAX: + viewerPath = Cache.getDefault(CHIMERAX_PATH, ""); + break; + case PYMOL: + viewerPath = Cache.getDefault(PYMOL_PATH, ""); + break; + } + } catch (IllegalArgumentException e) + { + Cache.log.error("Unknown structure viewer type: " + viewerType + + ", defaulting to Jmol"); + type = ViewerType.JMOL; + } + structureViewerPath.setText(viewerPath); + + structureViewerPath.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - validateChimeraPath(); + if (validateViewerPath()) + { + Cache.setProperty(structViewer.getSelectedItem() + .equals(ViewerType.CHIMERAX.name()) + ? CHIMERAX_PATH + : CHIMERA_PATH, structureViewerPath.getText()); + } } }); @@@ -425,7 -391,8 +432,8 @@@ new RowSorter.SortKey(m.getNameColumn(), SortOrder.ASCENDING)); sorter.setSortKeys(sortKeys); - sorter.sort(); + // BH 2018 setSortKeys will do the sort + // sorter.sort(); // set up filtering ActionListener onReset; @@@ -442,7 -409,7 +450,7 @@@ doReset.addActionListener(onReset); // filter to display only custom urls - final RowFilter customUrlFilter = new RowFilter() + final RowFilter customUrlFilter = new RowFilter<>() { @Override public boolean include( @@@ -544,23 -511,9 +552,9 @@@ /* * Set Output tab defaults */ - epsRendering.addItem(promptEachTimeOpt); - epsRendering.addItem(lineArtOpt); - epsRendering.addItem(textOpt); - String defaultEPS = Cache.getDefault("EPS_RENDERING", - "Prompt each time"); - if (defaultEPS.equalsIgnoreCase("Text")) - { - epsRendering.setSelectedItem(textOpt); - } - else if (defaultEPS.equalsIgnoreCase("Lineart")) - { - epsRendering.setSelectedItem(lineArtOpt); - } - else - { - epsRendering.setSelectedItem(promptEachTimeOpt); - } + setupOutputCombo(epsRendering, "EPS_RENDERING"); + setupOutputCombo(htmlRendering, "HTML_RENDERING"); + setupOutputCombo(svgRendering, "SVG_RENDERING"); autoIdWidth.setSelected(Cache.getDefault("FIGURE_AUTOIDWIDTH", false)); userIdWidth.setEnabled(!autoIdWidth.isSelected()); userIdWidthlabel.setEnabled(!autoIdWidth.isSelected()); @@@ -598,6 -551,39 +592,39 @@@ } /** + * A helper method that sets the items and initial selection in a character + * rendering option list (Prompt each time/Lineart/Text) + * + * @param comboBox + * @param propertyKey + */ + protected void setupOutputCombo(JComboBox comboBox, + String propertyKey) + { + comboBox.addItem(promptEachTimeOpt); + comboBox.addItem(lineArtOpt); + comboBox.addItem(textOpt); + + /* + * JalviewJS doesn't support Lineart so force it to Text + */ + String defaultOption = Platform.isJS() ? "Text" + : Cache.getDefault(propertyKey, "Prompt each time"); + if (defaultOption.equalsIgnoreCase("Text")) + { + comboBox.setSelectedItem(textOpt); + } + else if (defaultOption.equalsIgnoreCase("Lineart")) + { + comboBox.setSelectedItem(lineArtOpt); + } + else + { + comboBox.setSelectedItem(promptEachTimeOpt); + } + } + + /** * Save user selections on the Preferences tabs to the Cache and write out to * file. * @@@ -721,22 -707,9 +748,22 @@@ Boolean.toString(useRnaView.isSelected())); Cache.applicationProperties.setProperty(STRUCT_FROM_PDB, Boolean.toString(structFromPdb.isSelected())); + String viewer = structViewer.getSelectedItem().toString(); + String viewerPath = structureViewerPath.getText(); Cache.applicationProperties.setProperty(STRUCTURE_DISPLAY, - structViewer.getSelectedItem().toString()); - Cache.setOrRemove(CHIMERA_PATH, chimeraPath.getText()); + viewer); + if (viewer.equals(ViewerType.CHIMERA.name())) + { + Cache.setOrRemove(CHIMERA_PATH, viewerPath); + } + else if (viewer.equals(ViewerType.CHIMERAX.name())) + { + Cache.setOrRemove(CHIMERAX_PATH, viewerPath); + } + else if (viewer.equals(ViewerType.PYMOL.name())) + { + Cache.setOrRemove(PYMOL_PATH, viewerPath); + } Cache.applicationProperties.setProperty("MAP_WITH_SIFTS", Boolean.toString(siftsMapping.isSelected())); SiftsSettings.setMapWithSifts(siftsMapping.isSelected()); @@@ -746,6 -719,10 +773,10 @@@ */ Cache.applicationProperties.setProperty("EPS_RENDERING", ((OptionsParam) epsRendering.getSelectedItem()).getCode()); + Cache.applicationProperties.setProperty("HTML_RENDERING", + ((OptionsParam) htmlRendering.getSelectedItem()).getCode()); + Cache.applicationProperties.setProperty("SVG_RENDERING", + ((OptionsParam) svgRendering.getSelectedItem()).getCode()); /* * Save Connections settings @@@ -855,7 -832,10 +886,10 @@@ Cache.applicationProperties.setProperty("PAD_GAPS", Boolean.toString(padGaps.isSelected())); - wsPrefs.updateAndRefreshWsMenuConfig(false); + if (!Platform.isJS()) + { + wsPrefs.updateAndRefreshWsMenuConfig(false); + } /* * Save Backups settings @@@ -909,7 -889,7 +943,7 @@@ @Override protected boolean validateStructure() { - return validateChimeraPath(); + return validateViewerPath(); } @@@ -919,6 -899,7 +953,7 @@@ @Override public void startupFileTextfield_mouseClicked() { + // TODO: JAL-3048 not needed for Jalview-JS String fileFormat = Cache.getProperty("DEFAULT_FILE_FORMAT"); JalviewFileChooser chooser = JalviewFileChooser .forRead(Cache.getProperty("LAST_DIRECTORY"), fileFormat); @@@ -952,8 -933,11 +987,11 @@@ { try { - wsPrefs.updateWsMenuConfig(true); - wsPrefs.refreshWs_actionPerformed(e); + if (!Platform.isJS()) + { + wsPrefs.updateWsMenuConfig(true); + wsPrefs.refreshWs_actionPerformed(e); + } frame.setClosed(true); } catch (Exception ex) { @@@ -1092,17 -1076,25 +1130,25 @@@ @Override public void defaultBrowser_mouseClicked(MouseEvent e) { - JFileChooser chooser = new JFileChooser("."); - chooser.setDialogTitle( - MessageManager.getString("label.select_default_browser")); + // TODO: JAL-3048 not needed for j2s + if (!Platform.isJS()) // BH 2019 + /** + * Java only + * + * @j2sIgnore + */ + { + JFileChooser chooser = new JFileChooser("."); + chooser.setDialogTitle( + MessageManager.getString("label.select_default_browser")); - int value = chooser.showOpenDialog(this); + int value = chooser.showOpenDialog(this); - if (value == JFileChooser.APPROVE_OPTION) - { - defaultBrowser.setText(chooser.getSelectedFile().getAbsolutePath()); + if (value == JFileChooser.APPROVE_OPTION) + { + defaultBrowser.setText(chooser.getSelectedFile().getAbsolutePath()); + } } - } /* @@@ -1127,27 -1119,17 +1173,17 @@@ @Override public void minColour_actionPerformed(JPanel panel) { - Color col = JColorChooser.showDialog(this, + JalviewColourChooser.showColourChooser(this, MessageManager.getString("label.select_colour_minimum_value"), - minColour.getBackground()); - if (col != null) - { - panel.setBackground(col); - } - panel.repaint(); + panel); } @Override public void maxColour_actionPerformed(JPanel panel) { - Color col = JColorChooser.showDialog(this, + JalviewColourChooser.showColourChooser(this, MessageManager.getString("label.select_colour_maximum_value"), - maxColour.getBackground()); - if (col != null) - { - panel.setBackground(col); - } - panel.repaint(); + panel); } @Override @@@ -1155,28 -1137,18 +1191,18 @@@ { if (!useLegacyGap.isSelected()) { - Color col = JColorChooser.showDialog(this, + JalviewColourChooser.showColourChooser(this, MessageManager.getString("label.select_gap_colour"), - gapColour.getBackground()); - if (col != null) - { - gap.setBackground(col); - } - gap.repaint(); + gap); } } @Override public void hiddenColour_actionPerformed(JPanel hidden) { - Color col = JColorChooser.showDialog(this, + JalviewColourChooser.showColourChooser(this, MessageManager.getString("label.select_hidden_colour"), - hiddenColour.getBackground()); - if (col != null) - { - hidden.setBackground(col); - } - hidden.repaint(); + hidden); } @Override @@@ -1224,12 -1196,12 +1250,12 @@@ } } catch (NumberFormatException x) { + userIdWidth.setText(""); JvOptionPane.showInternalMessageDialog(Desktop.desktop, MessageManager .getString("warn.user_defined_width_requirements"), MessageManager.getString("label.invalid_id_column_width"), JvOptionPane.WARNING_MESSAGE); - userIdWidth.setText(""); } } @@@ -1241,20 -1213,19 +1267,20 @@@ } /** - * Returns true if chimera path is to a valid executable, else show an error - * dialog. + * Returns true if structure viewer path is to a valid executable, else shows + * an error dialog. Does nothing if the path is empty, as is the case for Jmol + * (built in to Jalview) or when Jalview is left to try default paths. */ - private boolean validateChimeraPath() + private boolean validateViewerPath() { - if (chimeraPath.getText().trim().length() > 0) + if (structureViewerPath.getText().trim().length() > 0) { - File f = new File(chimeraPath.getText()); + File f = new File(structureViewerPath.getText()); if (!f.canExecute()) { JvOptionPane.showInternalMessageDialog(Desktop.desktop, - MessageManager.getString("label.invalid_chimera_path"), - MessageManager.getString("label.invalid_name"), + MessageManager.getString("label.invalid_viewer_path"), + MessageManager.getString("label.invalid_viewer_path"), JvOptionPane.ERROR_MESSAGE); return false; } @@@ -1263,57 -1234,23 +1289,57 @@@ } /** - * If Chimera is selected, check it can be found on default or user-specified - * path, if not show a warning/help dialog. + * If Chimera or ChimeraX or Pymol is selected, check it can be found on + * default or user-specified path, if not show a warning/help dialog */ @Override protected void structureViewer_actionPerformed(String selectedItem) { - if (!selectedItem.equals(ViewerType.CHIMERA.name())) + if (selectedItem.equals(ViewerType.JMOL.name())) { + structureViewerPath.setEnabled(false); + structureViewerPathLabel.setEnabled(false); return; } boolean found = false; + structureViewerPath.setEnabled(true); + structureViewerPathLabel.setEnabled(true); + structureViewerPathLabel.setText(MessageManager + .formatMessage("label.viewer_path", selectedItem)); /* - * Try user-specified and standard paths for Chimera executable. + * Try user-specified and standard paths for structure viewer executable */ - List paths = StructureManager.getChimeraPaths(); - paths.add(0, chimeraPath.getText()); + String viewerPath = ""; + List paths = null; + try + { + ViewerType viewerType = ViewerType.valueOf(selectedItem); + switch (viewerType) + { + case JMOL: + // dealt with above + break; + case CHIMERA: + viewerPath = Cache.getDefault(CHIMERA_PATH, ""); + paths = StructureManager.getChimeraPaths(false); + break; + case CHIMERAX: + viewerPath = Cache.getDefault(CHIMERAX_PATH, ""); + paths = StructureManager.getChimeraPaths(true); + break; + case PYMOL: + viewerPath = Cache.getDefault(PYMOL_PATH, ""); + paths = PymolManager.getPymolPaths(); + break; + } + } catch (IllegalArgumentException e) + { + // only valid entries should be in the drop-down + } + structureViewerPath.setText(viewerPath); + + paths.add(0, structureViewerPath.getText()); for (String path : paths) { if (new File(path.trim()).canExecute()) @@@ -1322,13 -1259,12 +1348,13 @@@ break; } } + if (!found) { String[] options = { "OK", "Help" }; int showHelp = JvOptionPane.showInternalOptionDialog(Desktop.desktop, JvSwingUtils.wrapTooltip(true, - MessageManager.getString("label.chimera_missing")), + MessageManager.getString("label.viewer_missing")), "", JvOptionPane.YES_NO_OPTION, JvOptionPane.WARNING_MESSAGE, null, options, options[0]); if (showHelp == JvOptionPane.NO_OPTION) diff --combined src/jalview/gui/StructureViewerBase.java index 9b6fd61,418a84d..e180f6b --- a/src/jalview/gui/StructureViewerBase.java +++ b/src/jalview/gui/StructureViewerBase.java @@@ -20,6 -20,26 +20,6 @@@ */ package jalview.gui; -import jalview.api.AlignmentViewPanel; -import jalview.bin.Cache; -import jalview.datamodel.Alignment; -import jalview.datamodel.AlignmentI; -import jalview.datamodel.HiddenColumns; -import jalview.datamodel.PDBEntry; -import jalview.datamodel.SequenceI; -import jalview.gui.JalviewColourChooser.ColourChooserListener; -import jalview.gui.StructureViewer.ViewerType; -import jalview.gui.ViewSelectionMenu.ViewSetProvider; -import jalview.io.DataSourceType; -import jalview.io.JalviewFileChooser; -import jalview.io.JalviewFileView; -import jalview.jbgui.GStructureViewer; -import jalview.schemes.ColourSchemeI; -import jalview.schemes.ColourSchemes; -import jalview.structure.StructureMapping; -import jalview.structures.models.AAStructureBindingModel; -import jalview.util.MessageManager; - import java.awt.Color; import java.awt.Component; import java.awt.event.ActionEvent; @@@ -34,36 -54,16 +34,36 @@@ import java.io.IOException import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; +import java.util.Random; import java.util.Vector; import javax.swing.ButtonGroup; import javax.swing.JCheckBoxMenuItem; - import javax.swing.JColorChooser; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JRadioButtonMenuItem; import javax.swing.event.MenuEvent; import javax.swing.event.MenuListener; +import jalview.api.AlignmentViewPanel; +import jalview.bin.Cache; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.PDBEntry; +import jalview.datamodel.SequenceI; ++import jalview.gui.JalviewColourChooser.ColourChooserListener; +import jalview.gui.StructureViewer.ViewerType; +import jalview.gui.ViewSelectionMenu.ViewSetProvider; +import jalview.io.DataSourceType; +import jalview.io.JalviewFileChooser; +import jalview.io.JalviewFileView; +import jalview.jbgui.GStructureViewer; +import jalview.schemes.ColourSchemeI; +import jalview.schemes.ColourSchemes; +import jalview.structure.StructureMapping; +import jalview.structures.models.AAStructureBindingModel; +import jalview.util.MessageManager; +import jalview.ws.dbsources.Pdb; + /** * Base class with common functionality for JMol, Chimera or other structure * viewers. @@@ -90,13 -90,13 +90,13 @@@ public abstract class StructureViewerBa /** * list of alignment panels to use for superposition */ - protected Vector _alignwith = new Vector<>(); + protected Vector _alignwith = new Vector<>(); /** * list of alignment panels that are used for colouring structures by aligned * sequences */ - protected Vector _colourwith = new Vector<>(); + protected Vector _colourwith = new Vector<>(); private String viewId = null; @@@ -121,10 -121,6 +121,10 @@@ */ protected volatile boolean seqColoursApplied = false; + private IProgressIndicator progressBar = null; + + private Random random = new Random(); + /** * Default constructor */ @@@ -163,14 -159,13 +163,14 @@@ return _aps.contains(ap2.av.getSequenceSetId()); } - public boolean isUsedforaligment(AlignmentPanel ap2) + public boolean isUsedforaligment(AlignmentViewPanel ap2) { return (_alignwith != null) && _alignwith.contains(ap2); } - public boolean isUsedforcolourby(AlignmentPanel ap2) + @Override + public boolean isUsedForColourBy(AlignmentViewPanel ap2) { return (_colourwith != null) && _colourwith.contains(ap2); } @@@ -198,6 -193,8 +198,6 @@@ this.viewId = viewId; } - public abstract String getStateInfo(); - protected void buildActionMenu() { if (_alignwith == null) @@@ -218,7 -215,6 +218,7 @@@ } } + @Override public AlignmentPanel getAlignmentPanel() { return ap; @@@ -271,8 -267,7 +271,8 @@@ * * @param nap */ - public void removeAlignmentPanel(AlignmentPanel nap) + @Override + public void removeAlignmentPanel(AlignmentViewPanel nap) { try { @@@ -344,6 -339,8 +344,6 @@@ public abstract ViewerType getViewerType(); - protected abstract IProgressIndicator getIProgressIndicator(); - /** * add a new structure (with associated sequences and chains) to this viewer, * retrieving it if necessary first. @@@ -452,7 -449,7 +452,7 @@@ * create the mappings */ apanel.getStructureSelectionManager().setMapping(seq, chains, - pdbFilename, DataSourceType.FILE, getIProgressIndicator()); + pdbFilename, DataSourceType.FILE, getProgressIndicator()); /* * alert the FeatureRenderer to show new (PDB RESNUM) features @@@ -557,6 -554,8 +557,6 @@@ } } - abstract void showSelectedChains(); - /** * Action on selecting one of Jalview's registered colour schemes */ @@@ -567,7 -566,7 +567,7 @@@ ColourSchemeI cs = ColourSchemes.getInstance() .getColourScheme(colourSchemeName, getAlignmentPanel().av, al, null); - getBinding().setJalviewColourScheme(cs); + getBinding().colourByJalviewColourScheme(cs); } /** @@@ -601,7 -600,7 +601,7 @@@ @Override public void actionPerformed(ActionEvent actionEvent) { - viewerColour_actionPerformed(actionEvent); + viewerColour_actionPerformed(); } }); colourMenu.add(viewerColour); @@@ -617,7 -616,7 +617,7 @@@ @Override public void actionPerformed(ActionEvent actionEvent) { - background_actionPerformed(actionEvent); + background_actionPerformed(); } }); colourMenu.add(backGround); @@@ -648,7 -647,7 +648,7 @@@ @Override public void actionPerformed(ActionEvent actionEvent) { - seqColour_actionPerformed(actionEvent); + seqColour_actionPerformed(); } }); @@@ -660,7 -659,7 +660,7 @@@ @Override public void actionPerformed(ActionEvent actionEvent) { - chainColour_actionPerformed(actionEvent); + chainColour_actionPerformed(); } }); @@@ -672,15 -671,12 +672,15 @@@ @Override public void actionPerformed(ActionEvent actionEvent) { - chargeColour_actionPerformed(actionEvent); + chargeColour_actionPerformed(); } }); viewerColour = new JRadioButtonMenuItem(); - // text is set in overrides of this method + viewerColour + .setText(MessageManager.getString("label.colour_with_viewer")); + viewerColour.setToolTipText(MessageManager + .getString("label.let_viewer_manage_structure_colours")); viewerColour.setName(ViewerColour.ByViewer.name()); viewerColour.setSelected(!binding.isColourBySequence()); @@@ -707,7 -703,7 +707,7 @@@ else { // update the Chimera display now. - seqColour_actionPerformed(null); + seqColour_actionPerformed(); } } }); @@@ -718,18 -714,10 +718,18 @@@ @Override public void itemStateChanged(ItemEvent e) { - alignStructs.setEnabled(!_alignwith.isEmpty()); - alignStructs.setToolTipText(MessageManager.formatMessage( - "label.align_structures_using_linked_alignment_views", - _alignwith.size())); + if (_alignwith.isEmpty()) + { + alignStructs.setEnabled(false); + alignStructs.setToolTipText(null); + } + else + { + alignStructs.setEnabled(true); + alignStructs.setToolTipText(MessageManager.formatMessage( + "label.align_structures_using_linked_alignment_views", + _alignwith.size())); + } } }; viewSelectionMenu = new ViewSelectionMenu( @@@ -759,13 -747,24 +759,13 @@@ buildColourMenu(); } - @Override - public void setJalviewColourScheme(ColourSchemeI cs) - { - getBinding().setJalviewColourScheme(cs); - } - /** * Sends commands to the structure viewer to superimpose structures based on * currently associated alignments. May optionally return an error message for * the operation. */ @Override - protected String alignStructs_actionPerformed(ActionEvent actionEvent) - { - return alignStructs_withAllAlignPanels(); - } - - protected String alignStructs_withAllAlignPanels() + protected String alignStructsWithAllAlignPanels() { if (getAlignmentPanel() == null) { @@@ -780,8 -779,19 +780,8 @@@ String reply = null; try { - AlignmentI[] als = new Alignment[_alignwith.size()]; - HiddenColumns[] alc = new HiddenColumns[_alignwith.size()]; - int[] alm = new int[_alignwith.size()]; - int a = 0; - - for (AlignmentPanel alignPanel : _alignwith) - { - als[a] = alignPanel.av.getAlignment(); - alm[a] = -1; - alc[a++] = alignPanel.av.getAlignment().getHiddenColumns(); - } - reply = getBinding().superposeStructures(als, alm, alc); - if (reply != null) + reply = getBinding().superposeStructures(_alignwith); + if (reply != null && !reply.isEmpty()) { String text = MessageManager .formatMessage("error.superposition_failed", reply); @@@ -790,9 -800,9 +790,9 @@@ } catch (Exception e) { StringBuffer sp = new StringBuffer(); - for (AlignmentPanel alignPanel : _alignwith) + for (AlignmentViewPanel alignPanel : _alignwith) { - sp.append("'" + alignPanel.alignFrame.getTitle() + "' "); + sp.append("'" + alignPanel.getViewName() + "' "); } Cache.log.info("Couldn't align structures with the " + sp.toString() + "associated alignment panels.", e); @@@ -800,20 -810,27 +800,27 @@@ return reply; } + /** + * Opens a colour chooser dialog, and applies the chosen colour to the + * background of the structure viewer + */ @Override - public void background_actionPerformed(ActionEvent actionEvent) + public void background_actionPerformed() { - Color col = JColorChooser.showDialog(this, - MessageManager.getString("label.select_background_colour"), - null); - if (col != null) + String ttl = MessageManager.getString("label.select_background_colour"); + ColourChooserListener listener = new ColourChooserListener() { - getBinding().setBackgroundColour(col); - } + @Override + public void colourSelected(Color c) + { + getBinding().setBackgroundColour(c); + } + }; + JalviewColourChooser.showColourChooser(this, ttl, null, listener); } @Override - public void viewerColour_actionPerformed(ActionEvent actionEvent) + public void viewerColour_actionPerformed() { if (viewerColour.isSelected()) { @@@ -823,21 -840,21 +830,21 @@@ } @Override - public void chainColour_actionPerformed(ActionEvent actionEvent) + public void chainColour_actionPerformed() { chainColour.setSelected(true); getBinding().colourByChain(); } @Override - public void chargeColour_actionPerformed(ActionEvent actionEvent) + public void chargeColour_actionPerformed() { chargeColour.setSelected(true); getBinding().colourByCharge(); } @Override - public void seqColour_actionPerformed(ActionEvent actionEvent) + public void seqColour_actionPerformed() { AAStructureBindingModel binding = getBinding(); binding.setColourBySequence(seqColour.isSelected()); @@@ -856,7 -873,7 +863,7 @@@ } } // Set the colour using the current view for the associated alignframe - for (AlignmentPanel alignPanel : _colourwith) + for (AlignmentViewPanel alignPanel : _colourwith) { binding.colourBySequence(alignPanel); } @@@ -865,8 -882,9 +872,9 @@@ } @Override - public void pdbFile_actionPerformed(ActionEvent actionEvent) + public void pdbFile_actionPerformed() { + // TODO: JAL-3048 not needed for Jalview-JS - save PDB file JalviewFileChooser chooser = new JalviewFileChooser( Cache.getProperty("LAST_DIRECTORY")); @@@ -916,7 -934,7 +924,7 @@@ } @Override - public void viewMapping_actionPerformed(ActionEvent actionEvent) + public void viewMapping_actionPerformed() { CutAndPasteTransfer cap = new CutAndPasteTransfer(); try @@@ -978,7 -996,7 +986,7 @@@ if (!binding.isLoadingFromArchive()) { - seqColour_actionPerformed(null); + seqColour_actionPerformed(); } } @@@ -1031,181 -1049,4 +1039,181 @@@ toFront(); } + @Override + public long startProgressBar(String msg) + { + // TODO would rather have startProgress/stopProgress as the + // IProgressIndicator interface + long tm = random.nextLong(); + if (progressBar != null) + { + progressBar.setProgressBar(msg, tm); + } + return tm; + } + + @Override + public void stopProgressBar(String msg, long handle) + { + if (progressBar != null) + { + progressBar.setProgressBar(msg, handle); + } + } + + protected IProgressIndicator getProgressIndicator() + { + return progressBar; + } + + protected void setProgressIndicator(IProgressIndicator pi) + { + progressBar = pi; + } + + protected void setProgressMessage(String message, long id) + { + if (progressBar != null) + { + progressBar.setProgressBar(message, id); + } + } + + @Override + public void showConsole(boolean show) + { + // default does nothing + } + + /** + * Show only the selected chain(s) in the viewer + */ + protected void showSelectedChains() + { + List toshow = new ArrayList<>(); + for (int i = 0; i < chainMenu.getItemCount(); i++) + { + if (chainMenu.getItem(i) instanceof JCheckBoxMenuItem) + { + JCheckBoxMenuItem item = (JCheckBoxMenuItem) chainMenu.getItem(i); + if (item.isSelected()) + { + toshow.add(item.getText()); + } + } + } + getBinding().showChains(toshow); + } + + /** + * Tries to fetch a PDB file and save to a temporary local file. Returns the + * saved file path if successful, or null if not. + * + * @param processingEntry + * @return + */ + protected String fetchPdbFile(PDBEntry processingEntry) + { + String filePath = null; + Pdb pdbclient = new Pdb(); + AlignmentI pdbseq = null; + String pdbid = processingEntry.getId(); + long handle = System.currentTimeMillis() + + Thread.currentThread().hashCode(); + + /* + * Write 'fetching PDB' progress on AlignFrame as we are not yet visible + */ + String msg = MessageManager.formatMessage("status.fetching_pdb", + new Object[] + { pdbid }); + getAlignmentPanel().alignFrame.setProgressBar(msg, handle); + // long hdl = startProgressBar(MessageManager.formatMessage( + // "status.fetching_pdb", new Object[] + // { pdbid })); + try + { + pdbseq = pdbclient.getSequenceRecords(pdbid); + } catch (Exception e) + { + System.err.println( + "Error retrieving PDB id " + pdbid + ": " + e.getMessage()); + } finally + { + msg = pdbid + " " + MessageManager.getString("label.state_completed"); + getAlignmentPanel().alignFrame.setProgressBar(msg, handle); + // stopProgressBar(msg, hdl); + } + /* + * If PDB data were saved and are not invalid (empty alignment), return the + * file path. + */ + if (pdbseq != null && pdbseq.getHeight() > 0) + { + // just use the file name from the first sequence's first PDBEntry + filePath = new File(pdbseq.getSequenceAt(0).getAllPDBEntries() + .elementAt(0).getFile()).getAbsolutePath(); + processingEntry.setFile(filePath); + } + return filePath; + } + + /** + * If supported, saves the state of the structure viewer to a temporary file + * and returns the file, else returns null + * + * @return + */ + public File saveSession() + { + // TODO: a wait loop to ensure the file is written fully before returning? + return getBinding() == null ? null : getBinding().saveSession(); + } + + /** + * Close down this instance of Jalview's Chimera viewer, giving the user the + * option to close the associated Chimera window (process). They may wish to + * keep it open until they have had an opportunity to save any work. + * + * @param forceClose + * if true, close any linked Chimera process; if false, prompt first + */ + @Override + public void closeViewer(boolean forceClose) + { + AAStructureBindingModel binding = getBinding(); + if (binding != null && binding.isViewerRunning()) + { + if (!forceClose) + { + String viewerName = getViewerName(); + String prompt = MessageManager + .formatMessage("label.confirm_close_viewer", new Object[] + { binding.getViewerTitle(viewerName, false), viewerName }); + prompt = JvSwingUtils.wrapTooltip(true, prompt); + int confirm = JvOptionPane.showConfirmDialog(this, prompt, + MessageManager.getString("label.close_viewer"), + JvOptionPane.YES_NO_CANCEL_OPTION); + /* + * abort closure if user hits escape or Cancel + */ + if (confirm == JvOptionPane.CANCEL_OPTION + || confirm == JvOptionPane.CLOSED_OPTION) + { + return; + } + forceClose = confirm == JvOptionPane.YES_OPTION; + } + binding.closeViewer(forceClose); + } + setAlignmentPanel(null); + _aps.clear(); + _alignwith.clear(); + _colourwith.clear(); + // TODO: check for memory leaks where instance isn't finalised because jmb + // holds a reference to the window + // jmb = null; + dispose(); + } + } diff --combined src/jalview/jbgui/GPreferences.java index 8963be4,6de3888..ae6727a --- a/src/jalview/jbgui/GPreferences.java +++ b/src/jalview/jbgui/GPreferences.java @@@ -20,6 -20,22 +20,6 @@@ */ package jalview.jbgui; -import jalview.bin.Cache; -import jalview.fts.core.FTSDataColumnPreferences; -import jalview.fts.core.FTSDataColumnPreferences.PreferenceSource; -import jalview.fts.service.pdb.PDBFTSRestClient; -import jalview.gui.Desktop; -import jalview.gui.JalviewBooleanRadioButtons; -import jalview.gui.JvOptionPane; -import jalview.gui.JvSwingUtils; -import jalview.gui.StructureViewer.ViewerType; -import jalview.io.BackupFilenameParts; -import jalview.io.BackupFiles; -import jalview.io.BackupFilesPresetEntry; -import jalview.io.IntKeyStringValueEntry; -import jalview.util.MessageManager; -import jalview.util.Platform; - import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; @@@ -71,21 -87,6 +71,22 @@@ import javax.swing.event.ChangeListener import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; +import jalview.bin.Cache; +import jalview.fts.core.FTSDataColumnPreferences; +import jalview.fts.core.FTSDataColumnPreferences.PreferenceSource; +import jalview.fts.service.pdb.PDBFTSRestClient; +import jalview.gui.Desktop; +import jalview.gui.JalviewBooleanRadioButtons; +import jalview.gui.JvOptionPane; +import jalview.gui.JvSwingUtils; +import jalview.gui.StructureViewer.ViewerType; +import jalview.io.BackupFilenameParts; +import jalview.io.BackupFiles; +import jalview.io.BackupFilesPresetEntry; +import jalview.io.IntKeyStringValueEntry; +import jalview.util.MessageManager; ++import jalview.util.Platform; + /** * Base class for the Preferences panel. * @@@ -179,9 -180,7 +180,9 @@@ public class GPreferences extends JPane protected JComboBox structViewer = new JComboBox<>(); - protected JTextField chimeraPath = new JTextField(); + protected JLabel structureViewerPathLabel; + + protected JTextField structureViewerPath = new JTextField(); protected ButtonGroup mappingMethod = new ButtonGroup(); @@@ -251,6 -250,10 +252,10 @@@ */ protected JComboBox epsRendering = new JComboBox<>(); + protected JComboBox htmlRendering = new JComboBox<>(); + + protected JComboBox svgRendering = new JComboBox<>(); + protected JLabel userIdWidthlabel = new JLabel(); protected JCheckBox autoIdWidth = new JCheckBox(); @@@ -377,8 -380,11 +382,11 @@@ tabbedPane.add(initConnectionsTab(), MessageManager.getString("label.connections")); - tabbedPane.add(initBackupsTab(), - MessageManager.getString("label.backups")); + if (!Platform.isJS()) + { + tabbedPane.add(initBackupsTab(), + MessageManager.getString("label.backups")); + } tabbedPane.add(initLinksTab(), MessageManager.getString("label.urllinks")); @@@ -392,8 -398,11 +400,11 @@@ /* * See WsPreferences for the real work of configuring this tab. */ - wsTab.setLayout(new BorderLayout()); - tabbedPane.add(wsTab, MessageManager.getString("label.web_services")); + if (!Platform.isJS()) + { + wsTab.setLayout(new BorderLayout()); + tabbedPane.add(wsTab, MessageManager.getString("label.web_services")); + } /* * Handler to validate a tab before leaving it - currently only for @@@ -451,7 -460,7 +462,7 @@@ } /** - * Initialises the Output tabbed panel. + * Initialises the Output tab * * @return */ @@@ -459,18 -468,35 +470,35 @@@ { JPanel outputTab = new JPanel(); outputTab.setLayout(null); - JLabel epsLabel = new JLabel(); + + JLabel epsLabel = new JLabel( + MessageManager.formatMessage("label.rendering_style", "EPS")); epsLabel.setFont(LABEL_FONT); epsLabel.setHorizontalAlignment(SwingConstants.RIGHT); - epsLabel.setText(MessageManager.getString("label.eps_rendering_style")); - epsLabel.setBounds(new Rectangle(9, 31, 140, 24)); + epsLabel.setBounds(new Rectangle(9, 31, 160, 24)); epsRendering.setFont(LABEL_FONT); - epsRendering.setBounds(new Rectangle(154, 34, 187, 21)); + epsRendering.setBounds(new Rectangle(174, 34, 187, 21)); + JLabel htmlLabel = new JLabel( + MessageManager.formatMessage("label.rendering_style", "HTML")); + htmlLabel.setFont(LABEL_FONT); + htmlLabel.setHorizontalAlignment(SwingConstants.RIGHT); + htmlLabel.setBounds(new Rectangle(9, 55, 160, 24)); + htmlRendering.setFont(LABEL_FONT); + htmlRendering.setBounds(new Rectangle(174, 58, 187, 21)); + JLabel svgLabel = new JLabel( + MessageManager.formatMessage("label.rendering_style", "SVG")); + svgLabel.setFont(LABEL_FONT); + svgLabel.setHorizontalAlignment(SwingConstants.RIGHT); + svgLabel.setBounds(new Rectangle(9, 79, 160, 24)); + svgRendering.setFont(LABEL_FONT); + svgRendering.setBounds(new Rectangle(174, 82, 187, 21)); + JLabel jLabel1 = new JLabel(); jLabel1.setFont(LABEL_FONT); jLabel1.setHorizontalAlignment(SwingConstants.CENTER); jLabel1.setText(MessageManager.getString("label.append_start_end")); jLabel1.setFont(LABEL_FONT); + fastajv.setFont(LABEL_FONT); fastajv.setHorizontalAlignment(SwingConstants.LEFT); clustaljv.setText(MessageManager.getString("label.clustal") + " "); @@@ -487,7 -513,7 +515,7 @@@ TitledBorder titledBorder2 = new TitledBorder( MessageManager.getString("label.file_output")); jPanel11.setBorder(titledBorder2); - jPanel11.setBounds(new Rectangle(30, 72, 196, 182)); + jPanel11.setBounds(new Rectangle(30, 120, 196, 182)); GridLayout gridLayout3 = new GridLayout(); jPanel11.setLayout(gridLayout3); gridLayout3.setRows(8); @@@ -506,7 -532,7 +534,7 @@@ MessageManager.getString("label.automatically_set_id_width")); autoIdWidth.setToolTipText(JvSwingUtils.wrapTooltip(true, MessageManager .getString("label.adjusts_width_generated_eps_png"))); - autoIdWidth.setBounds(new Rectangle(228, 96, 188, 23)); + autoIdWidth.setBounds(new Rectangle(228, 144, 320, 23)); autoIdWidth.addActionListener(new ActionListener() { @@@ -524,10 -550,10 +552,10 @@@ userIdWidthlabel.setToolTipText( JvSwingUtils.wrapTooltip(true, MessageManager.getString( "label.manually_specify_width_left_column"))); - userIdWidthlabel.setBounds(new Rectangle(236, 120, 168, 23)); + userIdWidthlabel.setBounds(new Rectangle(236, 168, 320, 23)); userIdWidth.setFont(JvSwingUtils.getTextAreaFont()); userIdWidth.setText(""); - userIdWidth.setBounds(new Rectangle(232, 144, 84, 23)); + userIdWidth.setBounds(new Rectangle(232, 192, 84, 23)); userIdWidth.addActionListener(new ActionListener() { @@@ -540,10 -566,10 +568,10 @@@ modellerOutput.setFont(LABEL_FONT); modellerOutput .setText(MessageManager.getString("label.use_modeller_output")); - modellerOutput.setBounds(new Rectangle(228, 226, 168, 23)); + modellerOutput.setBounds(new Rectangle(228, 274, 320, 23)); embbedBioJSON.setFont(LABEL_FONT); embbedBioJSON.setText(MessageManager.getString("label.embbed_biojson")); - embbedBioJSON.setBounds(new Rectangle(228, 200, 250, 23)); + embbedBioJSON.setBounds(new Rectangle(228, 248, 250, 23)); jPanel11.add(jLabel1); jPanel11.add(blcjv); @@@ -557,9 -583,19 +585,19 @@@ outputTab.add(userIdWidth); outputTab.add(userIdWidthlabel); outputTab.add(modellerOutput); - outputTab.add(embbedBioJSON); - outputTab.add(epsLabel); - outputTab.add(epsRendering); + if (!Platform.isJS()) + { + /* + * JalviewJS doesn't support Lineart option or SVG output + */ + outputTab.add(embbedBioJSON); + outputTab.add(epsLabel); + outputTab.add(epsRendering); + outputTab.add(htmlLabel); + outputTab.add(htmlRendering); + outputTab.add(svgLabel); + outputTab.add(svgRendering); + } outputTab.add(jPanel11); return outputTab; } @@@ -1197,7 -1233,7 +1235,7 @@@ structureTab.setBorder(new TitledBorder( MessageManager.getString("label.structure_options"))); structureTab.setLayout(null); - final int width = 400; + final int width = 420; final int height = 22; final int lineSpacing = 25; int ypos = 15; @@@ -1245,19 -1281,13 +1283,19 @@@ viewerLabel.setFont(LABEL_FONT); viewerLabel.setHorizontalAlignment(SwingConstants.LEFT); viewerLabel.setText(MessageManager.getString("label.structure_viewer")); - viewerLabel.setBounds(new Rectangle(10, ypos, 200, height)); + viewerLabel.setBounds(new Rectangle(10, ypos, 220, height)); structureTab.add(viewerLabel); + /* + * add all external viewers as options here - check + * when selected whether the program is installed + */ structViewer.setFont(LABEL_FONT); - structViewer.setBounds(new Rectangle(160, ypos, 120, height)); + structViewer.setBounds(new Rectangle(190, ypos, 120, height)); structViewer.addItem(ViewerType.JMOL.name()); structViewer.addItem(ViewerType.CHIMERA.name()); + structViewer.addItem(ViewerType.CHIMERAX.name()); + structViewer.addItem(ViewerType.PYMOL.name()); structViewer.addActionListener(new ActionListener() { @Override @@@ -1270,38 -1300,35 +1308,38 @@@ structureTab.add(structViewer); ypos += lineSpacing; - JLabel pathLabel = new JLabel(); - pathLabel.setFont(new java.awt.Font("SansSerif", 0, 11)); - pathLabel.setHorizontalAlignment(SwingConstants.LEFT); - pathLabel.setText(MessageManager.getString("label.chimera_path")); - pathLabel.setBounds(new Rectangle(10, ypos, 140, height)); - structureTab.add(pathLabel); - - chimeraPath.setFont(LABEL_FONT); - chimeraPath.setText(""); + structureViewerPathLabel = new JLabel(); + structureViewerPathLabel.setFont(LABEL_FONT);// new Font("SansSerif", 0, 11)); + structureViewerPathLabel.setHorizontalAlignment(SwingConstants.LEFT); + structureViewerPathLabel.setText(MessageManager + .formatMessage("label.viewer_path", "Chimera(X)")); + structureViewerPathLabel.setBounds(new Rectangle(10, ypos, 170, height)); + structureViewerPathLabel.setEnabled(false); + structureTab.add(structureViewerPathLabel); + + structureViewerPath.setFont(LABEL_FONT); + structureViewerPath.setText(""); + structureViewerPath.setEnabled(false); final String tooltip = JvSwingUtils.wrapTooltip(true, - MessageManager.getString("label.chimera_path_tip")); - chimeraPath.setToolTipText(tooltip); - chimeraPath.setBounds(new Rectangle(160, ypos, 300, height)); - chimeraPath.addMouseListener(new MouseAdapter() + MessageManager.getString("label.viewer_path_tip")); + structureViewerPath.setToolTipText(tooltip); + structureViewerPath.setBounds(new Rectangle(190, ypos, 290, height)); + structureViewerPath.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) + if (structureViewerPath.isEnabled() && e.getClickCount() == 2) { String chosen = openFileChooser(); if (chosen != null) { - chimeraPath.setText(chosen); + structureViewerPath.setText(chosen); } } } }); - structureTab.add(chimeraPath); + structureTab.add(structureViewerPath); ypos += lineSpacing; nwMapping.setFont(LABEL_FONT); @@@ -1316,7 -1343,7 +1354,7 @@@ MessageManager.getString("label.mapping_method")); mmTitledBorder.setTitleFont(LABEL_FONT); mappingPanel.setBorder(mmTitledBorder); - mappingPanel.setBounds(new Rectangle(10, ypos, 452, 45)); + mappingPanel.setBounds(new Rectangle(10, ypos, 472, 45)); // GridLayout mappingLayout = new GridLayout(); mappingPanel.setLayout(new GridLayout()); mappingPanel.add(nwMapping); @@@ -1327,9 -1354,20 +1365,20 @@@ ypos += lineSpacing; FTSDataColumnPreferences docFieldPref = new FTSDataColumnPreferences( PreferenceSource.PREFERENCES, PDBFTSRestClient.getInstance()); - docFieldPref.setBounds(new Rectangle(10, ypos, 450, 120)); + docFieldPref.setBounds(new Rectangle(10, ypos, 470, 120)); structureTab.add(docFieldPref); + /* + * hide Chimera options in JalviewJS + */ + if (Platform.isJS()) + { - pathLabel.setVisible(false); - chimeraPath.setVisible(false); ++ structureViewerPathLabel.setVisible(false); ++ structureViewerPath.setVisible(false); + viewerLabel.setVisible(false); + structViewer.setVisible(false); + } + return structureTab; } @@@ -1706,6 -1744,13 +1755,13 @@@ visualTab.add(fontNameCB); visualTab.add(fontSizeCB); visualTab.add(fontStyleCB); + + if (Platform.isJS()) + { + startupCheckbox.setVisible(false); + startupFileTextfield.setVisible(false); + } + return visualTab; } @@@ -1718,7 -1763,7 +1774,7 @@@ BackupFilesPresetEntry savedPreset = BackupFilesPresetEntry .getSavedBackupEntry(); enableBackupFiles - .setSelected(Cache.getDefault(BackupFiles.ENABLED, true)); + .setSelected(Cache.getDefault(BackupFiles.ENABLED, !Platform.isJS())); BackupFilesPresetEntry backupfilesCustomEntry = BackupFilesPresetEntry .createBackupFilesPresetEntry(Cache diff --combined src/jalview/jbgui/GStructureViewer.java index 1fccdcb,dfee3e2..6c0beda --- a/src/jalview/jbgui/GStructureViewer.java +++ b/src/jalview/jbgui/GStructureViewer.java @@@ -20,10 -20,11 +20,6 @@@ */ package jalview.jbgui; --import jalview.api.structures.JalviewStructureDisplayI; --import jalview.gui.ColourMenuHelper.ColourChangeListener; - import jalview.util.MessageManager; - -import jalview.util.ImageMaker.TYPE; -import jalview.util.MessageManager; - import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; @@@ -37,6 -38,7 +33,12 @@@ import javax.swing.JMenuItem import javax.swing.JPanel; import javax.swing.JRadioButtonMenuItem; ++import jalview.api.structures.JalviewStructureDisplayI; ++import jalview.gui.ColourMenuHelper.ColourChangeListener; ++import jalview.util.ImageMaker.TYPE; ++import jalview.util.MessageManager; ++ + @SuppressWarnings("serial") public abstract class GStructureViewer extends JInternalFrame implements JalviewStructureDisplayI, ColourChangeListener { @@@ -86,6 -88,9 +88,9 @@@ private void jbInit() throws Exception { + + setName("jalview-structureviewer"); + JMenuBar menuBar = new JMenuBar(); this.setJMenuBar(menuBar); @@@ -104,7 -109,7 +109,7 @@@ @Override public void actionPerformed(ActionEvent actionEvent) { - pdbFile_actionPerformed(actionEvent); + pdbFile_actionPerformed(); } }); @@@ -115,7 -120,7 +120,7 @@@ @Override public void actionPerformed(ActionEvent actionEvent) { - png_actionPerformed(); + makePDBImage(TYPE.PNG); } }); @@@ -126,7 -131,7 +131,7 @@@ @Override public void actionPerformed(ActionEvent actionEvent) { - eps_actionPerformed(); + makePDBImage(TYPE.EPS); } }); @@@ -137,7 -142,7 +142,7 @@@ @Override public void actionPerformed(ActionEvent actionEvent) { - viewMapping_actionPerformed(actionEvent); + viewMapping_actionPerformed(); } }); @@@ -167,7 -172,7 +172,7 @@@ @Override public void actionPerformed(ActionEvent actionEvent) { - showHelp_actionPerformed(actionEvent); + showHelp_actionPerformed(); } }); alignStructs = new JMenuItem(); @@@ -178,7 -183,7 +183,7 @@@ @Override public void actionPerformed(ActionEvent actionEvent) { - alignStructs_actionPerformed(actionEvent); + alignStructsWithAllAlignPanels(); } }); @@@ -216,53 -221,49 +221,48 @@@ { } - protected void viewerColour_actionPerformed(ActionEvent actionEvent) + protected void viewerColour_actionPerformed() { } - protected abstract String alignStructs_actionPerformed( - ActionEvent actionEvent); + protected abstract String alignStructsWithAllAlignPanels(); - public void pdbFile_actionPerformed(ActionEvent actionEvent) + public void pdbFile_actionPerformed() { } - public void png_actionPerformed() - { - - } - - public void eps_actionPerformed() + public void makePDBImage(TYPE imageType) { } - public void viewMapping_actionPerformed(ActionEvent actionEvent) + public void viewMapping_actionPerformed() { } - public void seqColour_actionPerformed(ActionEvent actionEvent) + public void seqColour_actionPerformed() { } - public void chainColour_actionPerformed(ActionEvent actionEvent) + public void chainColour_actionPerformed() { } - public void chargeColour_actionPerformed(ActionEvent actionEvent) + public void chargeColour_actionPerformed() { } - public void background_actionPerformed(ActionEvent actionEvent) + public void background_actionPerformed() { } - public void showHelp_actionPerformed(ActionEvent actionEvent) + public void showHelp_actionPerformed() { } diff --combined src/jalview/project/Jalview2XML.java index b408c07,6340e64..4cfac7b --- a/src/jalview/project/Jalview2XML.java +++ b/src/jalview/project/Jalview2XML.java @@@ -24,55 -24,6 +24,56 @@@ import static jalview.math.RotatableMat import static jalview.math.RotatableMatrix.Axis.Y; import static jalview.math.RotatableMatrix.Axis.Z; +import java.awt.Color; +import java.awt.Font; +import java.awt.Rectangle; +import java.io.BufferedReader; ++import java.io.ByteArrayInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.lang.reflect.InvocationTargetException; +import java.math.BigInteger; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.Vector; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; +import java.util.jar.JarOutputStream; + +import javax.swing.JInternalFrame; +import javax.swing.SwingUtilities; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.Marshaller; +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamReader; + import jalview.analysis.Conservation; import jalview.analysis.PCA; import jalview.analysis.scoremodels.ScoreModels; @@@ -102,21 -53,17 +103,21 @@@ import jalview.datamodel.features.Featu import jalview.datamodel.features.FeatureMatcherI; import jalview.datamodel.features.FeatureMatcherSet; import jalview.datamodel.features.FeatureMatcherSetI; +import jalview.ext.rbvi.chimera.JalviewChimeraBinding; import jalview.ext.varna.RnaModel; import jalview.gui.AlignFrame; import jalview.gui.AlignViewport; import jalview.gui.AlignmentPanel; import jalview.gui.AppVarna; import jalview.gui.ChimeraViewFrame; +import jalview.gui.ChimeraXViewFrame; import jalview.gui.Desktop; +import jalview.gui.JalviewChimeraXBindingModel; import jalview.gui.JvOptionPane; import jalview.gui.OOMWarning; import jalview.gui.PCAPanel; import jalview.gui.PaintRefresher; +import jalview.gui.PymolViewer; import jalview.gui.SplitFrame; import jalview.gui.StructureViewer; import jalview.gui.StructureViewer.ViewerType; @@@ -203,6 -150,55 +204,6 @@@ import jalview.xml.binding.jalview.Sequ import jalview.xml.binding.jalview.ThresholdType; import jalview.xml.binding.jalview.VAMSAS; -import java.awt.Color; -import java.awt.Font; -import java.awt.Rectangle; -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.lang.reflect.InvocationTargetException; -import java.math.BigInteger; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.Vector; -import java.util.jar.JarEntry; -import java.util.jar.JarInputStream; -import java.util.jar.JarOutputStream; - -import javax.swing.JInternalFrame; -import javax.swing.SwingUtilities; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.Marshaller; -import javax.xml.datatype.DatatypeConfigurationException; -import javax.xml.datatype.DatatypeFactory; -import javax.xml.datatype.XMLGregorianCalendar; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamReader; - /** * Write out the current jalview desktop state as a Jalview XML stream. * @@@ -215,6 -211,15 +216,15 @@@ */ public class Jalview2XML { + + // BH 2018 we add the .jvp binary extension to J2S so that + // it will declare that binary when we do the file save from the browser + + static + { + Platform.addJ2SBinaryType(".jvp?"); + } + private static final String VIEWER_PREFIX = "viewer_"; private static final String RNA_PREFIX = "rna_"; @@@ -458,7 -463,7 +468,7 @@@ public boolean isResolvable() { return super.isResolvable() && mp.getTo() != null; - }; + } @Override boolean resolve() @@@ -690,7 -695,6 +700,6 @@@ } catch (Exception foo) { } - ; jout.close(); } catch (Exception ex) { @@@ -752,9 -756,10 +761,10 @@@ try { // create backupfiles object and get new temp filename destination - BackupFiles backupfiles = new BackupFiles(jarFile); - FileOutputStream fos = new FileOutputStream( - backupfiles.getTempFilePath()); + boolean doBackup = BackupFiles.getEnabled(); + BackupFiles backupfiles = doBackup ? new BackupFiles(jarFile) : null; + FileOutputStream fos = new FileOutputStream(doBackup ? + backupfiles.getTempFilePath() : jarFile); JarOutputStream jout = new JarOutputStream(fos); List frames = new ArrayList<>(); @@@ -775,12 -780,14 +785,14 @@@ } catch (Exception foo) { } jout.close(); boolean success = true; - backupfiles.setWriteSuccess(success); - success = backupfiles.rollBackupsAndRenameTempFile(); + if (doBackup) + { + backupfiles.setWriteSuccess(success); + success = backupfiles.rollBackupsAndRenameTempFile(); + } return success; } catch (Exception ex) @@@ -1092,17 -1099,15 +1104,17 @@@ if (!storeDS && !viewIds.contains(viewId)) { viewIds.add(viewId); - try + File viewerState = viewFrame.saveSession(); + if (viewerState != null) { - String viewerState = viewFrame.getStateInfo(); - writeJarEntry(jout, getViewerJarEntryName(viewId), - viewerState.getBytes()); - } catch (IOException e) + copyFileToJar(jout, viewerState.getPath(), + getViewerJarEntryName(viewId)); + } + else { - System.err.println( - "Error saving viewer state: " + e.getMessage()); + Cache.log.error("Failed to save viewer state for " + + + viewFrame.getViewerType().toString()); } } } @@@ -1671,6 -1676,7 +1683,7 @@@ // using save and then load try { + fileName = fileName.replace('\\', '/'); System.out.println("Writing jar entry " + fileName); JarEntry entry = new JarEntry(fileName); jout.putNextEntry(entry); @@@ -1999,23 -2005,32 +2012,23 @@@ protected void copyFileToJar(JarOutputStream jout, String infilePath, String jarEntryName) { - DataInputStream dis = null; - try + try (InputStream is = new FileInputStream(infilePath)) { File file = new File(infilePath); if (file.exists() && jout != null) { - dis = new DataInputStream(new FileInputStream(file)); - byte[] data = new byte[(int) file.length()]; - dis.readFully(data); - writeJarEntry(jout, jarEntryName, data); + System.out.println("Writing jar entry " + jarEntryName); + jout.putNextEntry(new JarEntry(jarEntryName)); + copyAll(is, jout); + jout.closeEntry(); + // dis = new DataInputStream(new FileInputStream(file)); + // byte[] data = new byte[(int) file.length()]; + // dis.readFully(data); + // writeJarEntry(jout, jarEntryName, data); } } catch (Exception ex) { ex.printStackTrace(); - } finally - { - if (dis != null) - { - try - { - dis.close(); - } catch (IOException e) - { - // ignore - } - } } } @@@ -2032,6 -2047,7 +2045,7 @@@ { if (jout != null) { + jarEntryName = jarEntryName.replace('\\','/'); System.out.println("Writing jar entry " + jarEntryName); jout.putNextEntry(new JarEntry(jarEntryName)); DataOutputStream dout = new DataOutputStream(jout); @@@ -2042,24 -2058,6 +2056,24 @@@ } /** + * Copies input to output, in 4K buffers; handles any data (text or binary) + * + * @param in + * @param out + * @throws IOException + */ + protected void copyAll(InputStream in, OutputStream out) + throws IOException + { + byte[] buffer = new byte[4096]; + int bytesRead = 0; + while ((bytesRead = in.read(buffer)) != -1) + { + out.write(buffer, 0, bytesRead); + } + } + + /** * Save the state of a structure viewer * * @param ap @@@ -2126,7 -2124,7 +2140,7 @@@ final String viewId = viewFrame.getViewId(); state.setViewId(viewId); state.setAlignwithAlignPanel(viewFrame.isUsedforaligment(ap)); - state.setColourwithAlignPanel(viewFrame.isUsedforcolourby(ap)); + state.setColourwithAlignPanel(viewFrame.isUsedForColourBy(ap)); state.setColourByJmol(viewFrame.isColouredByViewer()); state.setType(viewFrame.getViewerType().toString()); // pdb.addStructureState(state); @@@ -2510,7 -2508,7 +2524,7 @@@ vamsasSeq.setName(jds.getName()); vamsasSeq.setSequence(jds.getSequenceAsString()); vamsasSeq.setDescription(jds.getDescription()); - jalview.datamodel.DBRefEntry[] dbrefs = null; + List dbrefs = null; if (jds.getDatasetSequence() != null) { vamsasSeq.setDsseqid(seqHash(jds.getDatasetSequence())); @@@ -2532,20 -2530,20 +2546,20 @@@ */ if (dbrefs != null) { - for (int d = 0; d < dbrefs.length; d++) + for (int d = 0, nd = dbrefs.size(); d < nd; d++) { DBRef dbref = new DBRef(); - DBRefEntry dbRefEntry = dbrefs[d]; - dbref.setSource(dbRefEntry.getSource()); - dbref.setVersion(dbRefEntry.getVersion()); - dbref.setAccessionId(dbRefEntry.getAccessionId()); - if (dbRefEntry instanceof GeneLocus) + DBRefEntry ref = dbrefs.get(d); + dbref.setSource(ref.getSource()); + dbref.setVersion(ref.getVersion()); + dbref.setAccessionId(ref.getAccessionId()); + if (ref instanceof GeneLocus) { dbref.setLocus(true); } - if (dbRefEntry.hasMap()) + if (ref.hasMap()) { - Mapping mp = createVamsasMapping(dbRefEntry.getMap(), parentseq, + Mapping mp = createVamsasMapping(ref.getMap(), parentseq, jds, recurse); dbref.setMapping(mp); } @@@ -2740,7 -2738,7 +2754,7 @@@ * @param file * - HTTP URL or filename */ - public AlignFrame loadJalviewAlign(final String file) + public AlignFrame loadJalviewAlign(final Object file) { jalview.gui.AlignFrame af = null; @@@ -2774,7 -2772,7 +2788,7 @@@ public void run() { setLoadingFinishedForNewStructureViewers(); - }; + } }); } catch (Exception x) { @@@ -2784,44 -2782,52 +2798,52 @@@ return af; } - private jarInputStreamProvider createjarInputStreamProvider( - final String file) throws MalformedURLException - { - URL url = null; - errorMessage = null; - uniqueSetSuffix = null; - seqRefIds = null; - viewportsAdded.clear(); - frefedSequence = null; - - if (file.startsWith("http://")) - { - url = new URL(file); - } - final URL _url = url; - return new jarInputStreamProvider() - { - - @Override - public JarInputStream getJarInputStream() throws IOException - { - if (_url != null) - { - return new JarInputStream(_url.openStream()); - } - else - { - return new JarInputStream(new FileInputStream(file)); - } - } - - @Override - public String getFilename() - { - return file; - } - }; - } + @SuppressWarnings("unused") + private jarInputStreamProvider createjarInputStreamProvider(final Object ofile) throws MalformedURLException { + + // BH 2018 allow for bytes already attached to File object + try { + String file = (ofile instanceof File ? ((File) ofile).getCanonicalPath() : ofile.toString()); + byte[] bytes = Platform.isJS() ? Platform.getFileBytes((File) ofile) + : null; + URL url = null; + errorMessage = null; + uniqueSetSuffix = null; + seqRefIds = null; + viewportsAdded.clear(); + frefedSequence = null; + + if (file.startsWith("http://")) { + url = new URL(file); + } + final URL _url = url; + return new jarInputStreamProvider() { + + @Override + public JarInputStream getJarInputStream() throws IOException { + if (bytes != null) { + // System.out.println("Jalview2XML: opening byte jarInputStream for bytes.length=" + bytes.length); + return new JarInputStream(new ByteArrayInputStream(bytes)); + } + if (_url != null) { + // System.out.println("Jalview2XML: opening url jarInputStream for " + _url); + return new JarInputStream(_url.openStream()); + } else { + // System.out.println("Jalview2XML: opening file jarInputStream for " + file); + return new JarInputStream(new FileInputStream(file)); + } + } + + @Override + public String getFilename() { + return file; + } + }; + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } /** * Recover jalview session from a jalview project archive. Caller may @@@ -2863,9 -2869,6 +2885,6 @@@ if (jarentry != null && jarentry.getName().endsWith(".xml")) { - InputStreamReader in = new InputStreamReader(jin, UTF_8); - // JalviewModel object = new JalviewModel(); - JAXBContext jc = JAXBContext .newInstance("jalview.xml.binding.jalview"); XMLStreamReader streamReader = XMLInputFactory.newInstance() @@@ -2875,11 -2878,6 +2894,6 @@@ .unmarshal(streamReader, JalviewModel.class); JalviewModel object = jbe.getValue(); - /* - Unmarshaller unmar = new Unmarshaller(object); - unmar.setValidation(false); - object = (JalviewModel) unmar.unmarshal(in); - */ if (true) // !skipViewport(object)) { _af = loadFromObject(object, file, true, jprovider); @@@ -3187,6 -3185,8 +3201,6 @@@ protected String copyJarEntry(jarInputStreamProvider jprovider, String jarEntryName, String prefix, String suffixModel) { - BufferedReader in = null; - PrintWriter out = null; String suffix = ".tmp"; if (suffixModel == null) { @@@ -3197,24 -3197,33 +3211,24 @@@ { suffix = "." + suffixModel.substring(sfpos + 1); } - try - { - JarInputStream jin = jprovider.getJarInputStream(); - /* - * if (jprovider.startsWith("http://")) { jin = new JarInputStream(new - * URL(jprovider).openStream()); } else { jin = new JarInputStream(new - * FileInputStream(jprovider)); } - */ + try (JarInputStream jin = jprovider.getJarInputStream()) + { JarEntry entry = null; do { entry = jin.getNextJarEntry(); } while (entry != null && !entry.getName().equals(jarEntryName)); + if (entry != null) { - in = new BufferedReader(new InputStreamReader(jin, UTF_8)); + // in = new BufferedReader(new InputStreamReader(jin, UTF_8)); File outFile = File.createTempFile(prefix, suffix); outFile.deleteOnExit(); - out = new PrintWriter(new FileOutputStream(outFile)); - String data; - - while ((data = in.readLine()) != null) + try (OutputStream os = new FileOutputStream(outFile)) { - out.println(data); + copyAll(jin, os); } - out.flush(); String t = outFile.getAbsolutePath(); return t; } @@@ -3225,6 -3234,22 +3239,6 @@@ } catch (Exception ex) { ex.printStackTrace(); - } finally - { - if (in != null) - { - try - { - in.close(); - } catch (IOException e) - { - // ignore - } - } - if (out != null) - { - out.close(); - } } return null; @@@ -4403,46 -4428,29 +4417,46 @@@ * From 2.9: stateData.type contains JMOL or CHIMERA, data is in jar entry * "viewer_"+stateData.viewId */ - if (ViewerType.CHIMERA.toString().equals(stateData.getType())) + String type = stateData.getType(); + if (type == null) { - createChimeraViewer(viewerData, af, jprovider); + type = ViewerType.JMOL.toString(); } - else + try { - /* - * else Jmol (if pre-2.9, stateData contains JMOL state string) - */ - createJmolViewer(viewerData, af, jprovider); + ViewerType viewerType = ViewerType.valueOf(type); + switch (viewerType) + { + case CHIMERA: + createChimeraViewer(viewerData, af, jprovider, false); + break; + case CHIMERAX: + createChimeraViewer(viewerData, af, jprovider, true); + break; + case PYMOL: + createPymolViewer(viewerData, af, jprovider); + break; + case JMOL: + createJmolViewer(viewerData, af, jprovider); + } + } catch (IllegalArgumentException | NullPointerException e) + { + Cache.log.error( + "Invalid structure viewer type: " + type); } } /** - * Create a new Chimera viewer. + * Create a new Chimera or ChimeraX viewer * * @param data * @param af * @param jprovider + * @param isChimeraX */ protected void createChimeraViewer( Entry viewerData, AlignFrame af, - jarInputStreamProvider jprovider) + jarInputStreamProvider jprovider, boolean isChimeraX) { StructureViewerModel data = viewerData.getValue(); String chimeraSessionFile = data.getStateData(); @@@ -4454,11 -4462,8 +4468,11 @@@ * 'uniquified' sviewid used to reconstruct the viewer here */ String viewerJarEntryName = getViewerJarEntryName(data.getViewId()); + String extension = isChimeraX + ? JalviewChimeraXBindingModel.CHIMERAX_SESSION_EXTENSION + : JalviewChimeraBinding.CHIMERA_SESSION_EXTENSION; chimeraSessionFile = copyJarEntry(jprovider, viewerJarEntryName, - "chimera", ".py"); + "chimera", extension); Set> fileData = data.getFileData() .entrySet(); @@@ -4484,13 -4489,9 +4498,13 @@@ .toArray(new SequenceI[allseqs.size()][]); String newViewId = viewerData.getKey(); - ChimeraViewFrame cvf = new ChimeraViewFrame(chimeraSessionFile, - af.alignPanel, pdbArray, seqsArray, colourByChimera, - colourBySequence, newViewId); + ChimeraViewFrame cvf = isChimeraX + ? new ChimeraXViewFrame(chimeraSessionFile, af.alignPanel, + pdbArray, seqsArray, colourByChimera, colourBySequence, + newViewId) + : new ChimeraViewFrame(chimeraSessionFile, af.alignPanel, + pdbArray, seqsArray, colourByChimera, colourBySequence, + newViewId); cvf.setSize(data.getWidth(), data.getHeight()); cvf.setLocation(data.getX(), data.getY()); } @@@ -4867,7 -4868,18 +4881,18 @@@ { AlignFrame af = null; af = new AlignFrame(al, safeInt(view.getWidth()), - safeInt(view.getHeight()), uniqueSeqSetId, viewId); + safeInt(view.getHeight()), uniqueSeqSetId, viewId) + // { + // + // @Override + // protected void processKeyEvent(java.awt.event.KeyEvent e) { + // System.out.println("Jalview2XML AF " + e); + // super.processKeyEvent(e); + // + // } + // + // } + ; af.setFileName(file, FileFormat.Jalview); @@@ -6348,61 -6360,6 +6373,61 @@@ } /** + * Create a new PyMol viewer + * + * @param data + * @param af + * @param jprovider + */ + protected void createPymolViewer( + Entry viewerData, AlignFrame af, + jarInputStreamProvider jprovider) + { + StructureViewerModel data = viewerData.getValue(); + String pymolSessionFile = data.getStateData(); + + /* + * Copy PyMol session from jar entry "viewer_"+viewId to a temporary file + * + * NB this is the 'saved' viewId as in the project file XML, _not_ the + * 'uniquified' sviewid used to reconstruct the viewer here + */ + String viewerJarEntryName = getViewerJarEntryName(data.getViewId()); + pymolSessionFile = copyJarEntry(jprovider, viewerJarEntryName, + "pymol", ".pse"); + + Set> fileData = data.getFileData() + .entrySet(); + List pdbs = new ArrayList<>(); + List allseqs = new ArrayList<>(); + for (Entry pdb : fileData) + { + String filePath = pdb.getValue().getFilePath(); + String pdbId = pdb.getValue().getPdbId(); + // pdbs.add(new PDBEntry(filePath, pdbId)); + pdbs.add(new PDBEntry(pdbId, null, PDBEntry.Type.PDB, filePath)); + final List seqList = pdb.getValue().getSeqList(); + SequenceI[] seqs = seqList.toArray(new SequenceI[seqList.size()]); + allseqs.add(seqs); + } + + boolean colourByPymol = data.isColourByViewer(); + boolean colourBySequence = data.isColourWithAlignPanel(); + + // TODO use StructureViewer as a factory here, see JAL-1761 + final PDBEntry[] pdbArray = pdbs.toArray(new PDBEntry[pdbs.size()]); + final SequenceI[][] seqsArray = allseqs + .toArray(new SequenceI[allseqs.size()][]); + String newViewId = viewerData.getKey(); + + PymolViewer pv = new PymolViewer(pymolSessionFile, + af.alignPanel, pdbArray, seqsArray, colourByPymol, + colourBySequence, newViewId); + pv.setSize(data.getWidth(), data.getHeight()); + pv.setLocation(data.getX(), data.getY()); + } + + /** * Populates an XML model of the feature colour scheme for one feature type * * @param featureType diff --combined test/jalview/structure/StructureSelectionManagerTest.java index b86e91f,e59648f..9b240d3 --- a/test/jalview/structure/StructureSelectionManagerTest.java +++ b/test/jalview/structure/StructureSelectionManagerTest.java @@@ -124,10 -124,10 +124,10 @@@ public class StructureSelectionManagerT acf3.addMap(new Sequence("s3", "ttt"), new Sequence("p3", "p"), new MapList(new int[] { 1, 3 }, new int[] { 1, 1 }, 1, 1)); - List set1 = new ArrayList(); + List set1 = new ArrayList<>(); set1.add(acf1); set1.add(acf2); - List set2 = new ArrayList(); + List set2 = new ArrayList<>(); set2.add(acf2); set2.add(acf3); @@@ -218,7 -218,7 +218,7 @@@ assertEquals(1, pmap.getSeqs().size()); assertEquals("4IM2|A", pmap.getSeqs().get(0).getName()); - List structuremap1 = new ArrayList( + List structuremap1 = new ArrayList<>( sm.getMapping(P4IM2_MISSING)[0] .getPDBResNumRanges(seq.getStart(), seq.getEnd())); @@@ -313,7 -313,8 +313,7 @@@ // positional mapping to atoms for color by structure is still wrong, even // though panel looks correct. - StructureMappingcommandSet smcr[] = JmolCommands - .getColourBySequenceCommand(apssm, + String[] smcr = new JmolCommands().colourBySequence(apssm, new String[] { pdbe.getFile() }, new SequenceI[][] @@@ -321,10 -322,12 +321,10 @@@ new SequenceRenderer(alf.alignPanel.getAlignViewport()), alf.alignPanel); // Expected - all residues are white - for (StructureMappingcommandSet smm : smcr) + for (String c : smcr) { - for (String c : smm.commands) - { - System.out.println(c); - } + assertTrue(c.contains("color[255,255,255]")); + System.out.println(c); } } @@@ -415,7 -418,7 +415,7 @@@ PDBID); AlignmentAnnotation subseq_tf=null; - assertTrue(seq.getDBRefs() != null && seq.getDBRefs().length > 0); + assertTrue(seq.getDBRefs() != null && seq.getDBRefs().size() > 0); if (!al.findAnnotations(seq, null, TEMP_FACTOR_AA).iterator().hasNext()) {