package aliview.messenges; import java.awt.Component; import java.awt.Dialog.ModalityType; import java.awt.Dimension; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import javax.swing.JCheckBox; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JOptionPane; import org.apache.log4j.Logger; import utils.DialogUtils; import aliview.AliView; import aliview.AliViewWindow; import aliview.AminoAcid; import aliview.gui.AliViewJMenuBar; import aliview.settings.Settings; public class Messenger { private static final String LF = System.getProperty("line.separator"); private static final Logger logger = Logger.getLogger(Messenger.class); public static final Message SAVE_NOT_POSSIBLE_TRY_SAVE_AS = new Message("Not possible to save, try Save as....", "Sorry...."); public static final Message NO_SELECTION = new Message("Nothing selected...", "No selection"); public static Message NO_FASTA_IN_CLIPBOARD = new Message("Could not find fasta sequences in clipboard (name has to start with >)", "No fasta sequences"); public static Message NO_FASTA_OR_FILE_IN_CLIPBOARD = new Message("Could not find fasta sequences (name has to start with >)" + LF + "- or a valid alignment file name in clipboard.", "No sequences"); public static Message ALIGNER_SOMETHING_PROBLEM_ERROR = new Message("Something did not work out when aligning.", "Problem when aligning"); public static Message NO_FULLY_SELECTED_SEQUENCES = new Message("There are no fully selected sequences - if you only want to realign" + LF + "a part of sequence, select \"Realign selected block\" instead.", "No selected sequence"); public static Message COULD_NOT_OPEN_HELP_IN_BROWSER = new Message("Could not open help file in browser, help is available at: " + Settings.getAliViewHelpWebPage(), "Problem when aligning"); public static Message OUT_OF_MEMORY_ERROR = new Message("Out of memory error - you can probably still save your work as it is." + LF + // "One source of this error is the number of undo-steps preserved - you can change this in Settings." + LF + "If you want to increase memory available for AliView, see: " + Settings.getAliViewHelpWebPage(), "Out of memory"); public static Message ONLY_VIEW_WHEN_FILESEQUENCES = new Message("Edit capabilities are limited when large alignment is read from file" + LF + "You can delete and rearange sequences." + LF + "If you need full editing capabilities then you can increase " + LF + "AliView memory settings under menu \"Preferences\". Memory " + LF + "needed is 2 x file size if files are to be read into memory." + LF + " ", "Limited edit capabilities"); public static Message MUSCLE_PROFILE_INFO_MESSAGE = new Message("MUSCLE \"-profile\" command is used for adding new sequences" + LF + "to the alignment. The performance of this method might be" + LF + "less favourable than some other add sequences algorithms." + LF + "See for example Löytynoja et al (2012) and Katoh & Frith (2012)" + LF + "One option is to download and install MAFFT and then use the" + LF + "MAFFT -addfragments algorithm instead.", "Add sequences with MUSCLE profile"); public static final Message LIMITED_UNDO_CAPABILITIES = new Message("The size of the alignment prevents Undo functionality when editing." + LF + "- Don't forget to 'Save As' every once in a while....", "Undo function disabled"); public static final Message NO_PRIMERS_FOUND = new Message("Could not find any primers in selected region with current settings." + LF + "Try adjusting \"Find primer settings\" or try another selection." + LF + "Note that characters n or ? will greatly reduce the possibility" + LF + "of finding primers", "No primers found"); public static final Message EDIT_MODE_QUESTION = new Message("Edit key/menu pressed (or mouse edit), " + LF + "do you want to allow edits?" + LF + "", "Edit mode?"); public static final Message FILE_OPEN_NOT_EXISTS = new Message("Could not open file (does not exist).", "File not found"); public static final Message COMPLEMENT_FUNCTION_ERROR = new Message("Error in reverse complement function: ", "Problem"); public static final Message FILE_SAVE_ERROR = new Message("Error saving file: ", "File save problem"); public static final Message ERROR_PASTE = new Message("Error pasting: ", "Problem"); public static final Message UNDO_REDO_PROBLEM = new Message("Error in undo/redo function: ", "Problem"); public static final Message ERROR_RUNNING_EXTERNAL_COMMAND = new Message("Error running external command: ", "Problem"); public static final Message ERROR_PRINTING = new Message("Error in print function: "); public static final Message OPEN_LARGE_FILE_ERROR = new Message("Error when trying to open large file:" + LF + "One source of problem could be if you are running a 32-bit OS." + LF + "Opening large files are mainly tested on 64-bit OS" + LF + "Another problem could be if your Java version is 32-bit although" + LF + "your OS is 64-bit, in this case you could download and install latest 64-bit Java." + LF + "Another solution is if you can increase memory for AliView so that alignment is" + LF + "loaded into memory and not residing on file. See setting memory in Program Preferences.", "Problem"); public static final Message FILE_ERROR = new Message("Error when reading file:", "Problem"); public static final Message ALIGNMENT_META_READ_ERROR = new Message("Error during import alignment metadata: ", "Problem"); public static final Message ALIGNMENT_IMPORT_ERROR = new Message("Could not Import alignment: ", "Import problem"); public static final Message TO_BIG_SELECTION_FOR_COPY = new Message("Selection is to big to Copy", "To bil selection"); public static final Message NO_FASTA_INDEX_COULD_BE_SAVED = new Message("Could not save Fasta index file: Alignment has to be indexed" + LF + "from file when loaded and in Fasta format", "Problem"); public static final Message REALIGN_EVERYTHING = new Message("Are you sure you want to realign the whole alignment?", "Realign everything"); public static final Message PHENOTYPE_IMAGE_OPEN_ERROR = new Message("Could not create Phenotype from Image file. Wrong file type? (png,jpg)", "Wrong file"); public static final Message SUGGEST_ALIGN_AS_TRANSLATED = new Message("If you want to align Nucleotides as translated Amino Acids, please use function:" + LF + "Realign everything as Translated Amino Acids", "Can not realign"); private static int lastSelectedOption = -1; private static boolean showedMaxJPanelSizeMessageOnceThisSession; public static void main(String[] args) { boolean cbxSelected = showOKOnlyMessageWithCbx(MUSCLE_PROFILE_INFO_MESSAGE, true, null); logger.info("cbxSelected" + cbxSelected); } public static void showGeneralErrorMessage(Error error, JFrame parentFrame) { Message GENERAL_ERROR = new Message("Error (you can probably still save work as it is)" + LF + "Description: " + error.getMessage(), "Error"); showOKOnlyMessage(GENERAL_ERROR, parentFrame); } public static void showGeneralExceptionMessage(Exception exception, JFrame parentFrame) { Message GENERAL_ERROR = new Message("Exception (you can probably still save work as it is)" + LF + "Description: " + exception.getMessage(), "Exception"); showOKOnlyMessage(GENERAL_ERROR, parentFrame); } public static void showOKOnlyMessage(Message message, JFrame parentFrame) { showOKOnlyMessage(message, "", parentFrame); } public static void showOKOnlyMessage(Message message) { showOKOnlyMessage(message, "", AliView.getActiveWindow()); } public static void showOKOnlyMessage(Message message, String appendMessageText) { showOKOnlyMessage(message, appendMessageText, AliView.getActiveWindow()); } public static void showOKOnlyMessage(Message message, String appendMessageText, JFrame parentFrame) { final JDialog dialog = new JDialog(parentFrame); dialog.setTitle(message.title); // OBS DO NOT MODAL - Then there is problem in MAC when executed from error thread dialog.setModal(false); dialog.setAlwaysOnTop(true); String messageText = message.text + appendMessageText; JOptionPane optPane = new JOptionPane(messageText,JOptionPane.INFORMATION_MESSAGE); optPane.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent e) { if (e.getPropertyName().equals("value")) { switch ((Integer)e.getNewValue()) { case JOptionPane.OK_OPTION: //user clicks OK break; case JOptionPane.CANCEL_OPTION: //user clicks CANCEL break; } dialog.dispose(); } } }); dialog.setContentPane(optPane); dialog.pack(); dialog.setLocationRelativeTo(parentFrame); dialog.setVisible(true); //JOptionPane.showMessageDialog(aliViewWindow,message.text,message.title, JOptionPane.INFORMATION_MESSAGE); } public static int getLastSelectedOption() { return lastSelectedOption; } /* * * TODO this method should not be all static - due to problem with multiple dialogs and static variable (lastSelected) * */ public static boolean showOKOnlyMessageWithCbx(Message message, boolean cbxSelected, AliViewWindow aliViewWindow) { final JDialog dialog = new JDialog(aliViewWindow); dialog.setTitle(message.title); // OBS DO NOT MODAL - Then there is problem in MAC when executed from error thread dialog.setModal(true); dialog.setAlwaysOnTop(true); JCheckBox cbx = new JCheckBox("Don't show this message again (can be undone in Preferences)"); cbx.setSelected(cbxSelected); cbx.setFocusPainted(false); JOptionPane optPane = new JOptionPaneWithCheckbox(cbx, message.text,JOptionPane.INFORMATION_MESSAGE); optPane.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent e) { if (e.getPropertyName().equals("value")) { switch ((Integer)e.getNewValue()) { case JOptionPane.OK_OPTION: lastSelectedOption = JOptionPane.OK_OPTION; break; case JOptionPane.CANCEL_OPTION: lastSelectedOption = JOptionPane.CANCEL_OPTION; break; } dialog.dispose(); } } }); dialog.setContentPane(optPane); // TODO make sure dialogs does not become larger than screen size dialog.setMaximumSize(new Dimension(800,600)); dialog.setPreferredSize(new Dimension(800,600)); dialog.pack(); logger.debug("dialog.getPreferredSize()" + dialog.getPreferredSize()); dialog.setLocationRelativeTo(aliViewWindow); dialog.setVisible(true); return cbx.isSelected(); } public static boolean showOKCancelMessageWithCbx(Message message, boolean cbxSelected, AliViewWindow aliViewWindow) { final JDialog dialog = new JDialog(aliViewWindow); dialog.setTitle(message.title); // OBS DO NOT MODAL - Then there is problem in MAC when executed from error thread dialog.setModal(true); dialog.setAlwaysOnTop(true); JCheckBox cbx = new JCheckBox("Don't show this message again (can be undone in Preferences)"); cbx.setSelected(cbxSelected); cbx.setFocusPainted(false); JOptionPane optPane = new JOptionPaneWithCheckbox(cbx, message.text,JOptionPane.INFORMATION_MESSAGE, JOptionPane.OK_CANCEL_OPTION); optPane.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent e) { if (e.getPropertyName().equals("value")) { switch ((Integer)e.getNewValue()) { case JOptionPane.OK_OPTION: lastSelectedOption = JOptionPane.OK_OPTION; break; case JOptionPane.CANCEL_OPTION: lastSelectedOption = JOptionPane.CANCEL_OPTION; break; } // dialog.setModal(false); dialog.dispose(); } } }); dialog.setContentPane(optPane); dialog.pack(); dialog.setLocationRelativeTo(aliViewWindow); dialog.setVisible(true); //dialog.setModal(false); return cbx.isSelected(); //return dialog; } public static void showCountStopCodonMessage(int count, AliViewWindow aliViewWindow) { Message countMessage = new Message("Stop codons in alignment: " + count, "Stop codon count"); showOKOnlyMessage(countMessage, aliViewWindow); } public static void showDuplicateSeqNamesMessage(ArrayList<String> dupeNames){ boolean hideMessage = Settings.getHideDuplicateSeqNamesMessage().getBooleanValue(); if(! hideMessage){ String dupeString = ""; int dupeCount = 0; for(String dupe: dupeNames){ dupeString += dupe + LF; // Only list 10 names dupeCount ++; if(dupeCount == 10){ break; } } String prep = "are"; if(dupeCount == 1){ prep = "is"; } String dupeCountString = ""; if(dupeCount == 10){ dupeCountString = "at least 10"; }else{ dupeCountString = "" + dupeCount; } Message dupeMessage = new Message("There " + prep + " " + dupeCountString + " duplicate sequence name(s) in alignment, this might cause " + LF + "unexpected problems when calling alignment programs for example." + LF + "Duplicate sequences will be selected in alignment." + LF + "Duplicate name(s) " + prep + ": " + dupeString, "Duplicate sequence names"); boolean hideMessageNextTime = showOKOnlyMessageWithCbx(dupeMessage, hideMessage, AliView.getActiveWindow()); Settings.getHideDuplicateSeqNamesMessage().putBooleanValue(hideMessageNextTime); } } public static boolean showHideAlignmentProgramInvalidCharsInfoMessage(String invalidChars){ boolean hideMessage = Settings.getHideAlignmentProgramInvalidCharsInfoMessage().getBooleanValue(); if(! hideMessage){ Message invalCharMessage = new Message("Some aligners (e.g. Muscle, Mafft) are sensiteive to invalid characters," + LF + "the following were found: " + invalidChars + LF + "and you might need to replace them with X in your alignment.", "Problem characters"); boolean hideMessageNextTime = showOKCancelMessageWithCbx(invalCharMessage, hideMessage, AliView.getActiveWindow()); Settings.getHideAlignmentProgramInvalidCharsInfoMessage().putBooleanValue(hideMessageNextTime); } return hideMessage; } public static void showMaxJPanelSizeMessageOnceThisSession(){ if(! showedMaxJPanelSizeMessageOnceThisSession){ Message maxSizeMessage = new Message("The maximum size of the viewable area is 2147483647 pixels" + LF + "The current character-size is to large if you want to view" + LF + "the last residues, try decreasing the character size if you" + LF + "are missing residues at the end of alignment", "Max size"); showOKOnlyMessage(maxSizeMessage); showedMaxJPanelSizeMessageOnceThisSession = true; } } public static boolean askAllowEditMode() { boolean allowEditMode = false; boolean hideMessage = Settings.getHideAskBeforeEditMode().getBooleanValue(); if(hideMessage){ allowEditMode = true; }else{ boolean hideMessageNextTime = showOKCancelMessageWithCbx(EDIT_MODE_QUESTION, hideMessage, AliView.getActiveWindow()); Settings.getHideAskBeforeEditMode().putBooleanValue(hideMessageNextTime); if(getLastSelectedOption() == JOptionPane.OK_OPTION){ allowEditMode = true; } } return allowEditMode; } public static void showEditCharsetExceptionMessage(Exception exception, JFrame parentFrame) { Message charsetExceptionMessage = new Message("Could not parse the charsets text:" + LF + exception.getMessage(), "Parse charset text exception"); showOKOnlyMessage(charsetExceptionMessage, parentFrame); } } class Message{ String title; String text; public Message(String text, String title) { this.title = title; this.text = text; } public Message(String text) { this(text,""); } }