package aliview; import java.awt.AWTException; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.ComponentOrientation; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.MouseInfo; import java.awt.Point; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.Robot; import java.awt.Toolkit; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.DnDConstants; import java.awt.dnd.DropTargetDropEvent; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.awt.print.Book; import java.awt.print.PageFormat; import java.awt.print.Paper; import java.awt.print.Printable; import java.awt.print.PrinterException; import java.awt.print.PrinterJob; import java.io.BufferedWriter; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.Stack; import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; import javax.swing.AbstractAction; import javax.swing.AbstractButton; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.ButtonModel; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBoxMenuItem; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollBar; import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.JSplitPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.JToggleButton; import javax.swing.JToolBar; import javax.swing.JViewport; import javax.swing.KeyStroke; import javax.swing.RepaintManager; import javax.swing.SwingUtilities; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.ListDataEvent; import javax.swing.event.ListSelectionListener; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Appender; import org.apache.log4j.FileAppender; import org.apache.log4j.Level; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import utils.DialogUtils; import utils.FileUtilities; import utils.OSNativeUtils; import utils.nexus.CharSet; import utils.nexus.CodonPos; import utils.nexus.NexusUtilities; import aliview.aligner.Aligner; import aliview.aligner.AlignerADDItemsFrame; import aliview.aligner.AlignerALLItemsFrame; import aliview.alignment.Alignment; import aliview.alignment.AlignmentEvent; import aliview.alignment.AlignmentFile; import aliview.alignment.AlignmentMeta; import aliview.alignment.AlignmentListener; import aliview.color.ColorScheme; import aliview.exporter.ImageExporter; import aliview.externalcommands.CommandItem; import aliview.externalcommands.ExternalCommandExecutor; import aliview.gui.AliToolBar; import aliview.gui.AliViewJMenuBar; import aliview.gui.AliViewJMenuBarFactory; import aliview.gui.AlignmentPopupMenu; import aliview.gui.AppIcons; import aliview.gui.GlassPaneKeyListener; import aliview.gui.GlassPaneMouseListener; import aliview.gui.ListTopOffsetJPanel; import aliview.gui.MessageLogFrame; import aliview.gui.ScrollBarModelSyncChangeListener; import aliview.gui.SearchPanel; import aliview.gui.StatusPanel; import aliview.gui.TextEditDialog; import aliview.gui.TextEditFrame; import aliview.gui.TextEditPanel; import aliview.gui.TextEditPanelCharsets; import aliview.gui.TranslationToolPanel; import aliview.gui.pane.AlignmentPane; import aliview.gui.pane.CharPixels; import aliview.gui.pane.InvalidAlignmentPositionException; import aliview.gui.pane.NotUsed_AlignmentPane_Orig; import aliview.importer.AlignmentFactory; import aliview.importer.AlignmentImportException; import aliview.importer.FileFormat; import aliview.importer.FileImportUtils; import aliview.importer.SequencesFactory; import aliview.messenges.Messenger; import aliview.old.ExternalCmdFrame; import aliview.old.MyScrollPane; import aliview.phenotype2genotype.Phenotype2Genootype; import aliview.primer.Primer; import aliview.primer.PrimerResultsFrame; import aliview.sequencelist.AlignmentDataEvent; import aliview.sequencelist.AlignmentDataListener; import aliview.sequencelist.AlignmentSelectionEvent; import aliview.sequencelist.AlignmentSelectionListener; import aliview.sequencelist.FilePage; import aliview.sequencelist.FileSequenceAlignmentListModel; import aliview.sequencelist.FindObject; import aliview.sequencelist.SequenceJList; import aliview.sequencelist.AlignmentListModel; import aliview.sequencelist.SequenceListMouseListener; import aliview.sequencelist.SequenceListMouseWheelListener; import aliview.sequencelist.SequenceListSelectionModel; import aliview.sequences.Sequence; import aliview.sequences.SequenceUtils; import aliview.settings.Settings; import aliview.settings.SettingsFrame; import aliview.settings.PrimerSettingsPanel; import aliview.subprocesses.SubProcessWindow; import aliview.test.RubberBandingListener; import aliview.undo.UndoSavedState; import aliview.undo.UndoSavedStateEditedSequences; import aliview.undo.UndoSavedStateEverything; import aliview.undo.UndoSavedStateMetaOnly; import aliview.undo.UndoSavedStateSequenceOrder; import aliview.utils.FileDrop; import aliview.utils.Utils; import aliview.utils.FileDrop.Listener; public class AliViewWindow extends JFrame implements UndoControler, AlignmentListener, AlignmentSelectionListener, AlignmentDataListener, Printable{ private static final String LF = System.getProperty("line.separator"); private static final Logger logger = Logger.getLogger(AliViewWindow.class); private static final SequencesFactory seqFactory = new SequencesFactory(); private AliViewWindow aliViewWindow; private Preferences prefs = Preferences.userNodeForPackage(AliViewWindow.class); private static final Rectangle DEFAULT_WIN_GEOMETRY = new Rectangle(20,20,600,400); protected JViewport viewport; protected AlignmentPane alignmentPane; // MyScrollPane JScrollPane alignmentScrollPane; //JPanel alignmentAndRulerPanel; private SequenceJList sequenceJList; private Alignment alignment; private SearchPanel searchPanel; private StatusPanel statusPanel; private JTextField primer1txtField; private JTextField primer2txtField; private PrimerResultsFrame primerResultsFrame; private int nextNameFindSequenceNumber; // private LimitedStack<UndoSavedState> undoStack = new LimitedStack<UndoSavedState>(30); // private LimitedStack<UndoSavedState> redoStack = new LimitedStack<UndoSavedState>(30); // private Stack<UndoSavedState> undoStack = new Stack<UndoSavedState>(); // private Stack<UndoSavedState> redoStack = new Stack<UndoSavedState>(); UndoList undoList = new UndoList(); private boolean hasUnsavedUndoableEdits; private static Component glassPane; private AliViewJMenuBarFactory menuBarFactory; private JMenu mnFilePages; private UndoControler undoControler; private FindObject findObj; private AliCursor aliCursor = new AliCursor(0, 0); private JScrollPane listScrollPane; private ScrollBarModelSyncChangeListener scrollBarListener; private ButtonModel editModeModel; private AliViewJMenuBar aliViewMenuBar; // private AlignmentDataAndSelectionListener aliListener; private TranslationToolPanel translationPanel; private AliToolBar aliToolbar; private ListTopOffsetJPanel listTopOffset; private boolean hasNotifiedUserAboutLimitedUndo; /* public AliViewWindow(AliViewJMenuBarFactory menuBarFactory) { this(null, menuBarFactory); } */ private JPanel alignmentAndRulerPanel; private JPanel listAndTopOffset; private JPanel rulerPanel; public long getLastPaneEndTime(){ return alignmentPane.getEndTime(); } public AliViewWindow(File alignmentFile,AliViewJMenuBarFactory menuBarFactory) { this.aliViewWindow = this; this.menuBarFactory = menuBarFactory; // prepare glassPane glassPane = this.getGlassPane(); glassPane.addMouseListener(new GlassPaneMouseListener()); glassPane.addKeyListener(new GlassPaneKeyListener()); // try to Load alignment Alignment newAlignment = null; if(alignmentFile != null){ if(alignmentFile.exists()){ newAlignment = AlignmentFactory.createNewAlignment(alignmentFile); Settings.putLoadAlignmentDirectory(alignmentFile.getAbsoluteFile().getParent()); Settings.putLoadAlignmentDirectory(alignmentFile.getAbsoluteFile().getParent()); Settings.addRecentFile(alignmentFile); }else{ Messenger.showOKOnlyMessage(Messenger.FILE_OPEN_NOT_EXISTS, "Filename: " + alignmentFile, aliViewWindow); } }else{ logger.info("no file"); } // create empty alignment if it is still null after loading if(newAlignment == null){ logger.info("alignment was null creating new"); newAlignment = AlignmentFactory.createNewEmptyAlignment(); } // Create File drop handler new FileDrop( this.getRootPane(), true, new FileDrop.Listener(){ public void filesDropped( java.io.File[] files, DropTargetDropEvent evt ){ aliViewWindow.filesDropped(files, evt.getDropAction()); } // end filesDropped }); // end FileDrop.Listener // remember and restore geometry this.restoreWindowGeometry(); this.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { saveWindowGeometry(); } }); // Set close window accelerator Action closeWinAction = new AbstractAction() { public void actionPerformed(ActionEvent e) { AliView.closeWindow(aliViewWindow); } }; this.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(OSNativeUtils.getCloseWinKeyAccelerator(), "CloseWin"); this.getRootPane().getActionMap().put("CloseWin", closeWinAction); // Set focus next window accelerator // Action focusNextWinAction = new AbstractAction() { // public void actionPerformed(ActionEvent e) { // logger.info("focusNext"); // AliView.focusNextWin(); // } // }; // this.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(OSNativeUtils.getFocusNextWinKeyAccelerator(), "FocusNextWin"); // this.getRootPane().getActionMap().put("FocusNextWin", focusNextWinAction); // TODO maybe there are other keys in Mac to remove.... // remove F2 as edit key in JTable etc. Action doNothing = new AbstractAction() { public void actionPerformed(ActionEvent e) { logger.info("doing nothing"); } }; this.getRootPane().getInputMap().put(KeyStroke.getKeyStroke("F2"),"doNothing"); this.getRootPane().getActionMap().put("doNothing", doNothing); // Icon this.setIconImage(AppIcons.getProgramIconImage()); // Init dialog utilities with this frame DialogUtils.init(this); initWindow(newAlignment); } public void fileDropped(List<File> fileList, int dropAction) { // Convert list to array File[] filesArray = new File[ fileList.size() ]; fileList.toArray( filesArray ); filesDropped(filesArray, dropAction); } public void filesDropped(File[] files, int dropAction) { logger.info("DnDConstants.ACTION_COPY" + DnDConstants.ACTION_COPY); // Shift modifier = DnDConstants.ACTION_MOVE logger.info("DnDConstants.ACTION_MOVE" + DnDConstants.ACTION_MOVE); logger.info("dropAction" + dropAction); // On linux it is opposite if(OSNativeUtils.isLinuxOrUnix()){ if(dropAction == DnDConstants.ACTION_MOVE){ dropAction = DnDConstants.ACTION_COPY; }else if(dropAction == DnDConstants.ACTION_COPY){ dropAction = DnDConstants.ACTION_MOVE; } } // Action_MOVE = shift-drop = add file as fasta instead if(dropAction == DnDConstants.ACTION_COPY){ for(File droppedFile: files){ logger.info("file dropped"); addSequencesFromFile(droppedFile,0); // TODO only open one for now break; } } // Action_COPY = open new window else{ for(File droppedFile: files){ logger.info("file dropped"); AliView.openAlignmentFile(droppedFile); // TODO only open one for now break; } } } public UndoControler getUndoControler(){ return undoControler; } public static Component getAliViewWindowGlassPane(){ return glassPane; } public void logScrollPane() { logger.info(alignmentScrollPane.getViewport().getSize()); } private void initWindow(Alignment newAlignment) { logger.info("inside init()"); //Color COLORSCHEME_BACKGROUND = Settings.getColorSchemeNucleotide().getBaseBackgroundColor(NucleotideUtilities.GAP); //Color COLORSCHEME_BACKGROUND = Settings.getColorSchemeNucleotide().getBaseBackgroundColor(NucleotideUtilities.GAP); //Color COLORSCHEME_BACKGROUND = Color.white;//Settings.getColorSchemeNucleotide().getBaseBackgroundColor(NucleotideUtilities.GAP); alignment = newAlignment; // add listener alignment.addAlignmentListener(this); alignment.addAlignmentDataListener(this); alignment.addAlignmentSelectionListener(this); // UNDO if(alignment.isUndoable()){ this.undoControler = aliViewWindow; }else{ this.undoControler = new EmptyUndoControler(); } logger.info("here"); // Create the main panel where alignment is drawn alignmentPane = new AlignmentPane(); AlignmentPaneMouseListener ml = new AlignmentPaneMouseListener(); alignmentPane.addMouseListener(ml); alignmentPane.addMouseMotionListener(ml); alignmentPane.addMouseWheelListener(ml); AlignmentRulerMouseListener rl = new AlignmentRulerMouseListener(); alignmentPane.getRulerComponent().addMouseListener(rl); alignmentPane.getRulerComponent().addMouseMotionListener(rl); AlignmentKeyListener kl = new AlignmentKeyListener(); alignmentPane.addKeyListener(kl); //alignmentPane.getRulerComponent().addKeyListener(kl); alignmentPane.setAlignment(alignment); // When alignment is loaded this.updateWindowTitle(); // Always horizontal scrollbar so list and pane not have varied height - then list and alignment could get out of synch // alignmentScrollPane = new MyScrollPane(alignmentPane, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); alignmentScrollPane = new JScrollPane(alignmentPane, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); alignmentScrollPane.setAutoscrolls(true); alignmentScrollPane.setMinimumSize(new Dimension(150, 150)); logger.info("alignmentPane.isDoubleBuffered()" + alignmentPane.isDoubleBuffered()); //boolean paneDoubleBuff = alignmentPane.isDoubleBuffered(); boolean paneDoubleBuff = true; alignmentScrollPane.setDoubleBuffered(paneDoubleBuff); //alignmentScrollPane.setDoubleBuffered(false); alignmentScrollPane.getVerticalScrollBar().setUnitIncrement(16); alignmentScrollPane.getHorizontalScrollBar().setUnitIncrement(160); // BACKINGSTORE_SCROLL_MODE is not working on Mac Retina-screen //alignmentScrollPane.getViewport().setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE); //alignmentScrollPane.setDropTarget(alignmentPane); alignmentPane.setDoubleBuffered(paneDoubleBuff); //alignmentPane.setDoubleBuffered(false); //alignmentScrollPane.setBorder(null); alignmentScrollPane.setBorder(BorderFactory.createEmptyBorder()); viewport = alignmentScrollPane.getViewport(); viewport.setAutoscrolls(true); sequenceJList = new SequenceJList(alignment.getSequences(), alignmentPane.getCharHeight(), this); // // To be able to consume mouse events before they gets to the // JList default listeners we first remove all built in listeners // and then instead add our ones at top, and finally add the old ones back // MouseListener[] oldOnes = sequenceJList.getMouseListeners(); for(MouseListener oldMl: oldOnes){ sequenceJList.removeMouseListener(oldMl); } MouseMotionListener[] oldMMOnes = sequenceJList.getMouseMotionListeners(); for(MouseMotionListener oldMl: oldMMOnes){ sequenceJList.removeMouseMotionListener(oldMl); } // MouseWheelListener[] oldMWOnes = sequenceJList.getMouseWheelListeners(); // for(MouseWheelListener oldMl: oldMWOnes){ // sequenceJList.removeMouseWheelListener(oldMl); // } // Add our listeners SequenceListMouseListener ourSeqListML = new SequenceListMouseListener(this); sequenceJList.addMouseListener(ourSeqListML); sequenceJList.addMouseMotionListener(ourSeqListML); SequenceListMouseWheelListener ourSeqListMWL = new SequenceListMouseWheelListener(this); sequenceJList.addMouseWheelListener(ourSeqListMWL); // And return the default listeners below our ones for(MouseListener oldMl: oldOnes){ sequenceJList.addMouseListener(oldMl); } for(MouseMotionListener oldMl: oldMMOnes){ sequenceJList.addMouseMotionListener(oldMl); } // for(MouseWheelListener oldMl: oldMWOnes){ // sequenceJList.addMouseWheelListener(oldMl); // } // // sequenceJList.setBackground(COLORSCHEME_BACKGROUND); // aliListener = new AlignmentDataAndSelectionListener(alignmentPane, this, sequenceJList); //sequenceJList.addListSelectionListener(aliListener); // alignment.getSequences().addAlignmentDataListener(aliListener); // alignment.getSequences().addAlignmentSelectionListener(aliListener); // Always horizontal scrollbar so list and pane not have varied height - then list and alignment could get out of synch listScrollPane = new JScrollPane(sequenceJList, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); // TODO the preferred sizes // Setting size does nothing - since it is inside split-pane - setting splitpane dividerlocation does the trick //listScrollPane.setMinimumSize(new Dimension(100, 30)); //listScrollPane.setPreferredSize(new Dimension(300,500)); //listScrollPane.setDoubleBuffered(true); listScrollPane.setBorder(new EmptyBorder(0,0,0,0)); //listScrollPane.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_NEVER); // Synchronize vertical scroll between two panes from alignment pane model to list (first the model) scrollBarListener = new ScrollBarModelSyncChangeListener(listScrollPane.getVerticalScrollBar().getModel()); alignmentScrollPane.getVerticalScrollBar().getModel().addChangeListener( scrollBarListener ); // Second sync is from list scrollbar back to alignmentPane // ScrollPaneSyncKeyAndMouseWheelListener wl = new ScrollPaneSyncKeyAndMouseWheelListener(listScrollPane, alignmentScrollPane); //, aliViewWindow); // listScrollPane.addMouseWheelListener(wl); // JScrollBar listBar = listScrollPane.getVerticalScrollBar(); // listBar.addMouseMotionListener(wl); // listBar.addMouseListener(wl); // sequenceJList.addKeyListener(wl); sequenceJList.addSynchPanes(listScrollPane, alignmentScrollPane); // Ruler JComponent alignmentRuler = alignmentPane.getRulerComponent(); Dimension alignmentRulerDimension = new Dimension(1000,20); alignmentRuler.setPreferredSize(alignmentRulerDimension); // CharsetRuler JComponent charsetRuler = alignmentPane.getCharsetRulerComponent(); Dimension charsetRulerDimension = new Dimension(0,0); charsetRuler.setPreferredSize(charsetRulerDimension); // RulerPanel rulerPanel = new JPanel(); rulerPanel.setLayout(new BoxLayout(rulerPanel, BoxLayout.Y_AXIS)); rulerPanel.add(alignmentRuler); rulerPanel.add(charsetRuler); // Alignment And RulerPanel together alignmentAndRulerPanel = new JPanel(new BorderLayout()); alignmentAndRulerPanel.add(alignmentScrollPane, BorderLayout.CENTER); alignmentAndRulerPanel.add(rulerPanel, BorderLayout.NORTH); // topoffset listpanel to match rulers height listTopOffset = new ListTopOffsetJPanel(rulerPanel); listTopOffset.setPreferredSize(new Dimension(100, rulerPanel.getPreferredSize().height)); listAndTopOffset = new JPanel(new BorderLayout()); listAndTopOffset.add(listScrollPane, BorderLayout.CENTER); listAndTopOffset.add(listTopOffset, BorderLayout.NORTH); // Splitpane between list and alignmentview JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, listAndTopOffset, alignmentAndRulerPanel); splitPane.setDividerSize(6); splitPane.setDividerLocation(200); //listTopOffset.setBackground(splitPane.getBackground()); this.getContentPane().add(splitPane, BorderLayout.CENTER); // Panel with all small status message labels such as xpos ypos statusPanel = new StatusPanel(alignmentPane, alignment); alignment.addAlignmentListener(statusPanel); alignment.addAlignmentDataListener(statusPanel); alignment.addAlignmentSelectionListener(statusPanel); // bottomPanel with status and in the future maybe more.... JPanel bottomPanel = new JPanel(); bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.X_AXIS)); this.getContentPane().add(bottomPanel, BorderLayout.SOUTH); //bottomPanel.add(searchField); bottomPanel.add(Box.createHorizontalGlue()); bottomPanel.add(statusPanel); logger.info("middle of GUI"); // // Create Menubar Toolbar and Popupmenu // aliViewMenuBar = menuBarFactory.create(this); logger.info("done create menubar"); this.setJMenuBar(aliViewMenuBar); aliViewMenuBar.disableAllButEssentialButtons(); Settings.addSettingsListener(aliViewMenuBar); AlignmentPopupMenu poupMenu = new AlignmentPopupMenu(aliViewWindow, aliViewMenuBar); alignmentPane.addMouseListener(poupMenu); sequenceJList.addMouseListener(poupMenu); /* for(MouseListener mouseL: sequenceJList.getMouseListeners()){ sequenceJList.removeMouseListener(mouseL); } for(MouseMotionListener mouseML: sequenceJList.getMouseMotionListeners()){ sequenceJList.removeMouseMotionListener(mouseML); } SequenceListMouseListener seqML = new SequenceListMouseListener(); sequenceJList.addMouseListener(seqML); sequenceJList.addMouseMotionListener(seqML); */ //fileSequencesChanged(); translationPanel = new TranslationToolPanel(aliViewWindow); alignment.addAlignmentListener(translationPanel); alignment.addAlignmentDataListener(translationPanel); alignment.addAlignmentSelectionListener(translationPanel); searchPanel = new SearchPanel(); searchPanel.getSearchField().addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { performFind(); } }); searchPanel.getSearchField().addFocusListener(new FocusListener() { public void focusLost(FocusEvent e) { } public void focusGained(FocusEvent e) { alignment.clearSelection(); } }); aliToolbar = new AliToolBar(aliViewMenuBar, searchPanel, translationPanel); aliToolbar.setFloatable(false); aliToolbar.setBorder(new EmptyBorder(0,0,0,0)); // toolbar layout might be different in som plaf but since it is not floating doesn't matter this.getContentPane().add(aliToolbar, BorderLayout.NORTH); // // End toolbar // aliViewMenuBar.rebuildSelectCharsetsSubmenu(); aliViewMenuBar.updateAllMenuEnabled(); alignment.addAlignmentListener(aliViewMenuBar); alignment.addAlignmentDataListener(aliViewMenuBar); alignment.addAlignmentSelectionListener(aliViewMenuBar); // JPanel anotherGlaggP = (JPanel) this.getGlassPane(); // anotherGlaggP.setLayout(new FlowLayout()); // JPanel message = new JPanel(); // message.setPreferredSize(new Dimension(400,200)); // message.setMaximumSize(new Dimension(400,200)); // message.setOpaque(true); // message.add(new JLabel("A Small label on top")); // anotherGlaggP.add(message); // anotherGlaggP.setVisible(true); // Set a default ColorScheme (has to be done after all pnels are created) setColorSchemeNucleotide(Settings.getColorSchemeNucleotide()); logger.info("init() finished"); } public AliViewJMenuBar getAliMenuBar() { return aliViewMenuBar; } /* * * This * */ public void findNamesFromClipboard() { // get clipboard String clipboard = getClipboard(); if(clipboard != null){ String[] lines = clipboard.split(LF); List<Integer> allFoundIndices = new ArrayList<Integer>(); for(String line: lines){ FindObject findObj = new FindObject(line,true); findObj = alignment.findInNames(findObj); allFoundIndices.addAll(findObj.getFoundIndices()); } alignment.clearSelection(); if(allFoundIndices.size() > 0){ alignment.selectIndices(allFoundIndices); sequenceJList.ensureIndexIsVisible(allFoundIndices.get(0)); } } } /* * * This method is a bonus - not really needed for alignment program.... * */ public void reverseComplementClipboard(){ String clipData = AliViewWindow.getClipboard(); if(clipData == null){ return; } // trim indata if it ends or starts with newline etc. clipData = clipData.trim(); String revComp = ""; // check if fasta if(clipData.startsWith(">")){ try { AlignmentListModel sequences = seqFactory.createFastaSequences(new StringReader(clipData)); // TODO change everywhere to fixed new-line for(Sequence seq: sequences){ seq.reverseComplement(); revComp += ">" + seq.getName() + LF; revComp += seq.getBasesAsString() + LF; } } catch (AlignmentImportException e) { e.printStackTrace(); Messenger.showOKOnlyMessage(Messenger.COMPLEMENT_FUNCTION_ERROR, LF + e.getLocalizedMessage(), this); } } // no fasta just revcomp brutally else{ revComp = aliview.NucleotideUtilities.reverse(clipData); revComp = aliview.NucleotideUtilities.complement(revComp); } // set clipboard StringSelection ss = new StringSelection(revComp); Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, null); } public void saveAlignmentFile() { // If alignment only is temp-file then save via chooser - otherwise without chooser if(alignment.getAlignmentFile().isAliViewTempFile()){ saveAlignmentAsFileViaChooser(); }else{ saveAlignmentAsFile(); } } public void showMessageLog() { startDebug(); MessageLogFrame messFrame = new MessageLogFrame(this); messFrame.setVisible(true); } public void updateWindowTitle() { AlignmentFile aliFile = alignment.getAlignmentFile(); if(aliFile == null || aliFile.getName().length() == 0){ this.setTitle("AliView"); }else{ // Add a symbol if unsaved if(hasUnsavedUndoableEdits()){ this.setTitle("AliView - " + "*" + aliFile.getNameWithoutTempPrefix()); } else{ this.setTitle("AliView - " + aliFile.getNameWithoutTempPrefix()); } } } private boolean hasUnsavedUndoableEdits() { if(hasUnsavedUndoableEdits == true){ return true; } if(alignment.getAlignmentFile() != null){ if(alignment.getAlignmentFile().isAliViewTempFile()){ return true; } } return false; } protected boolean hasUnsavedEdits() { return hasUnsavedUndoableEdits(); } public void performFind(String searchText) { searchPanel.setText(searchText); alignment.clearFindLastPos(); performFind(); } public void performFind() { alignment.clearSelection(); // if the searchterm is new then create a new obj and start from beginning String searchTerm = searchPanel.getText(); if(findObj == null){ findObj = new FindObject(searchTerm); // First try finding in names findObj.setFindNextInNames(true); } if(!findObj.getSearchTerm().equalsIgnoreCase(searchTerm)){ findObj = new FindObject(searchTerm); // First try finding in names findObj.setFindNextInNames(true); } findObj.setIsFound(false); findObj.setFindAll(false); if(findObj.findNextInNames() == true){ findObj = alignment.findInNames(findObj); if(findObj.isFound()){ searchPanel.setFoundMessage(); alignment.selectSequencesWithIndex(findObj.getFoundIndices()); sequenceJList.ensureIndexIsVisible(findObj.getFoundIndices().get(0).intValue()); // TODO Move this to a ScrollPaneSynchronizer.class // JScrollPane source = listScrollPane; // JScrollPane dest = alignmentScrollPane; // Point viewPos = new Point( dest.getViewport().getViewPosition().x, source.getViewport().getViewPosition().y ); // dest.getViewport().setViewPosition(viewPos); } else{ // nothing found try in sequences findObj.setFindNextInSequences(true); } } if(findObj.findNextInSequences() == true){ //findObj.setNextFindSeqNumber(0); alignment.clearSelection(); //sequenceJList.clearSelection(); // clear selection is not sending a listselectionevent findObj = alignment.findAndSelectInSequences(findObj); if(findObj.isFound()){ searchPanel.setFoundMessage(); alignmentPane.scrollRectToSelectionCenter(); } else{ // nothing found try in names findObj.setFindNextInNames(true); } } if(findObj.isFound() == false){ searchPanel.setNoFoundMessage(); } // requestPaneRepaint(); } public void requestPaneRepaint(){ alignmentPane.revalidate(); alignmentPane.repaint(); } public void requestPaneAndRulerRepaint(){ alignmentPane.revalidate(); alignmentPane.repaintAndForceRuler(); } public void requestScrollToVisibleSelection(){ alignmentPane.scrollRectToSelection(); } public void requestRepaintAndRevalidateALL() { // logger.info("requestRepaintAndRevalidateALL"); // revalidate is an invalidate and validate alignmentAndRulerPanel.revalidate(); listAndTopOffset.revalidate(); rulerPanel.revalidate(); alignmentPane.getCharsetRulerComponent().revalidate(); alignmentPane.validateSequenceOrder(); alignmentPane.validateSize(); alignmentPane.revalidate(); sequenceJList.revalidate(); alignmentPane.repaintAndForceRuler(); sequenceJList.repaint(); listAndTopOffset.repaint(); } /* public void requestPaneRepaint(){ alignmentPane.revalidate(); alignmentPane.repaint(); } public void requestPaneAndListRepaint(){ alignmentPane.revalidate(); alignmentPane.repaint(); sequenceJList.repaint(); } public void requestPaneAndRulerRepaint(){ alignmentPane.revalidate(); alignmentPane.repaintForceRuler(); } private void requestRepaintCursor() { requestRepaintSelection(); } private void requestRepaintSelection() { // repaint selection then cursor will be redrawn Rectangle rect = alignment.getSelectionAsMinRect(); requestPaneRepaintMatrixRect(rect); } private void requestRepaintSelectedSequences() { Rectangle selectRect = alignment.getSelectionAsMinRect(); Rectangle converted = alignmentPane.matrixCoordToPaneCoord(selectRect); // 2000 should make sure the whole window is covered converted.grow(2000,30); requestPaneRepaintRect(converted); } private void requestPaneRepaintMatrixRect(Rectangle rect) { //rect.grow(2,2); Rectangle converted = alignmentPane.matrixCoordToPaneCoord(rect); requestPaneRepaintRect(converted); } private void requestPaneRepaintRect(Rectangle rect){ rect.grow((int)alignmentPane.getCharWidth()*3,(int)alignmentPane.getCharHeight()*3); alignmentPane.repaint(rect); } private void requestRepaintAndRevalidateALL() { alignmentPane.validateSequenceOrder(); alignmentPane.validateSize(); alignmentPane.revalidate(); //sequenceJList.validateSelection(); sequenceJList.revalidate(); alignmentPane.repaint(); sequenceJList.repaint(); } */ public static final String getClipboard() { Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null); try { if (t != null && t.isDataFlavorSupported(DataFlavor.stringFlavor)){ String text = (String)t.getTransferData(DataFlavor.stringFlavor); return text; } } catch (UnsupportedFlavorException e){ } catch (IOException e) { } return null; } /* * These methods should be moved out to parent container */ public void zoomInAt(Point mousePos){ // TODO Problem is that a scrollpane need to be resized before setViewPosiiton() // and all should be done at once before repaint!!! // Get alignmentPane size before resize since it will change afeter resize // we need to now relative size different between new and old size because // we want to zoom in on same position (same nucleotide) where mouse was in // old pane Dimension oldSize = alignmentPane.getPreferredSize(); Point viewPoint = alignmentScrollPane.getViewport().getViewPosition(); Point mousePosInScrollPaneCoord = new Point(mousePos.x - viewPoint.x, mousePos.y - viewPoint.y); logger.info("oldSize" + oldSize); logger.info("mousePosInScrollPaneCoord" + mousePosInScrollPaneCoord); logger.info("mousePosOnPane" + mousePos); incCharSize(); Dimension newSize = alignmentPane.getPreferredSize(); alignmentPane.setSize(newSize); logger.info("pane-newSize" + newSize); // Now when alignmentPanel coordinates have changed due to resize, lets focus on the // relative position where mouse pointer were earlier (same nucleotide) double paneRelSizeX = newSize.getWidth()/oldSize.getWidth(); double paneRelSizeY = newSize.getHeight()/oldSize.getHeight(); int mousePosXOnResizedPane = (int) (mousePos.getX() * paneRelSizeX); int mousePosYOnResizedPane = (int) (mousePos.getY() * paneRelSizeY); Point mousePosOnResizedPane = new Point(mousePosXOnResizedPane, mousePosYOnResizedPane); // calculate new view location int newX = mousePosOnResizedPane.x - mousePosInScrollPaneCoord.x; int newY = mousePosOnResizedPane.y - mousePosInScrollPaneCoord.y; logger.info("newX" + newX); logger.info("newY" + newY); final Point newViewPoint = new Point(newX, newY); viewPoint = alignmentScrollPane.getViewport().getViewPosition(); logger.info("beforeViewPoint" + viewPoint); logger.info("newViewPoint" + newViewPoint); // Old viewport has to be replaced - otherwise problem drawing graphics // Not needed actually on zoomIn - only on zoomOut // alignmentScrollPane.setViewport(null); // alignmentScrollPane.setViewportView(alignmentPane); // Set new position alignmentScrollPane.getViewport().setViewPosition(newViewPoint); Point afterViewPoint = alignmentScrollPane.getViewport().getViewPosition(); logger.info("afterViewPoint" + viewPoint); // if(alignmentPane.isPointWithinMatrix(mousePosOnResizedPane)){ // // // This moving the mouse is done to make sure zoom in at right point even if pane is to small // int xMouseDiff = newViewPoint.x - afterViewPoint.x; // int yMouseDiff = newViewPoint.y - afterViewPoint.y; // logger.info("xMouseDiff=" + xMouseDiff); // logger.info("yMouseDiff=" + yMouseDiff); // // try { // // Robot robot = new Robot(); // Point onScreen = MouseInfo.getPointerInfo().getLocation(); // robot.mouseMove(onScreen.x + xMouseDiff, onScreen.y + yMouseDiff); // } catch (AWTException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } // } //alignmentPane.setForceRepaintAll(true); //requestPaneRepaint(); //alignmentPane.setForceRepaintAll(true); //alignmentPane.repaint(0,0,newSize.width, newSize.height); // no longer need to paintImmediately, since instead destroying viewport //alignmentPane.paintImmediately(0,0,newSize.width, newSize.height); SwingUtilities.invokeLater(new Runnable() { public void run(){ scrollBarListener.stateChanged(new ChangeEvent(alignmentScrollPane.getVerticalScrollBar().getModel())); } }); SwingUtilities.invokeLater(new Runnable() { public void run(){ // listScrollPane.getViewport().setViewPosition(new Point(0, newViewPoint.y)); } }); } public void zoomOutAt(Point mousePos){ // Get alignmentPane size before resize since it will change afeter resize // we need to now relative size different between new and old size because // we want to zoom in on same position (same nucleotide) where mouse was in // old pane Dimension oldSize = alignmentPane.getPreferredSize(); Point viewPoint = alignmentScrollPane.getViewport().getViewPosition(); Point mousePosInScrollPaneCoord = new Point(mousePos.x - viewPoint.x, mousePos.y - viewPoint.y); Point mouseInMatrixCoord = alignmentPane.paneCoordToMatrixCoord(mousePosInScrollPaneCoord); logger.info("oldSize" + oldSize); boolean didChangeSize = decCharSize(); if(didChangeSize){ final Dimension newSize = alignmentPane.getPreferredSize(); alignmentPane.setSize(newSize); logger.info("newSize" + newSize); // Now when alignmentPanel coordinates have changed due to resize, lets focus on the // relative position where mouse pointer were earlier (same nucleotide) double paneRelSizeX = newSize.getWidth()/oldSize.getWidth(); double paneRelSizeY = newSize.getHeight()/oldSize.getHeight(); int mousePosXOnResizedPane = (int) (mousePos.getX() * paneRelSizeX); int mousePosYOnResizedPane = (int) (mousePos.getY() * paneRelSizeY); Point mousePosOnResizedPane = new Point(mousePosXOnResizedPane, mousePosYOnResizedPane); // calculate new vew location int newX = mousePosOnResizedPane.x - mousePosInScrollPaneCoord.x; int newY = mousePosOnResizedPane.y - mousePosInScrollPaneCoord.y; final Point newViewPoint = new Point(newX, newY); // Old viewport has to be replaced alignmentScrollPane.setViewport(null); alignmentScrollPane.setViewportView(alignmentPane); // Set new pos alignmentScrollPane.getViewport().setViewPosition(newViewPoint); Point afterViewPoint = alignmentScrollPane.getViewport().getViewPosition(); logger.info("afterViewPoint" + viewPoint); // if(alignmentPane.isPointWithinMatrix(mousePosOnResizedPane)){ // // // This moving the mouse is done to make sure zoom in at right point even if pane is to small // int xMouseDiff = newViewPoint.x - afterViewPoint.x; // int yMouseDiff = newViewPoint.y - afterViewPoint.y; // logger.info("xMouseDiff=" + xMouseDiff); // logger.info("yMouseDiff=" + yMouseDiff); // // try { // // Robot robot = new Robot(); // Point onScreen = MouseInfo.getPointerInfo().getLocation(); // robot.mouseMove(onScreen.x + xMouseDiff, onScreen.y + yMouseDiff); // } catch (AWTException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } // } //requestPaneRepaint(); //alignmentPane.setForceRepaintAll(true); //alignmentPane.repaint(0,0,newSize.width, newSize.height); // no longer need to paintImmediately, since instead destroying viewport //alignmentPane.paintImmediately(0,0,newSize.width, newSize.height); SwingUtilities.invokeLater(new Runnable() { public void run(){ scrollBarListener.stateChanged(new ChangeEvent(alignmentScrollPane.getVerticalScrollBar().getModel())); } }); SwingUtilities.invokeLater(new Runnable() { public void run(){ // listScrollPane.getViewport().setViewPosition(new Point(0, newViewPoint.y)); } }); } } /* * End t hese methods should be moved out to parent container */ /** * Initialize the contents of the frame. */ public boolean saveAlignmentAsFileViaChooser(){ return saveAlignmentAsFileViaChooser(alignment.getFileFormat(), false); } /** * Initialize the contents of the frame. */ public boolean saveAlignmentAsFileViaChooser(FileFormat fileFormat, boolean saveAsCopy){ // Get dir for saving String suggestedDir = null; String suggestedFileName = null; if(alignment.getAlignmentFile().isAliViewTempFile()){ File lastRecent = Settings.getLastRecentFile(); File lastRecentDir = null; if(lastRecent == null){ lastRecentDir = AlignmentFile.createUserHomeFile(); }else{ lastRecentDir = lastRecent.getParentFile(); } suggestedDir = lastRecentDir.getAbsolutePath(); suggestedFileName = alignment.getAlignmentFile().getNameWithoutTempPrefix(); }else{ suggestedDir = alignment.getAlignmentFile().getParent(); suggestedFileName = alignment.getFileName(); } // if file format not is same as alignment strip surrent suffix and add new one if(fileFormat != alignment.getFileFormat()){ suggestedFileName = FileFormat.stripFileSuffixFromName(suggestedFileName); suggestedFileName += "." + fileFormat.getSuffix(); } // make sure there is a file name if(suggestedFileName == null || suggestedFileName.length() < 1){ suggestedFileName = "alignment" + "." + fileFormat.getSuffix(); } File suggestedFile = new File(suggestedDir, suggestedFileName); Component parent = this.getParent(); File selectedFile = FileUtilities.selectSaveFileViaChooser(suggestedFile,parent); // här borde det vara alignment getAlignmentAsFastaStream if(selectedFile != null){ // Ask user if file exists if(selectedFile.exists()){ String message = "File already exists - do you want to overwrite?"; int retVal = JOptionPane.showConfirmDialog(this, message, "Overwrite?", JOptionPane.OK_CANCEL_OPTION); if(retVal != JOptionPane.OK_OPTION){ return false; } } try { if(fileFormat == fileFormat.IMAGE_PNG){ ImageExporter.writeComponentAsImageToFile(selectedFile, fileFormat.getSuffix(), alignmentPane); }else{ alignment.saveAlignmentAsFile(selectedFile, fileFormat); } if(! saveAsCopy){ alignment.setAlignmentFile(selectedFile); alignment.setAlignmentFormat(fileFormat); aliViewWindow.updateWindowTitle(); Settings.putSaveAlignmentDirectory(selectedFile.getParent()); hasUnsavedUndoableEdits = false; this.updateWindowTitle(); // reload so names get updated if(fileFormat == FileFormat.NEXUS_SIMPLE){ this.reloadCurrentFile(); } } if(fileFormat != fileFormat.IMAGE_PNG){ Settings.addRecentFile(selectedFile); } } catch (IOException e) { e.printStackTrace(); // Meddela användaren om fel Messenger.showOKOnlyMessage(Messenger.FILE_SAVE_ERROR, LF + e.getLocalizedMessage(), this); } } else{ return false; } return true; } public void exportRaxMLFile() { exportRaxMLFileViaChooser(); } public boolean exportRaxMLFileViaChooser(){ // Get dir for saving String suggestedDir = null; String suggestedFileName = null; if(alignment.getAlignmentFile().isAliViewTempFile()){ File lastRecent = Settings.getLastRecentFile(); File lastRecentDir = null; if(lastRecent == null){ lastRecentDir = AlignmentFile.createUserHomeFile(); }else{ lastRecentDir = lastRecent.getParentFile(); } suggestedDir = lastRecentDir.getAbsolutePath(); suggestedFileName = alignment.getAlignmentFile().getNameWithoutTempPrefix(); }else{ suggestedDir = alignment.getAlignmentFile().getParent(); suggestedFileName = alignment.getFileName(); } // make sure there is a file name if(suggestedFileName == null){ suggestedFileName = ""; } // strip previous suffix suggestedFileName = FileFormat.stripFileSuffixFromName(suggestedFileName); suggestedFileName += ".partitions"; File suggestedFile = new File(suggestedDir, suggestedFileName); Component parent = this.getParent(); File selectedFile = FileUtilities.selectSaveFileViaChooser(suggestedFile,parent); // här borde det vara alignment getAlignmentAsFastaStream if(selectedFile != null){ // Ask user if file exists if(selectedFile.exists()){ String message = "File already exists - do you want to overwrite?"; int retVal = JOptionPane.showConfirmDialog(this, message, "Overwrite?", JOptionPane.OK_CANCEL_OPTION); if(retVal != JOptionPane.OK_OPTION){ return false; } } try { alignment.exportPartitionsFileRaxMLFormat(selectedFile); } catch (IOException e) { e.printStackTrace(); // Meddela användaren om fel Messenger.showOKOnlyMessage(Messenger.FILE_SAVE_ERROR, LF + e.getLocalizedMessage(), this); } } else{ return false; } return true; } /** * Initialize the contents of the frame. */ public void saveAlignmentAsFile(){ // Get dir for saving String saveDir = alignment.getAlignmentFile().getParent(); // and filename String saveFileName = alignment.getFileName(); // make sure there is a file name if(saveFileName == null || saveFileName.length() < 1){ Messenger.showOKOnlyMessage(Messenger.SAVE_NOT_POSSIBLE_TRY_SAVE_AS, aliViewWindow); return; } File saveFile = new File(saveDir, saveFileName); try { alignment.saveAlignmentAsFile(saveFile, alignment.getFileFormat()); // many of this below should not be necessary alignment.setAlignmentFile(saveFile); alignment.setAlignmentFormat(alignment.getFileFormat()); aliViewWindow.updateWindowTitle(); Settings.putSaveAlignmentDirectory(saveFile.getAbsoluteFile().getParent()); hasUnsavedUndoableEdits = false; this.updateWindowTitle(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); // Meddela användaren om fel Messenger.showOKOnlyMessage(Messenger.FILE_SAVE_ERROR, LF + e.getLocalizedMessage(), this); } } public void saveSelectionAsFastaFileViaChooser() { String suggestedDir = alignment.getAlignmentFile().getParent(); String suggestedFileName = alignment.getAlignmentFile().getName(); suggestedFileName = FileFormat.stripFileSuffixFromName(suggestedFileName); suggestedFileName += ".selection." + FileFormat.FASTA.getSuffix(); File suggestedFile = new File(suggestedDir, suggestedFileName); Component parentComponent = this.getParent(); File selectedFile = FileUtilities.selectSaveFileViaChooser(suggestedFile,parentComponent); if(selectedFile != null){ alignment.saveSelectionAsFastaFile(selectedFile); Settings.putSaveSelectionDirectory(selectedFile.getParent()); } } public void reloadCurrentFile() { boolean isOKGoAhead = requestReloadWindow(); if(isOKGoAhead){ getUndoControler().pushUndoState(); File currentFile = alignment.getAlignmentFile(); loadNewAlignmentFile(currentFile); hasUnsavedUndoableEdits = false; this.updateWindowTitle(); } } // TODO maybe it should not be possible // to open alignment in old window // would be easier to make it right public void loadNewAlignmentFile(File selectedFile){ alignment = AlignmentFactory.createNewAlignment(selectedFile); setupNewAlignment(alignment); //requestPaneAndListRepaint(); hasUnsavedUndoableEdits = false; this.updateWindowTitle(); aliViewMenuBar.rebuildSelectCharsetsSubmenu(); aliViewMenuBar.updateAllMenuEnabled(); } /* * * TODO Maybe not setup new - but create new somehow * */ private void setupNewAlignment(Alignment newAlignment){ alignment = newAlignment; alignment.addAlignmentListener(this); alignment.addAlignmentDataListener(this); alignment.addAlignmentSelectionListener(this); alignment.addAlignmentListener(statusPanel); alignment.addAlignmentDataListener(statusPanel); alignment.addAlignmentSelectionListener(statusPanel); alignment.addAlignmentListener(aliViewMenuBar); alignment.addAlignmentDataListener(aliViewMenuBar); alignment.addAlignmentSelectionListener(aliViewMenuBar); alignment.addAlignmentListener(translationPanel); alignment.addAlignmentDataListener(translationPanel); alignment.addAlignmentSelectionListener(translationPanel); alignmentPane.setAlignment(alignment); sequenceJList.setModel(alignment.getSequences()); sequenceJList.setSelectionModel(alignment.getSequences().getAlignmentSelectionModel().getSequenceListSelectionModel()); // alignment.getSequences().addAlignmentDataListener(aliListener); // alignment.getSequences().addAlignmentSelectionListener(aliListener); statusPanel.setAlignment(alignment); statusPanel.updateAll(); alignmentPane.validateSize(); aliViewWindow.updateWindowTitle(); aliViewMenuBar.rebuildSelectCharsetsSubmenu(); aliViewMenuBar.updateAllMenuEnabled(); } public void zoomIn(){ // if pointer is on pane Point zoomPoint = alignmentPane.getMousePosition(); if(zoomPoint == null){ // else get center position of view Point viewPoint = alignmentScrollPane.getViewport().getViewPosition(); Dimension dimension = alignmentScrollPane.getViewport().getExtentSize(); Point centerPos = new Point(viewPoint.x + dimension.width / 2, viewPoint.y + dimension.height / 2); zoomPoint = centerPos; } zoomInAt(zoomPoint); } public void zoomOut(){ // if pointer is on pane Point zoomPoint = alignmentPane.getMousePosition(); if(zoomPoint == null){ // else get center position of view Point viewPoint = alignmentScrollPane.getViewport().getViewPosition(); Dimension dimension = alignmentScrollPane.getViewport().getExtentSize(); Point centerPos = new Point(viewPoint.x + dimension.width / 2, viewPoint.y + dimension.height / 2); zoomPoint = centerPos; } zoomOutAt(zoomPoint); } protected void incCharSize(){ alignmentPane.incCharSize(); sequenceJList.setCharSize(alignmentPane.getCharHeight()); } protected boolean decCharSize() { boolean didChange = alignmentPane.decCharSize(); // if(didChange){ sequenceJList.setCharSize(alignmentPane.getCharHeight()); // } return didChange; } public void restoreWindowGeometry(){ // Restore window geometry Rectangle bounds = new Rectangle(); bounds.x = prefs.getInt("window.x",DEFAULT_WIN_GEOMETRY.x); bounds.y = prefs.getInt("window.y",DEFAULT_WIN_GEOMETRY.y); bounds.width = prefs.getInt("window.width",DEFAULT_WIN_GEOMETRY.width); bounds.height = prefs.getInt("window.height",DEFAULT_WIN_GEOMETRY.height); this.setBounds(bounds); // Do not use pack()! } public void saveWindowGeometry(){ // Restore window geometry Rectangle bounds = this.getBounds(); prefs.putInt("window.x",bounds.x); prefs.putInt("window.y",bounds.y); prefs.putInt("window.width",bounds.width); prefs.putInt("window.height",bounds.height); try { prefs.flush(); } catch (BackingStoreException e){ // TODO Auto-generated catch block e.printStackTrace(); } } public synchronized void reAlignSelectedSequences(){ if(alignment.isTranslatedOnePos()){ Messenger.showOKOnlyMessage(Messenger.SUGGEST_ALIGN_AS_TRANSLATED, aliViewWindow); return; } CommandItem firstSelected = null; for(CommandItem item: Settings.getAlignADDCommands()){ if(item.isActivated()){ firstSelected = item; firstSelected.reParseCommand(); break; } } if(firstSelected != null){ try { // check that a full sequence is selected if(alignment.hasFullySelectedSequences()){ // Save selected sequences in one file and other in another final File unselectedAlignmentTempFile = AlignmentFile.createAliViewTempFile("unselected-alignment", FileFormat.FASTA.getSuffix()); final File selectedAlignmentTempFile = AlignmentFile.createAliViewTempFile("selected-alignment", FileFormat.FASTA.getSuffix()); alignment.saveSelectedSequencesAsFastaFile(selectedAlignmentTempFile, false); alignment.saveUnSelectedSequencesAsFastaFile(unselectedAlignmentTempFile, false); alignAndAddSequences(firstSelected, unselectedAlignmentTempFile, selectedAlignmentTempFile); }else{ Messenger.showOKOnlyMessage(Messenger.NO_FULLY_SELECTED_SEQUENCES, this); } } catch (IOException e) { // Meddela användaren om fel Messenger.showOKOnlyMessage(Messenger.ALIGNER_SOMETHING_PROBLEM_ERROR, LF + "Message: " + e.getLocalizedMessage(), aliViewWindow); e.printStackTrace(); } } } public synchronized void alignAndAddSequences(File additionalSequencesFile) throws IOException { if(alignment.isTranslatedOnePos()){ Messenger.showOKOnlyMessage(Messenger.SUGGEST_ALIGN_AS_TRANSLATED, aliViewWindow); return; } CommandItem firstSelected = null; for(CommandItem item: Settings.getAlignADDCommands()){ if(item.isActivated()){ firstSelected = item; firstSelected.reParseCommand(); break; } } if(firstSelected != null){ // Save current alignment in tempdir (to be sure all unsaved changes are there) FileFormat currentTempFileFormat = firstSelected.getCurrentAlignmentFileFormat(); final File currentAlignmentTempFile = AlignmentFile.createAliViewTempFile("current-alignment", currentTempFileFormat.getSuffix()); alignment.saveAlignmentAsFile(currentAlignmentTempFile, currentTempFileFormat); alignAndAddSequences(firstSelected, currentAlignmentTempFile, additionalSequencesFile); } } public synchronized void alignAndAddSequences(final CommandItem alignItem, File origSequences, File newSeqs){ if(alignment.isTranslatedOnePos()){ Messenger.showOKOnlyMessage(Messenger.SUGGEST_ALIGN_AS_TRANSLATED, aliViewWindow); return; } if(StringUtils.containsIgnoreCase(alignItem.getCommand(), "profile")){ boolean hideMessage = Settings.getHideMuscleProfileAlignInfoMessage().getBooleanValue(); if(! hideMessage){ boolean hideMessageNextTime = Messenger.showOKOnlyMessageWithCbx(Messenger.MUSCLE_PROFILE_INFO_MESSAGE, true, this); Settings.getHideMuscleProfileAlignInfoMessage().putBooleanValue(hideMessageNextTime); } } // warn if invalid characters String invalidChars = alignment.getFirstAlignmentProgInvalidCharacter(); if(invalidChars.length() > 0 ){ Messenger.showHideAlignmentProgramInvalidCharsInfoMessage(invalidChars); int choise = Messenger.getLastSelectedOption(); if(choise == JOptionPane.CANCEL_OPTION){ return; } } try { // Create a tempFile for new alignment final File newAlignmentTempFile = AlignmentFile.createAliViewTempFile("alignment", ".fasta"); final SubProcessWindow subProcessWin = SubProcessWindow.getAlignmentProgressWindow(aliViewWindow, true); subProcessWin.setCloseWhenDoneCbxSelection(Settings.getHideAlignmentProgressWindowWhenDone().getBooleanValue()); subProcessWin.setTitle("Align and add sequences with " + alignItem.getName()); subProcessWin.setAlwaysOnTop(false); subProcessWin.show(); alignItem.setParameterCurrentFile(origSequences); alignItem.setParameterSecondFile(newSeqs); alignItem.setParameterOutputFile(newAlignmentTempFile); Thread thread = new Thread(new Runnable(){ public void run(){ try { ExternalCommandExecutor.executeMultiple(alignItem, subProcessWin); //Aligner.mafftAlign(currentAlignmentTempFile, newAlignmentTempFile, subProcessWin); // aligning is done the new thread should activate GUI again before it is finished SwingUtilities.invokeLater(new Runnable() { public void run(){ boolean wasProcessInterruptedByUser = subProcessWin.wasSubProcessDestrouedByUser(); aliViewWindow.realignmentOfSelectedSeqsDone(wasProcessInterruptedByUser, newAlignmentTempFile); subProcessWin.appendOutput(LF + "Done" + LF); // close window automatically if that is what is wanted if(Settings.getHideAlignmentProgressWindowWhenDone().getBooleanValue()){ subProcessWin.dispose(); } setSoftLockGUIThroughMenuDisable(false); //glassPane.setVisible(false); } }); } catch (IOException e) { setSoftLockGUIThroughMenuDisable(false); //glassPane.setVisible(false); // Meddela användaren om fel subProcessWin.appendOutput(e.getMessage()); Messenger.showOKOnlyMessage(Messenger.ALIGNER_SOMETHING_PROBLEM_ERROR, LF + "Message: " + e.getLocalizedMessage(), aliViewWindow); e.printStackTrace(); } } }); // Lock GUI while second thread is working setSoftLockGUIThroughMenuDisable(true); //glassPane.setVisible(true); thread.start(); } catch (IOException e) { setSoftLockGUIThroughMenuDisable(false); Messenger.showOKOnlyMessage(Messenger.ALIGNER_SOMETHING_PROBLEM_ERROR, LF + "Message: " + e.getLocalizedMessage(), aliViewWindow); e.printStackTrace(); } } public void reAlignEverythingWithDefaultProgram() { if(alignment.isTranslatedOnePos()){ Messenger.showOKOnlyMessage(Messenger.SUGGEST_ALIGN_AS_TRANSLATED, aliViewWindow); return; } CommandItem firstSelected = null; for(CommandItem item: Settings.getAlignALLCommands()){ if(item.isActivated()){ firstSelected = item; firstSelected.reParseCommand(); break; } } if(firstSelected != null){ reAlignEverythingWithAlignCommand(firstSelected, false,false); } } public void reAlignEverythingAsTranslatedAA() { CommandItem firstSelected = null; for(CommandItem item: Settings.getAlignALLCommands()){ if(item.isActivated()){ firstSelected = item; firstSelected.reParseCommand(); break; } } if(firstSelected != null){ reAlignEverythingWithAlignCommand(firstSelected, true,false); } } public synchronized void reAlignSelectionInSeparateThread() { if(alignment.isTranslatedOnePos()){ Messenger.showOKOnlyMessage(Messenger.SUGGEST_ALIGN_AS_TRANSLATED, aliViewWindow); return; } CommandItem firstSelected = null; for(CommandItem item: Settings.getAlignALLCommands()){ if(item.isActivated()){ firstSelected = item; firstSelected.reParseCommand(); break; } } if(firstSelected != null){ reAlignEverythingWithAlignCommand(firstSelected, false,true); } } public void reAlignEverythingWithAlignCommand(final CommandItem alignItem, final boolean asTranslatedAA, final boolean selection){ // ask if realign everything if(! selection){ boolean hideMessage = Settings.getHideRealignEverythingMessage().getBooleanValue(); if(! hideMessage){ boolean hideMessageNextTime = Messenger.showOKCancelMessageWithCbx(Messenger.REALIGN_EVERYTHING, hideMessage, aliViewWindow); Settings.getHideRealignEverythingMessage().putBooleanValue(hideMessageNextTime); int choise = Messenger.getLastSelectedOption(); if(choise == JOptionPane.CANCEL_OPTION){ return; } } } // warn if invalid characters String invalidChars = alignment.getFirstAlignmentProgInvalidCharacter(); if(invalidChars.length() > 0){ String invalCharMessage = "Some aligners (e.g. Muscle, Mafft) are sensiteive to invalid characters," + LF + "the following were found and you might need to replace them with X in your alignment: " + invalidChars; int choise = JOptionPane.showConfirmDialog(this, invalCharMessage, "Problem characters", JOptionPane.OK_CANCEL_OPTION); if(choise == JOptionPane.CANCEL_OPTION){ return; } } try { logger.info("alignWithDefault"); // Save current alignment in tempdir (to be sure all unsaved changes are there) FileFormat currentTempFileFormat = alignItem.getCurrentAlignmentFileFormat(); final File currentAlignmentTempFile = AlignmentFile.createAliViewTempFile("current-alignment", currentTempFileFormat.getSuffix()); // save selection if user changes it during alignment final Rectangle selectionBounds = alignment.getSelectionAsMinRect(); if(asTranslatedAA){ alignment.saveAlignmentAsFile(currentAlignmentTempFile, FileFormat.FASTA_TRANSLATED_AMINO_ACID); }else if(selection){ alignment.saveSelectionAsFastaFile(currentAlignmentTempFile); }else{ alignment.saveAlignmentAsFile(currentAlignmentTempFile, currentTempFileFormat); } // Create a tempFile for new alignment final File newAlignmentTempFile = AlignmentFile.createAliViewTempFile("alignment", ".fasta"); // Replace static parameters in command alignItem.setParameterCurrentFile(currentAlignmentTempFile); alignItem.setParameterOutputFile(newAlignmentTempFile); final SubProcessWindow subProcessWin = SubProcessWindow.getAlignmentProgressWindow(aliViewWindow, true); subProcessWin.setCloseWhenDoneCbxSelection(Settings.getHideAlignmentProgressWindowWhenDone().getBooleanValue()); subProcessWin.setTitle("Align with " + alignItem.getName()); subProcessWin.setAlwaysOnTop(false); subProcessWin.show(); Thread thread = new Thread(new Runnable(){ public void run(){ try { ExternalCommandExecutor.executeMultiple(alignItem, subProcessWin); //Aligner.mafftAlign(currentAlignmentTempFile, newAlignmentTempFile, subProcessWin); logger.info("donerealign"); // aligning is done the new thread should activate GUI again before it is finished SwingUtilities.invokeLater(new Runnable() { public void run(){ boolean wasProcessInterruptedByUser = subProcessWin.wasSubProcessDestrouedByUser(); if(asTranslatedAA){ aliViewWindow.realignmentAsAADone(wasProcessInterruptedByUser, newAlignmentTempFile); }else if(selection){ aliViewWindow.realignmentOfSelectionDone(wasProcessInterruptedByUser, newAlignmentTempFile, selectionBounds); }else{ aliViewWindow.realignmentDone(wasProcessInterruptedByUser, newAlignmentTempFile); } subProcessWin.appendOutput(LF + "Done" + LF); logger.info("before-set-visible-false"); // close window automatically if that is what is wanted if(Settings.getHideAlignmentProgressWindowWhenDone().getBooleanValue()){ subProcessWin.dispose(); } //glassPane.setVisible(false); setSoftLockGUIThroughMenuDisable(false); } }); } catch (IOException e) { // TODO Auto-generated catch block //glassPane.setVisible(false); setSoftLockGUIThroughMenuDisable(false); subProcessWin.appendOutput(e.getMessage()); Messenger.showOKOnlyMessage(Messenger.ALIGNER_SOMETHING_PROBLEM_ERROR, LF + "Message: " + e.getLocalizedMessage(), aliViewWindow); e.printStackTrace(); } } }); // Lock GUI while second thread is working //glassPane.setVisible(true); setSoftLockGUIThroughMenuDisable(true); thread.start(); } catch (IOException e) { setSoftLockGUIThroughMenuDisable(false); Messenger.showOKOnlyMessage(Messenger.ALIGNER_SOMETHING_PROBLEM_ERROR, LF + "Error message:" + e.getLocalizedMessage(), aliViewWindow); e.printStackTrace(); } } private void setSoftLockGUIThroughMenuDisable(boolean lock) { aliViewMenuBar.setMenuLock(lock); } // TODO this is a quite dirty method that probably should be pushed into alignment or implemented in an Aligner.class // it is also not dealing with changed selection during waitingtime (but it is blocked by glass-pane // TODO this and many other methods only if sequences are "editable" private void realignmentOfSelectionDone(boolean wasProcessInterruptedByUser, File newRealignedSelectionTempFile, Rectangle selectionBounds){ if(! wasProcessInterruptedByUser){ // Reload alignment if(newRealignedSelectionTempFile.length() > 0){ aliViewWindow.getUndoControler().pushUndoState(); // load realigned into alignment Alignment realignment = AlignmentFactory.createNewAlignment(newRealignedSelectionTempFile); // restore selection (if changed by user during time) alignment.setSelectionWithin(selectionBounds); alignment.replaceSelectedCharactersWithThis(realignment); alignment.padAndTrimSequences(); requestPaneRepaint(); }else{ //glassPane.setVisible(false); setSoftLockGUIThroughMenuDisable(false); Messenger.showOKOnlyMessage(Messenger.ALIGNER_SOMETHING_PROBLEM_ERROR, aliViewWindow); //final String message = "Something did not work out when aligning"; //JOptionPane.showMessageDialog(this, message, "Problem when aligning", JOptionPane.INFORMATION_MESSAGE); } } logger.info("Finished realignmentOfSelection"); } private void realignmentAsAADone(boolean wasProcessInterruptedByUser, File newRealignedTempFile){ if(! wasProcessInterruptedByUser){ // Reload alignment if(newRealignedTempFile.length() > 0){ try{ aliViewWindow.getUndoControler().pushUndoState(); Alignment realignment = AlignmentFactory.createNewAlignment(newRealignedTempFile); alignment.realignNucleotidesUseThisAAAlignmentAsTemplate(realignment); alignment.padAndTrimSequences(); }catch(Exception exc){ exc.printStackTrace(); setSoftLockGUIThroughMenuDisable(false); Messenger.showGeneralExceptionMessage(exc, aliViewWindow); } } else{ //glassPane.setVisible(false); setSoftLockGUIThroughMenuDisable(false); Messenger.showOKOnlyMessage(Messenger.ALIGNER_SOMETHING_PROBLEM_ERROR, aliViewWindow); // String message = "Something did not work out when aligning"; // JOptionPane.showMessageDialog(this, message, "Problem when aligning", JOptionPane.INFORMATION_MESSAGE); } } logger.info("Finished realignmentAsAADone"); } protected void realignmentOfSelectedSeqsDone(boolean wasProcessInterruptedByUser, File newRealignedTempFile) { if(! wasProcessInterruptedByUser){ // Reload alignment // TO DO HANDLE bad loading of file better if(newRealignedTempFile.length() > 0){ aliViewWindow.getUndoControler().pushUndoState(); // TODO storing this could be done slightly more unified // store path to current working file File storedAlignmentFile = alignment.getAlignmentFile(); AlignmentListModel prevSeqOrder = alignment.getSequences(); // Keep meta when realigning AlignmentMeta storedMeta = alignment.getAlignentMetaCopy(); loadNewAlignmentFile(newRealignedTempFile); // Restore alignment.setAlignmentFile(storedAlignmentFile); this.updateWindowTitle(); alignment.setAlignentMeta(storedMeta); alignment.sortSequencesByThisModel(prevSeqOrder); alignment.padAndTrimSequences(); } else{ setSoftLockGUIThroughMenuDisable(false); Messenger.showOKOnlyMessage(Messenger.ALIGNER_SOMETHING_PROBLEM_ERROR, aliViewWindow); } } logger.info("Finished reAlignWithDefault"); } protected void realignmentDone(boolean wasProcessInterruptedByUser, File newRealignedTempFile) { if(! wasProcessInterruptedByUser){ // Reload new alignment if(newRealignedTempFile.length() > 0){ aliViewWindow.getUndoControler().pushUndoState(); // TODO storing this could be done slightly more unified // store path to current working file File storedAlignmentFile = alignment.getAlignmentFile(); // When realigning all don't keep alignment meta // AlignmentMeta storedMeta = alignment.getAlignentMetaCopy(); loadNewAlignmentFile(newRealignedTempFile); // Restore alignment.setAlignmentFile(storedAlignmentFile); this.updateWindowTitle(); // When realigning all dont keep alignment meta //alignment.setAlignentMeta(storedMeta); alignment.padAndTrimSequences(); } else{ //glassPane.setVisible(false); setSoftLockGUIThroughMenuDisable(false); Messenger.showOKOnlyMessage(Messenger.ALIGNER_SOMETHING_PROBLEM_ERROR, aliViewWindow); } } logger.info("Finished reAlignWithDefault"); } public static void logAllLogs(){ Enumeration enumer = Logger.getRootLogger().getAllAppenders(); while ( enumer.hasMoreElements() ){ Appender app = (Appender)enumer.nextElement(); if ( app instanceof FileAppender ){ System.out.println("File: " + ((FileAppender)app).getFile()); } } } public static void flushAllLogs() { try { Set<FileAppender> flushedFileAppenders = new HashSet<FileAppender>(); Enumeration currentLoggers = LogManager.getLoggerRepository().getCurrentLoggers(); while(currentLoggers.hasMoreElements()) { Object nextLogger = currentLoggers.nextElement(); if(nextLogger instanceof Logger) { Logger currentLogger = (Logger) nextLogger; Enumeration allAppenders = currentLogger.getAllAppenders(); while(allAppenders.hasMoreElements()) { Object nextElement = allAppenders.nextElement(); if(nextElement instanceof FileAppender) { FileAppender fileAppender = (FileAppender) nextElement; if(!flushedFileAppenders.contains(fileAppender) && !fileAppender.getImmediateFlush()) { flushedFileAppenders.add(fileAppender); //log.info("Appender "+fileAppender.getName()+" is not doing immediateFlush "); fileAppender.setImmediateFlush(true); currentLogger.info("FLUSH"); fileAppender.setImmediateFlush(false); } else { //log.info("fileAppender"+fileAppender.getName()+" is doing immediateFlush"); } } } } } } catch(RuntimeException e) { logger.error("Failed flushing logs",e); } } public void clearSelectedBases(){ if(! requestEditMode()){ return; } List<Sequence> prevState = alignment.clearSelectedBases(isUndoable()); if(isUndoable()){ aliViewWindow.getUndoControler().pushUndoState(new UndoSavedStateEditedSequences(prevState, alignment.getAlignentMetaCopy())); } //requestPaneRepaint(); } private boolean isUndoable() { // MemoryUtils.logMem(); // logger.info("getPresumableFreeMemory()=" + MemoryUtils.getPresumableFreeMemoryMB()); // logger.info("alignment.getApproximateMemorySize()" + alignment.getApproximateMemorySizeMB()); double presumableFreeMemory = MemoryUtils.getPresumableFreeMemoryMB(); double alignmentSize = alignment.getApproximateMemorySizeMB(); double memoryLimit = (2 * alignmentSize) + 100; if(presumableFreeMemory < memoryLimit){ // tell user: if(! hasNotifiedUserAboutLimitedUndo){ Messenger.showOKOnlyMessage(Messenger.LIMITED_UNDO_CAPABILITIES, this); hasNotifiedUserAboutLimitedUndo = true; } return false; } else{ return true; } } public void findPrimerInCurrentSelection() { long selectionSize = alignment.getSelectionSize(); // no selection retur if(selectionSize == 0){ Messenger.showOKOnlyMessage(Messenger.NO_SELECTION, this); return; } if(selectionSize > 1000*100){ // optionpane String message = "In a large selection finding primers might take some time, " + LF + "Do you want to go ahead?"; int retVal = JOptionPane.showConfirmDialog(this, message, "Continue?", JOptionPane.OK_CANCEL_OPTION); if(retVal != JOptionPane.OK_OPTION){ return; } } ArrayList<Primer> primerResult = alignment.findPrimerInSelection(); // kill old frame if(primerResultsFrame != null){ primerResultsFrame.dispose(); } // if results - else show message if(primerResult != null && primerResult.size() > 0){ primerResultsFrame = new PrimerResultsFrame(primerResult, aliViewWindow); primerResultsFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); }else{ Messenger.showOKOnlyMessage(Messenger.NO_PRIMERS_FOUND, this); } } public void addAndAlignMultipleSeqFromClipOneByOne() { String clipData = getClipboard(); // check if fasta if(clipData != null && FileFormat.isThisFasta(clipData)){ try { AlignmentListModel sequences = seqFactory.createFastaSequences(new StringReader(clipData)); for(Sequence seq: sequences){ try { // Save sequences one by one into temp file File clipboardSequenceFile = AlignmentFile.createAliViewTempFile("clipboard_selection", ".fasta"); BufferedWriter buffWriter = new BufferedWriter(new FileWriter(clipboardSequenceFile)); String fastaSeqName = ">" + seq.getName() + LF + seq.getBasesAsString(); buffWriter.append(fastaSeqName); seq.writeBases(buffWriter); buffWriter.flush(); buffWriter.close(); aliViewWindow.alignAndAddSequences(clipboardSequenceFile); } catch (IOException e) { Messenger.showOKOnlyMessage(Messenger.ALIGNER_SOMETHING_PROBLEM_ERROR, LF + "Error message:" + e.getLocalizedMessage(), aliViewWindow); e.printStackTrace(); } } } catch (AlignmentImportException e) { Messenger.showOKOnlyMessage(Messenger.ALIGNER_SOMETHING_PROBLEM_ERROR, LF + "Error message:" + e.getLocalizedMessage(), aliViewWindow); e.printStackTrace(); } } // no fasta // skip else{ Messenger.showOKOnlyMessage(Messenger.NO_FASTA_IN_CLIPBOARD, aliViewWindow); } } public void addAndAlignSeqFromFile() { // As default get last used stored directory String suggestedDir = Settings.getLoadAlignmentDirectory(); File suggestedFile = new File(suggestedDir); File selectedFile = FileUtilities.selectOpenFileViaChooser(suggestedFile,aliViewWindow); if(selectedFile != null){ try { alignAndAddSequences(selectedFile); } catch (IOException e) { Messenger.showOKOnlyMessage(Messenger.ALIGNER_SOMETHING_PROBLEM_ERROR, LF + "Message: " + e.getLocalizedMessage(), aliViewWindow); e.printStackTrace(); } } } public void addAndAlignSeqFromClipboard() { try { String clipboardSelection = getClipboard(); logger.info(clipboardSelection); // Firstly see if there is a file in clipboard if(clipboardSelection != null && clipboardSelection.length() > 0){ File clipboardSequenceFile = new File(clipboardSelection); // if clipboard not was file if(! clipboardSequenceFile.exists()){ // if clipboard not is is fasta try to create fasta out of it if(! clipboardSelection.startsWith(">")){ //clipboardSelection = ">clipboard_sequence" + LF + clipboardSelection; // Tell user not a fasta file Messenger.showOKOnlyMessage(Messenger.NO_FASTA_IN_CLIPBOARD, aliViewWindow); return; } // save clipboard to file clipboardSequenceFile = AlignmentFile.createAliViewTempFile("clipboard_selection", ".fasta"); FileUtils.writeStringToFile(clipboardSequenceFile, clipboardSelection); } File newSequenceFile = clipboardSequenceFile; alignAndAddSequences(newSequenceFile); } } catch (IOException e1) { Messenger.showOKOnlyMessage(Messenger.ALIGNER_SOMETHING_PROBLEM_ERROR, LF + "Message: " + e1.getLocalizedMessage(), aliViewWindow); e1.printStackTrace(); } } public void toggleDrawCodonpos() { alignmentPane.setDrawCodonPosOnRuler(! alignmentPane.getDrawCodonPosOnRuler()); requestPaneAndRulerRepaint(); } public void toggleIgnoreGapInTranslation() { alignmentPane.setIgnoreGapInTranslation(! alignmentPane.getIgnoreGapInTranslation()); requestPaneAndRulerRepaint(); } public void toggleTranslationShowBoth() { alignmentPane.setShowTranslationAndNuc(! alignmentPane.getShowTranslationAndNuc()); requestPaneAndRulerRepaint(); } public void decReadingFrame() { alignment.decReadingFrame(); requestPaneAndRulerRepaint(); } public void incReadingFrame() { alignment.incReadingFrame(); requestPaneAndRulerRepaint(); } public void setReadingFrame(int readingFrame) { alignment.setReadingFrame(readingFrame); requestPaneAndRulerRepaint(); } public void toggleDrawAminoAcidCode() { alignmentPane.setDrawAminoAcidCode(! alignmentPane.isDrawAminoAcidCode()); requestPaneAndRulerRepaint(); } public void setEditMode(boolean allowEdit){ alignment.setEditMode(allowEdit); fireEditModeChanged(); } public void setShowTranslation(boolean selected) { alignmentPane.setShowTranslation(selected); if(selected == false){ } alignmentPane.setDrawCodonPosOnRuler(alignmentPane.isShowTranslation()); if(translationPanel != null){ translationPanel.setVisible(alignmentPane.isShowTranslation()); } requestPaneAndRulerRepaint(); } public void setHighlightNonConsensus(boolean selected) { alignmentPane.setHighlightNonCons(selected); requestPaneRepaint(); } public void setHighlightConsensus(boolean selected) { alignmentPane.setHighlightCons(selected); requestPaneRepaint(); } public void setHighlightDiff(boolean selected) { alignmentPane.setHighlightDiffTrace(selected); requestPaneRepaint(); } //private void setTranslationOnePos public void mntmToggleTranslationOnePos(){ logger.info("toggleOnePos"); // translated pos to nucleotide pos - save the current vals before changing // translated/nucleotide view, this is for scrolling to similar position Point oldTransPosTopLeft = alignmentPane.getVisibleUpperLeftMatrixPos(); Point oldNucPosTopLeft = alignmentPane.getVisibleUpperLeftMatrixPos(); Rectangle oldSelectRect = alignment.getSelectionAsMinRect(); boolean isPrevShowTransOnePos = alignment.isTranslatedOnePos(); alignment.setTranslationOnePos(! alignment.isTranslatedOnePos()); boolean isNowShowTransOnePos = alignmentPane.isShowTranslationOnePos(); aliViewMenuBar.setEditFunctionsEnabled(alignment.isEditable()); // this is to scroll pane to similair position when changing nucleotide/translationOnePos if(isPrevShowTransOnePos != isNowShowTransOnePos){ if(isPrevShowTransOnePos){ // adjust to make selection at same place after re-translation // get first selected position diff from upper left; int selectionDiff = 0; if(oldSelectRect != null){ selectionDiff = oldSelectRect.x - oldTransPosTopLeft.x; if(selectionDiff > 0 && selectionDiff < 1000){ selectionDiff = (int) (2.01 * (double) selectionDiff); }else{ selectionDiff = 0; } } // translated to nucleotide CodonPos codonPos = alignment.getAlignmentMeta().getCodonPositions().getCodonInTranslatedPos(oldTransPosTopLeft.x); Point nucPosUpperLeft = new Point(codonPos.startPos + selectionDiff, oldTransPosTopLeft.y); alignmentPane.scrollToVisibleUpperLeftMatrixPos(nucPosUpperLeft); } else{ // adjust to make selection at same place after translation // get first selected position diff from upper left; int selectionDiff = 0; if(oldSelectRect != null){ selectionDiff = oldSelectRect.x - oldNucPosTopLeft.x; if(selectionDiff > 0 && selectionDiff < 1000){ selectionDiff = (int) (0.685 * (double) selectionDiff); }else{ selectionDiff = 0; } } // nucleotide pos to translated int aaPos = alignment.getAlignmentMeta().getCodonPositions().getAminoAcidPosFromNucleotidePos( oldNucPosTopLeft.x); //logger.info("codonPos" + codonPosition); Point translatedUpperLeft = new Point(aaPos - selectionDiff, oldNucPosTopLeft.y); //logger.info(translatedUpperLeft); alignmentPane.scrollToVisibleUpperLeftMatrixPos(translatedUpperLeft); } } //alignmentPane.repaint(); // requestPaneAndRulerRepaint(); // if(toPoint != null){ // logger.info("alignmentPane.getSize()" + alignmentPane.getSize()); // alignmentPane.scrollToVisibleUpperLeftMatrixPos(toPoint); // } } public void sortSequencesByName() { aliViewWindow.getUndoControler().pushUndoState(new UndoSavedStateSequenceOrder(alignment.getSequences().getDelegateSequencesCopy(), alignment.getAlignentMetaCopy())); alignment.sortSequencesByName(); alignmentPane.validateSequenceOrder(); //requestPaneAndListRepaint(); } public void sortSequencesByCharColumn() { aliViewWindow.getUndoControler().pushUndoState(new UndoSavedStateSequenceOrder(alignment.getSequences().getDelegateSequencesCopy(), alignment.getAlignentMetaCopy())); alignment.sortSequencesByCharInSelectedColumn(); alignmentPane.validateSequenceOrder(); //requestPaneAndListRepaint(); } public void setSelectionAsNonCoding() { //aliViewWindow.getUndoControler().pushUndoState(new UndoSavedStateMetaOnly(alignment.getAlignentMetaCopy())); alignment.setSelectionAsNonCoding(); requestPaneAndRulerRepaint(); } public void setSelectionAsCoding(int startPos) { //aliViewWindow.getUndoControler().pushUndoState(new UndoSavedStateMetaOnly(alignment.getAlignentMetaCopy())); alignment.setSelectionAsCoding(startPos); requestPaneAndRulerRepaint(); } public void addOrRemoveSelectionToExcludes() { //getUndoControler().pushUndoState(); alignment.addOrRemoveSelectionToExcludes(); requestPaneRepaint(); } public void moveSelectedToBottom() { aliViewWindow.getUndoControler().pushUndoState(new UndoSavedStateSequenceOrder(alignment.getSequences().getDelegateSequencesCopy(), alignment.getAlignentMetaCopy())); alignment.moveSelectedSequencesToBottom(); //requestPaneAndListRepaint(); //alignmentPane.validateSize(); } public void moveSelectedToTop() { aliViewWindow.getUndoControler().pushUndoState(new UndoSavedStateSequenceOrder(alignment.getSequences().getDelegateSequencesCopy(), alignment.getAlignentMetaCopy())); alignment.moveSelectedSequencesToTop(); //requestPaneAndListRepaint(); //alignmentPane.validateSize(); } public void moveSelectedDown() { aliViewWindow.getUndoControler().pushUndoState(new UndoSavedStateSequenceOrder(alignment.getSequences().getDelegateSequencesCopy(), alignment.getAlignentMetaCopy())); alignment.moveSelectedSequencesDown(); requestScrollToVisibleSelection(); //alignmentPane.validateSize(); //requestRepaintAndRevalidateALL(); } public void moveSelectedUp() { logger.info("move sel up"); aliViewWindow.getUndoControler().pushUndoState(new UndoSavedStateSequenceOrder(alignment.getSequences().getDelegateSequencesCopy(), alignment.getAlignentMetaCopy())); alignment.moveSelectedSequencesUp(); requestScrollToVisibleSelection(); //alignmentPane.validateSize(); } public void moveSelectedTo(int index) { aliViewWindow.getUndoControler().pushUndoState(new UndoSavedStateSequenceOrder(alignment.getSequences().getDelegateSequencesCopy(), alignment.getAlignentMetaCopy())); alignment.moveSelectedSequencesTo(index); requestScrollToVisibleSelection(); } public void selectEverythingWithinGaps(Point point) { alignment.selectEverythingWithinGaps(point); //requestPaneRepaint(); } public void selectAll() { int size = sequenceJList.getModel().getSize(); if(size > 0){ sequenceJList.setSelectionInterval(0, size-1); } //alignment.selectAll(); //alignmentPane.repaint(); } public void deleteSelected(){ if(! requestEditMode()){ return; } /* aliViewWindow.getUndoControler().pushUndoState(); sequenceJList.deleteSelectedSequences(); alignment.deleteSelectedBases(); */ if(alignment.hasFullySelectedSequences()){ if(isUndoable()){ aliViewWindow.getUndoControler().pushUndoState(new UndoSavedStateSequenceOrder(alignment.getSequences().getDelegateSequencesCopy(), alignment.getAlignentMetaCopy())); } alignment.deleteFullySelectedSequences(); } else if(alignment.hasSelection()){ if(isUndoable()){ aliViewWindow.getUndoControler().pushUndoState(); } alignment.deleteSelectedBases(); } MemoryUtils.logMem(); requestRepaintAndRevalidateALL(); } public void deleteExludedBases() { aliViewWindow.getUndoControler().pushUndoState(); alignment.deleteAllExsetBases(); // Currently recalc codon-pos after deletion //alignment.getCodonPositions().updateCodonPositionsToDefault123BetweenExset(alignment.getExcludes()); //requestPaneRepaint(); } public void deleteEmptySequences() { aliViewWindow.getUndoControler().pushUndoState(); alignment.deleteEmptySequences(); /* // todo remove this ugly synch of list and pane so they communicate themselves SequenceListModel lm = (SequenceListModel) alignmentList.getModel(); ArrayList<Sequence> sequences = new ArrayList<Sequence>(); for(Sequence seq: lm){ sequences.add(seq); } */ //alignmentList.revalidate(); //requestPaneAndListRepaint(); } public void copySelectionAsFasta() { logger.info("copy selection as fasta"); alignment.copySelectionToClipboardAsFasta(); } public void copyNames() { alignment.copySelectionNames(); } public void copySelectionAsNucleotides() { alignment.copySelectionToClipboardAsNucleotides(); } public void renameFirstSelected(){ String name = alignment.getFirstSelectedSequenceName(); if(name != null){ // Position the edit dialog close to the sequence to be renamed Point pos = sequenceJList.getFirstSelectedCellPos(); pos.translate(130, -60); //logger.info("pos" + pos); TextEditDialog txtEdit = new TextEditDialog(pos); txtEdit.showOKCancelTextEditor(name, TextEditDialog.EDIT_SEQUENCE_NAME_TEXT, this); if(txtEdit.getSelectedValue() == JOptionPane.OK_OPTION){ String newName = txtEdit.getEditText(); List<Sequence> prevState = alignment.setFirstSelectedSequenceName(newName); if(isUndoable()){ aliViewWindow.getUndoControler().pushUndoState(new UndoSavedStateEditedSequences(prevState, alignment.getAlignmentMeta())); } requestRepaintAndRevalidateALL(); } } } public void addSequencesFromFile(int atIndex){ // As default get last used stored directory String suggestedDir = Settings.getLoadAlignmentDirectory(); File suggestedFile = new File(suggestedDir); File selectedFile = FileUtilities.selectOpenFileViaChooser(suggestedFile,aliViewWindow); if(selectedFile != null){ addSequencesFromFile(selectedFile, atIndex); } } public void addSequencesFromFile(File seqFile, int atIndex){ if(seqFile == null || !seqFile.exists()){ return; } aliViewWindow.getUndoControler().pushUndoState(); // if alignment is empty create a new one from the file // TODO this should not be needed to check, but handled gracefully as one method if(alignment.getSize() == 0){ Alignment newAlignment = newAlignment = AlignmentFactory.createNewAlignment(seqFile); if(newAlignment != null){ //initWindow(newAlignment); setupNewAlignment(newAlignment); } } else{ alignment.addSequences(seqFile, atIndex); //alignment.addFasta(clipboardSelection); } //requestRepaintAndRevalidateALL(); } public void pasteFasta(int pasteAtIndex) { String clipboardSelection = getClipboard(); if(clipboardSelection != null && ((FileFormat.isThisFasta(clipboardSelection)) || FileFormat.isThisSequenceFile(clipboardSelection))){ try { File clipFile = null; if(!FileFormat.isThisSequenceFile(clipboardSelection)){ clipFile = AlignmentFile.createAliViewTempFile("clipboard-alignment", ".fasta"); FileUtils.writeStringToFile(clipFile, clipboardSelection); }else{ clipFile = new File(clipboardSelection); } addSequencesFromFile(clipFile, pasteAtIndex); } catch (IOException e) { e.printStackTrace(); Messenger.showOKOnlyMessage(Messenger.ERROR_PASTE, LF + e.getLocalizedMessage(), aliViewWindow); } }else{ Messenger.showOKOnlyMessage(Messenger.NO_FASTA_IN_CLIPBOARD, aliViewWindow); } } public void pasteFasta() { pasteFasta(0); } public void merge2SelectedSequences() { List<Sequence> selected = alignment.getSelectedSequences(); if(selected.size() == 2){ aliViewWindow.getUndoControler().pushUndoState(); boolean isMerged = alignment.mergeTwoSequences(selected, true); if(isMerged){ alignment.deleteSequence(selected.get(1)); } } //requestRepaintAndRevalidateALL(); } public void deleteVerticalGaps() { aliViewWindow.getUndoControler().pushUndoState(); alignment.deleteVerticalGaps(); requestPaneRepaint(); //logger.info("alignment.getMaximumSequenceLength()" + alignment.getMaximumSequenceLength()); } public void find() { searchPanel.getSearchField().requestFocus(); searchPanel.getSearchField().selectAll(); // logger.info(searchPanel.getSearchField().getText()); } public void reverseComplementSelectedSequences() { aliViewWindow.getUndoControler().pushUndoState(); alignment.reverseComplementFullySelectedSequences(); //requestPaneRepaint(); } public void reverseComplementAlignment() { aliViewWindow.getUndoControler().pushUndoState(); alignment.reverseComplementAlignment(); } public void complementAlignment() { aliViewWindow.getUndoControler().pushUndoState(); alignment.complementAlignment(); } public void clearSelection(){ if(aliCursor != null){ aliCursor.restorePosition(); } alignment.clearSelection(); } public void invertSelection(){ // if(aliCursor != null){ // aliCursor.restorePosition(); // } // get the rect we have to repaint // Rectangle rect = alignment.getSelectionAsMinRect(); alignment.invertSelection(); //requestPaneRepaint(); } public void replaceSelectedWithChar(char typed) { aliViewWindow.getUndoControler().pushUndoState(); alignment.replaceSelectedWithChar(typed); // This is to repaint selected sequences only // Rectangle selectRect = alignment.getSelectionAsMinRect(); // Point paneXY = alignmentPane.matrixCoordToPaneCoord(new Point(selectRect.x, selectRect.y)); // Rectangle selectInPaneCoord = new Rectangle( paneXY.x, paneXY.y, // (int) (selectRect.width * alignmentPane.charWidth), // (int) (selectRect.height * alignmentPane.charHeight + alignmentPane.charHeight)); // selectInPaneCoord.grow(100, 100); // alignmentPane.paintImmediately(selectInPaneCoord); // alignmentPane.validateSize(); //requestRepaintSelectedSequences(); } public void deleteAllGaps() { if(! requestEditMode()){ return; } undoControler.pushUndoState(); alignment.deleteAllGaps(); alignment.rightPadSequencesWithGapUntilEqualLength(); //requestPaneRepaint();; } public void trimSequences() { undoControler.pushUndoState(); alignment.trimSequences(); //requestPaneRepaint(); } public void moveSelectionRight() { if(! requestEditMode()){ return; } List<Sequence> prevState = alignment.moveSelectionRight(isUndoable()); if(isUndoable()){ aliViewWindow.getUndoControler().pushUndoState(new UndoSavedStateEditedSequences(prevState, alignment.getAlignentMetaCopy())); } requestScrollToVisibleSelection(); } public void moveSelectionLeft(){ if(! requestEditMode()){ return; } List<Sequence> prevState = alignment.moveSelectionLeft(isUndoable()); if(isUndoable()){ aliViewWindow.getUndoControler().pushUndoState(new UndoSavedStateEditedSequences(prevState, alignment.getAlignentMetaCopy())); } requestScrollToVisibleSelection(); } public void deleteGapMoveLeft() { if(! requestEditMode()){ return; } List<Sequence> prevState = alignment.deleteGapMoveLeft(isUndoable()); if(isUndoable()){ aliViewWindow.getUndoControler().pushUndoState(new UndoSavedStateEditedSequences(prevState, alignment.getAlignentMetaCopy())); } alignmentPane.validateSize(); requestScrollToVisibleSelection(); } public void deleteGapMoveRight() { if(! requestEditMode()){ return; } List<Sequence> prevState = alignment.deleteGapMoveRight(isUndoable()); if(isUndoable()){ aliViewWindow.getUndoControler().pushUndoState(new UndoSavedStateEditedSequences(prevState, alignment.getAlignentMetaCopy())); } alignmentPane.validateSize(); requestScrollToVisibleSelection(); } public void insertGapMoveRight() { if(! requestEditMode()){ return; } List<Sequence> prevState = alignment.insertGapLeftOfSelectionMoveRight(isUndoable()); logger.debug("prevState" + prevState); if(isUndoable()){ aliViewWindow.getUndoControler().pushUndoState(new UndoSavedStateEditedSequences(prevState, alignment.getAlignentMetaCopy())); } alignmentPane.validateSize(); requestScrollToVisibleSelection(); } public void insertGapMoveLeft() { if(! requestEditMode()){ return; } List<Sequence> prevState = alignment.insertGapRightOfSelectionMoveLeft(isUndoable()); if(isUndoable()){ aliViewWindow.getUndoControler().pushUndoState(new UndoSavedStateEditedSequences(prevState, alignment.getAlignentMetaCopy())); } // This movement has to repaint all repaint selected sequences only alignmentPane.validateSize(); alignmentPane.scrollMatrixX(-1); requestScrollToVisibleSelection(); } public boolean requestReloadWindow(){ boolean isReloadOK = true; if(this.hasUnsavedEdits()){ // optionpane String message = "There might be unsaved edits - do you want to reload and loose changes?"; this.toFront(); int retVal = JOptionPane.showConfirmDialog(this, message, "Reload and loose changes?", JOptionPane.YES_NO_CANCEL_OPTION); if(retVal == JOptionPane.YES_OPTION){ isReloadOK = true; } if(retVal == JOptionPane.NO_OPTION){ isReloadOK = false; } if(retVal == JOptionPane.CANCEL_OPTION){ isReloadOK = false; } } else{ isReloadOK = true; } return isReloadOK; } public boolean requestWindowClose(){ boolean isCloseOK = true; if(this.hasUnsavedEdits()){ // optionpane String message = "There might be unsaved edits - save before close?"; this.toFront(); int retVal = JOptionPane.showConfirmDialog(this, message, "Save edits?", JOptionPane.YES_NO_CANCEL_OPTION); if(retVal == JOptionPane.YES_OPTION){ boolean wasFileSaved = this.saveAlignmentAsFileViaChooser(); // now is OK if(wasFileSaved){ isCloseOK = true; }else{ isCloseOK = false; } } if(retVal == JOptionPane.NO_OPTION){ isCloseOK = true; } if(retVal == JOptionPane.CANCEL_OPTION){ isCloseOK = false; } } else{ isCloseOK = true; } return isCloseOK; } public boolean isEmpty(){ boolean isEmpty = true; if(alignment != null && alignment.getSequences() != null && alignment.getSequences().getSize() > 0){ isEmpty = false; } return isEmpty; } public void selectDuplicates() { alignment.clearSelection(); alignment.selectDuplicates(); //requestPaneRepaint(); } private void setPaneAndListBGColor(Color color){ listTopOffset.setBackground(color); sequenceJList.setBackground(color); alignmentPane.setBackground(color); alignmentPane.getRulerComponent().setBackground(color); alignmentPane.getCharsetRulerComponent().setBackground(color); } public void setColorSchemeNucleotide(ColorScheme aScheme){ setPaneAndListBGColor(aScheme.getBaseBackgroundColor(NucleotideUtilities.GAP)); alignmentPane.setColorSchemeNucleotide(aScheme); requestPaneRepaint(); Settings.setColorSchemeNucleotide(aScheme); } public void setColorSchemeAminoAcid(ColorScheme aScheme) { setPaneAndListBGColor(aScheme.getBaseBackgroundColor(NucleotideUtilities.GAP)); alignmentPane.setColorSchemeAminoAcid(aScheme); requestPaneRepaint(); Settings.setColorSchemeAminoAcid(aScheme); } public void setGeneticCode(GeneticCode genCode) { alignment.setGeneticCode(genCode); requestPaneRepaint(); } public void setDifferenceTraceSequence(Point alignmentPanePos) { Point matrixPos = alignmentPane.paneCoordToMatrixCoord(alignmentPanePos); alignmentPane.setDifferenceTraceSequence((int)matrixPos.getY()); requestPaneRepaint(); } public void createStats(){ //alignment.getSequences().setTranslation(true); alignment.getStats(); MemoryUtils.logMem(); /* some old stuff for(int n = 0; n < 100; n++){ logger.info("askrepaint"); alignmentPane.repaint(); try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } */ // ArrayList<CharSet> charsets = alignment.getAlignentMeta().getCharsets(); // for(CharSet aCharSet: charsets){ // selectAll(aCharSet); // logger.info(aCharSet.getName()); // break; // } } public void selectAll(CharSet aCharSet) { alignment.selectAll(aCharSet); } /* public void fileSequencesChanged(){ alignment.fileSequenceContentsChanged(); createOrUpdateDynamicLoadFileMenu(); if(aliViewMenuBar != null){ aliViewMenuBar.updateAllMenuEnabled(); } if(statusPanel != null){ // TODO move these to somewhere else statusPanel.updateAll(); statusPanel.repaint(); } // Show message about limited edit capabilities boolean hideNextTimeSelected = Settings.getHideFileSeqLimitedEditCapabilities().getBooleanValue(); if(!hideNextTimeSelected){ hideNextTimeSelected = Messenger.showOKOnlyMessageWithCbx(Messenger.ONLY_VIEW_WHEN_FILESEQUENCES, true, this); Settings.getHideFileSeqLimitedEditCapabilities().putBooleanValue(hideNextTimeSelected); } } */ private void fireEditModeChanged() { aliViewMenuBar.editModeChanged(); } public void createOrUpdateDynamicLoadFileMenu(){ logger.info("create"); /* if(alignment.getSequences() instanceof FileSequenceAlignmentListModel && aliViewMenuBar != null){ final FileSequenceAlignmentListModel seqList = (FileSequenceAlignmentListModel) alignment.getSequences(); List<FilePage> pages = seqList.getFilePages(); if(pages != null && pages.size() > 1){ aliViewMenuBar.createDynamicLoadFilePages(seqList, pages); } } */ } /* * * Undo/Redo, very simple implemented * */ public void pushUndoState(){ if(isUndoable()){ UndoSavedState state = new UndoSavedStateEverything(alignment.getSequences().getCopy(), alignment.getAlignentMetaCopy()); pushUndoState(state); } } public void pushUndoState(UndoSavedState state){ undoList.add(state); // TODO this should maybe be handled better than indirect as here hasUnsavedUndoableEdits = true; this.updateWindowTitle(); fireUndoRedoChange(); } /* private String getUndoSavedStateFastaString(){ StringWriter fastaWriter = new StringWriter(); try { alignment.storeAlignmetAsFasta(new BufferedWriter(fastaWriter)); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } String fastaBuffer = fastaWriter.toString(); return fastaBuffer; } */ private void fireUndoRedoChange() { aliViewMenuBar.setUndoButtonEnabled(!isUndoStackEmpty()); aliViewMenuBar.setRedoButtonEnabled(!isRedoStackEmpty()); } public boolean isUndoStackEmpty(){ return ! undoList.hasAvailableUndos(); } public boolean isRedoStackEmpty(){ return ! undoList.hasAvailableRedos(); } private void undoSequenceEdit(UndoSavedStateEditedSequences undoObj) { logger.info("undoSequenceEdit"); for(Sequence previous: undoObj.editedSequences){ int index = alignment.getSequenceIndex(alignment.getSequenceByID(previous.getID())); alignment.getSequences().set(index, previous); } } private void undoMetaOnly(UndoSavedStateMetaOnly state) { logger.info("undoMetaOnly"); alignment.setAlignentMeta(state.meta); } private void undoSequenceOrder(UndoSavedStateSequenceOrder state) { logger.info("undoSequenceOrder"); alignment.getSequences().setSequences(state.sequencesBackend); // sequenceJList.setModel(alignment.getSequences()); // sequenceJList.setSelectionModel(alignment.getSequences().getAlignmentSelectionModel().getSequenceListSelectionModel()); alignment.setAlignentMeta(state.meta); } private void undoEverything(UndoSavedStateEverything state) throws AlignmentImportException { logger.info("undoEverything"); // alignment.setNewSequences(seqFactory.createSequences(new StringReader(state.fastaAlignment))); alignment.setNewSequencesFromUndo(state.sequences); // sequenceJList.setModel(alignment.getSequences()); alignment.setAlignentMeta(state.meta); } public void undo() { if(undoList.hasAvailableUndos()){ // Before first undo is performed save current state so it is possible to redo if(undoList.isCurrentStateNeeded()){ // Save current state undoList.addCurrentState(new UndoSavedStateEverything(alignment.getSequences().getCopy(), alignment.getAlignentMetaCopy())); } UndoSavedState undoObj = undoList.getUndoState(); logger.info("inne i undo"); if(undoObj instanceof UndoSavedStateEverything){ // No longer used try { logger.info("undo everyt"); undoEverything((UndoSavedStateEverything)undoObj); } catch (AlignmentImportException e) { Messenger.showOKOnlyMessage(Messenger.UNDO_REDO_PROBLEM, LF + e.getLocalizedMessage(), aliViewWindow); e.printStackTrace(); } }else if(undoObj instanceof UndoSavedStateSequenceOrder){ undoSequenceOrder((UndoSavedStateSequenceOrder)undoObj); }else if(undoObj instanceof UndoSavedStateEditedSequences){ undoSequenceEdit((UndoSavedStateEditedSequences)undoObj); }else if(undoObj instanceof UndoSavedStateMetaOnly){ undoMetaOnly((UndoSavedStateMetaOnly)undoObj); } requestRepaintAndRevalidateALL(); } if(isUndoStackEmpty()){ logger.info("updatingTitl"); hasUnsavedUndoableEdits = false; updateWindowTitle(); } fireUndoRedoChange(); } public void redo() { if(undoList.hasAvailableRedos()){ UndoSavedState redoObj = undoList.getRedoState(); if(redoObj instanceof UndoSavedStateEverything){ try { undoEverything((UndoSavedStateEverything)redoObj); } catch (AlignmentImportException e) { // TODO Auto-generated catch block e.printStackTrace(); Messenger.showOKOnlyMessage(Messenger.UNDO_REDO_PROBLEM, LF + e.getLocalizedMessage(), aliViewWindow); } }else if(redoObj instanceof UndoSavedStateSequenceOrder){ undoSequenceOrder((UndoSavedStateSequenceOrder)redoObj); }else if(redoObj instanceof UndoSavedStateEditedSequences){ undoSequenceEdit((UndoSavedStateEditedSequences)redoObj); }else if(redoObj instanceof UndoSavedStateMetaOnly){ undoMetaOnly((UndoSavedStateMetaOnly)redoObj); } requestRepaintAndRevalidateALL();; } fireUndoRedoChange(); } /* public static byte[] compress(String inString){ long startTime = System.currentTimeMillis(); // logger.info(inString.length()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { GZIPOutputStream gzipOS = new GZIPOutputStream(baos); byte[] uncompressed = inString.getBytes(); // logger.info(uncompressed.length); gzipOS.write(uncompressed); gzipOS.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } byte[] compressed = baos.toByteArray(); long endTime = System.currentTimeMillis(); logger.info("Compress took " + (endTime - startTime) + " milliseconds"); return compressed; } public static String decompress(byte[] compressed){ String decompressed = null; try { GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(compressed)); decompressed = IOUtils.toString(gis); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return decompressed; } */ /* * * End Undo * */ // TODO could be moved to alignmentPane - but is ok here for now (then labels could be passed to or from alignmentPane) // TODO could do a Selection change listener and also mousepointer moved listener (Easiest would be to do status label in alignment pane and pass it to window) // todo mouse listener on jlist - it is to slow to listen on selection change events (update on alignment pane is not instatiounous) private class AlignmentPaneMouseListener implements MouseListener, MouseMotionListener, MouseWheelListener { private Point startPoint; private Point startPointScreen; private Point startPaneVisibleRectLocation; private Point dragPointStart; private boolean isDragging; private Rectangle lastRect; private Rectangle maxRepaintRect; /* // Chech if no ctrl modifier - then clear previous selection if(! e.isControlDown()){ logger.info("modifiers" + e.getModifiers()); alignmentPane.clearSelection(); alignmentList.clearSelection(); } try { alignmentPane.selectBaseAt(mousePos); } catch (InvalidAlignmentPositionException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } */ public void mousePressed(MouseEvent e) { alignmentPane.requestFocus(); // Skip right click if(e.getButton() == e.BUTTON3){ return; } logger.info("mouse pressed" + e.getClickCount()); // Save some startpoints startPoint = e.getPoint(); startPointScreen = e.getLocationOnScreen(); startPaneVisibleRectLocation = alignmentPane.getVisibleRect().getLocation(); lastRect = new Rectangle(e.getPoint()); logger.info("points done"); // if click is within an existing selection // we should think about drag possibility if(alignmentPane.isWithinExistingSelection(e.getPoint())){ dragPointStart = e.getPoint(); }else{ // if shift is down something is selected already make a new rect selection if(e.isShiftDown()){ // this is done in mouse released instead } // new single point selection else{ // clear list selection sequenceJList.clearSelection(); alignmentPane.requestFocus(); alignment.clearSelection(); sequenceJList.clearSelection(); try { alignmentPane.selectBaseAt(startPoint); // statusPanel.setPointerPos(startPoint); } catch (InvalidAlignmentPositionException e1) { //nothing needs to be done e1.printStackTrace(); } } // requestPaneRepaint(); } } public void mouseReleased(MouseEvent e){ logger.info("mouseReleased e.getPoint=" + e.getPoint()); // Skip right click if(e.getButton() == e.BUTTON3){ return; } // logger.info("mouse released" + e.getClickCount()); if(startPoint == null){ logger.info("nostartpos"); }else{ // if startpoint is same as release-point select by point if(alignmentPane.paneCoordToMatrixCoord(e.getPoint()).distance(alignmentPane.paneCoordToMatrixCoord(startPoint)) == 0){ // if shift is down something is selected already make a new rect selection if(e.isShiftDown()){ // // set default first pos and override if cursor is selected // Point firstPos = alignment.getFirstSelectedPosition(); // // if there is a cursor-pos and it is selected then use it instead of // if(aliCursor != null){ // if(alignment.isBaseSelected(aliCursor.x, aliCursor.y)){ // firstPos = new Point(aliCursor.x, aliCursor.y); // } // } Point clickPoint = alignmentPane.paneCoordToMatrixCoord(e.getPoint()); Rectangle clickRect = new Rectangle(clickPoint); logger.info(clickRect); Rectangle currentSelection = alignment.getSelectionAsMinRect(); logger.info(currentSelection); Rectangle newSelection = Utils.addRects(clickRect, currentSelection); logger.info(newSelection); // clear before new selection - this to avoid non-rectangle selections alignment.clearSelection(); alignment.setSelectionWithin(newSelection); //int selectionSize = alignmentPane.selectWithin(newSelection); } else{ logger.info("mouse released"); // clear selection alignment.clearSelection(); alignment.clearTempSelection(); // if click is on ruler, all should get select if(e.getComponent() == alignmentPane.getRulerComponent()){ alignmentPane.selectColumnAt(startPoint); // cursor have to change int x = alignmentPane.getColumnAt(e.getPoint()); aliCursor.setPosition(x,0); }else{ try { alignmentPane.selectBaseAt(startPoint); } catch (InvalidAlignmentPositionException e1) { // nothing needs to be done e1.printStackTrace(); } } } }else if(isDragging){ isDragging = false; alignment.clearSelectionOffset(); dragPointStart = null; // else select by rectangle }else{ logger.info("select Within"); Rectangle selectRect = new Rectangle(e.getPoint()); selectRect.add(startPoint); logger.info("selectRect" + selectRect); if(e.isControlDown()){ // alignmentPane.addSelectionWithin(selectRect); } else{ int selectionSize = 0; alignment.clearSelection(); if(e.getComponent() == alignmentPane.getRulerComponent()){ selectionSize = alignmentPane.selectColumnsWithin(selectRect); }else{ selectionSize = alignmentPane.selectWithin(selectRect); } logger.info(alignment.getSelectionAsMinRect()); } alignment.clearTempSelection(); } // Clear stuff when released startPoint = null; startPointScreen = null; isDragging = false; alignment.clearSelectionOffset(); dragPointStart = null; } maxRepaintRect = null; //sequenceJList.validateSelection(); //requestPaneRepaint(); // logger.info(e.getPoint()); // new cursor-pos if shift is not pressed if(! e.isShiftDown()){ Point clickPos = alignmentPane.paneCoordToMatrixCoord(e.getPoint()); logger.info(clickPos); aliCursor.setPosition(clickPos.x, clickPos.y); } } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mouseClicked(MouseEvent e) { logger.info("mouse clicked" + e.getClickCount()); // Skip right click if(e.getButton() == e.BUTTON3){ return; } if(e.getClickCount() == 2){ Point matrixCoord = alignmentPane.paneCoordToMatrixCoord(e.getPoint()); logger.info(matrixCoord); selectEverythingWithinGaps(matrixCoord); } /* if(e.getButton() == e.BUTTON3){ logger.info("right-click"); try { alignmentPane.setDifferenceTraceSequence(e.getPoint()); } catch (InvalidAlignmentPositionException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } alignmentPane.repaint(); } */ } public void mouseDragged(MouseEvent e) { // logger.info("mouse dragged start"); // Theese lines makes sure pane is scrolling when user selects // and moves outside current visible rect (keyword scroll speed) Rectangle preferredVisisble = new Rectangle(e.getPoint()); // scroll if pointer outside of scrollpane window if(! alignmentPane.getVisibleRect().contains(e.getPoint())){ // grow little extra so it scrolls quickly in beginning preferredVisisble.grow(30,30); alignmentPane.scrollRectToVisible(preferredVisisble); } statusPanel.setPointerPos(e.getPoint()); if(startPoint != null){ // Dragging bases if(dragPointStart != null){ if(isDragging != true){ isDragging = true; getUndoControler().pushUndoState(); } Rectangle selectRect = alignment.getSelectionAsMinRect(); Rectangle selectInPaneCoord = alignmentPane.matrixCoordToPaneCoord(selectRect); //if(selectInPaneCoord.contains(e.getPoint())){ int diff = e.getPoint().x - dragPointStart.x; double diffInSeqPositons = diff/alignmentPane.getCharWidth(); int intDiffInseqPos = (int)diffInSeqPositons; // Test first if move is possible - otherwise many false requestedit if not possible if(alignment.isMoveSelectionRightPossible() || alignment.isMoveSelectionLeftPossible()){ if(requestEditMode()){ //if(e.getPoint().x >= selectInPaneCoord.x && e.getPoint().x <= selectInPaneCoord.getMaxX()){ alignment.moveSelection(intDiffInseqPos, isUndoable()); //} } } selectInPaneCoord.grow(4 + 3 * Math.abs(diff),0); //requestPaneRepaintRect(selectInPaneCoord); } // Selecting else{ Rectangle selectRect = new Rectangle(e.getPoint()); selectRect.add(startPoint); Rectangle selectRectMatrixCoords = alignmentPane.paneCoordToMatrixCoord(selectRect); alignment.setTempSelection(selectRectMatrixCoords); if(maxRepaintRect == null){ maxRepaintRect = new Rectangle(selectRect); }else{ maxRepaintRect.add(selectRect); } // requestPaneRepaintRect(new Rectangle(maxRepaintRect)); } // sequenceJList.validateSelection(); } // logger.info("mouse dragged done"); } public void mouseMoved(MouseEvent e) { // int ungapedPos = alignmentPane.getUngapedSequenceXPositionAt(e.getPoint()); // // add one because of program internaly works with pos 0 as the first // lblSelectionInfo.setText("" + (ungapedPos + 1) + " (ungaped position) "); } public void mouseWheelMoved(MouseWheelEvent e) { // Zoom in out if ctrl is pressed if(e.getModifiersEx() == OSNativeUtils.getMouseWheelZoomModifierMask()){ if(e.getWheelRotation() > 0){ aliViewWindow.zoomOutAt(e.getPoint()); } else if(e.getWheelRotation() < 0){ aliViewWindow.zoomInAt(e.getPoint()); } } // Else scroll pane left or right else if(e.isShiftDown()){ int wheelRotation = e.getWheelRotation(); if(aliViewWindow.isReverseHorizontalRotation()){ wheelRotation = wheelRotation * -1; } if(wheelRotation > 0){ Rectangle preferedVisible = alignmentPane.getVisibleRect(); preferedVisible.setLocation((int) (preferedVisible.x - (double)Settings.getHorizontalScrollModifier().getIntValue()/200 * preferedVisible.getWidth()), preferedVisible.y); alignmentPane.scrollRectToVisible(preferedVisible); alignmentPane.revalidate(); // break to avoid diagonal moves return; } else if(wheelRotation < 0){ Rectangle preferedVisible = alignmentPane.getVisibleRect(); preferedVisible.setLocation((int) (preferedVisible.x + (double)Settings.getHorizontalScrollModifier().getIntValue()/200 * preferedVisible.getWidth()), preferedVisible.y); alignmentPane.scrollRectToVisible(preferedVisible); alignmentPane.revalidate(); // break to avoid diagonal moves return; } // Else scroll pane up or down }else{ int wheelRotation = e.getWheelRotation(); if(aliViewWindow.isReverseVerticalRotation()){ wheelRotation = wheelRotation * -1; } if(wheelRotation > 0){ Rectangle preferedVisible = alignmentPane.getVisibleRect(); preferedVisible.setLocation(preferedVisible.x, (int) (preferedVisible.y + (double)Settings.getVerticalScrollModifier().getIntValue()/200 * preferedVisible.getHeight())); alignmentPane.scrollRectToVisible(preferedVisible); alignmentPane.revalidate(); // break to avoid diagonal moves return; } else if(wheelRotation < 0){ Rectangle preferedVisible = alignmentPane.getVisibleRect(); preferedVisible.setLocation(preferedVisible.x, (int) (preferedVisible.y - (double)Settings.getVerticalScrollModifier().getIntValue()/200 * preferedVisible.getHeight())); alignmentPane.scrollRectToVisible(preferedVisible); alignmentPane.revalidate(); // break to avoid diagonal moves return; } } } } // // END AlignmentPaneMouseListener // // // // // // TODO could be moved to alignment ruler (but it is ok here) private class AlignmentRulerMouseListener implements MouseListener, MouseMotionListener{ private Point startPoint; private Point startPointOnAlignmentPane; private Rectangle maxRepaintRect; public void mousePressed(MouseEvent e) { // Save some startpoints startPoint = e.getPoint(); startPointOnAlignmentPane = new Point(alignmentPane.getVisibleRect().x + e.getPoint().x,0); // if shift is down something is selected already make a new rect selection if(e.isShiftDown()){ } // clear and make new single point select else{ alignment.clearTempSelection(); sequenceJList.clearSelection(); alignment.clearSelection(); alignmentPane.selectColumnAt(startPointOnAlignmentPane); //requestPaneRepaint(); } } public void mouseReleased(MouseEvent e){ if(startPoint != null){ // if shift is down something is selected already make a new rect selection if(e.isShiftDown()){ Point firstPos = alignment.getFirstSelectedPosition(); Point paneFirstPoint = alignmentPane.matrixCoordToPaneCoord(firstPos); Rectangle selectRect = new Rectangle(paneFirstPoint); Point endPointOnAlignmentPane = new Point(alignmentPane.getVisibleRect().x + e.getPoint().x,alignmentPane.getHeight()); selectRect.add(endPointOnAlignmentPane); int selectionSize = alignmentPane.selectWithin(selectRect); } else{ Point endPointOnAlignmentPane = new Point(alignmentPane.getVisibleRect().x + e.getPoint().x,alignmentPane.getHeight()); Rectangle selectRect = new Rectangle(startPointOnAlignmentPane); selectRect.add(endPointOnAlignmentPane); logger.info(selectRect); int selectionSize = 0; alignment.clearSelection(); if(startPointOnAlignmentPane.x == endPointOnAlignmentPane.x){ alignmentPane.selectColumnAt(endPointOnAlignmentPane); int x = alignmentPane.getColumnAt(e.getPoint()); logger.info(aliCursor); logger.info(aliCursor.x); logger.info(aliCursor.y); aliCursor.setPosition(x,0); }else{ selectionSize = alignmentPane.selectColumnsWithin(selectRect); int x = alignmentPane.getColumnAt(e.getPoint()); logger.info(aliCursor); logger.info(aliCursor.x); logger.info(aliCursor.y); aliCursor.setPosition(x,0); } alignment.clearTempSelection(); } } Point posOnPaneNotRuler = new Point(alignmentPane.getVisibleRect().x + e.getPoint().x,0); Point matrixPoint = alignmentPane.paneCoordToMatrixCoord(posOnPaneNotRuler); logger.info("x=" + matrixPoint.x); aliCursor.setPosition(matrixPoint.x,0); // request focus after aliCursor change otherwise not really working alignmentPane.requestFocus(); // Clear startpoint startPoint = null; startPointOnAlignmentPane = null; maxRepaintRect = null; //requestPaneRepaint(); } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mouseClicked(MouseEvent e) { } public void mouseDragged(MouseEvent e) { // Theese lines makes sure pane is scrolling when user selects // and moves outside current visible rect int alignmentYPos = alignmentPane.getVisibleRect().y; int alignmentXPos = alignmentPane.getVisibleRect().x + e.getPoint().x; Rectangle preferredVisisble = new Rectangle(new Point(alignmentXPos,alignmentYPos)); if(! alignmentPane.getVisibleRect().contains(e.getPoint())){ // grow little extra so it scrolls quickly in beginning preferredVisisble.grow(30,0); alignmentPane.scrollRectToVisible(preferredVisisble); } if(startPoint != null){ Point endPointOnAlignmentPane = new Point(alignmentPane.getVisibleRect().x + e.getPoint().x,alignmentPane.getHeight()); Rectangle selectRect = new Rectangle(startPointOnAlignmentPane); selectRect.add(endPointOnAlignmentPane); Rectangle selectRectMatrixCoords = alignmentPane.paneCoordToMatrixCoord(selectRect); alignment.setTempSelection(selectRectMatrixCoords); if(maxRepaintRect == null){ maxRepaintRect = new Rectangle(selectRect); }else{ maxRepaintRect.add(selectRect); } //requestPaneRepaintRect(new Rectangle(maxRepaintRect)); } } public void mouseMoved(MouseEvent e) { // TODO Auto-generated method stub } } // // END AlignmentRulerMouseListener // private class AlignmentKeyListener implements KeyListener{ public void keyTyped(KeyEvent e){ logger.info("is typed"); if(e.isControlDown() || e.isAltDown() || e.isAltGraphDown() || e.isMetaDown()){ // Skip }else{ char typed = e.getKeyChar(); String allowedChars = "QWERTYUIOPASDFGHJKLZXCVBNM?qwertyuiopasdfghjklzxcvbnm"; if(allowedChars.indexOf(typed) > -1){ if(aliViewWindow.requestEditMode()){ replaceSelectedWithChar(typed); } } } } public void keyPressed(KeyEvent e) { //logger.info("keyPressed Time from last endTim " + (System.currentTimeMillis() - alignmentPane.getEndTime()) + " milliseconds"); // Skip if any modifier but shift is down if(e.isControlDown() || e.isAltDown() || e.isAltGraphDown() || e.isMetaDown()){ return; } // only if selection - otherwise key-press should be forwarded to scrollbars if(alignment.hasSelection()){ if(e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_KP_UP){ e.consume(); scrollToCursor(KeyEvent.VK_UP); moveCursorUp(e.isShiftDown()); } if(e.getKeyCode() == KeyEvent.VK_DOWN || e.getKeyCode() == KeyEvent.VK_KP_DOWN){ e.consume(); scrollToCursor(KeyEvent.VK_DOWN); moveCursorDown(e.isShiftDown()); } if(e.getKeyCode() == KeyEvent.VK_LEFT || e.getKeyCode() == KeyEvent.VK_KP_LEFT){ e.consume(); scrollToCursor(KeyEvent.VK_LEFT); moveCursorLeft(e.isShiftDown()); } if(e.getKeyCode() == KeyEvent.VK_RIGHT || e.getKeyCode() == KeyEvent.VK_KP_RIGHT){ e.consume(); scrollToCursor(KeyEvent.VK_RIGHT); moveCursorRight(e.isShiftDown()); } } } public void keyReleased(KeyEvent e) { } } private AliCursor createNewAliCursor(){ //alignment.clearSelection(); Point center = alignmentPane.matrixCoordToPaneCoord((new Point((int)alignmentPane.getVisibleRect().getCenterX(), (int)alignmentPane.getVisibleRect().getCenterY()))); AliCursor newAliCursor = new AliCursor(center.x, center.y); return newAliCursor; } public boolean isReverseHorizontalRotation() { return Settings.getReverseHorizontalMouseWheel().getBooleanValue(); } public boolean isReverseVerticalRotation() { return Settings.getReverseVerticalMouseWheel().getBooleanValue(); } public void scrollToCursor(int keyDirection) { AliCursor aliCursor = getAliCursor(); if(aliCursor != null){ Point pointInPaneCoord = alignmentPane.matrixCoordToPaneCoord(new Point(aliCursor.x, aliCursor.y)); Rectangle visiRect = new Rectangle(pointInPaneCoord); if(keyDirection == KeyEvent.VK_LEFT){ visiRect.add(visiRect.getMinX() - 40, visiRect.getCenterY()); } if(keyDirection == KeyEvent.VK_RIGHT){ visiRect.add(visiRect.getMaxX() + 40, visiRect.getCenterY()); } if(keyDirection == KeyEvent.VK_UP){ visiRect.add(visiRect.getCenterX(), visiRect.getMinY() - 40); } if(keyDirection == KeyEvent.VK_DOWN){ visiRect.add(visiRect.getCenterX(), visiRect.getMaxY() + 40); } if(! alignmentPane.getVisibleRect().contains(visiRect)){ alignmentPane.scrollRectToVisible(visiRect); } } } public void scrollToVisibleCursor() { AliCursor aliCursor = getAliCursor(); logger.info(aliCursor); if(aliCursor != null){ logger.info("point" + new Point(aliCursor.x, aliCursor.y)); Point pointInPaneCoord = alignmentPane.matrixCoordToPaneCoord(new Point(aliCursor.x, aliCursor.y)); Rectangle visiRect = new Rectangle(pointInPaneCoord); visiRect.grow(40, 40); logger.info("alignmentPane.getVisibleRect()" + alignmentPane.getVisibleRect()); logger.info("alignmentPane.getVisibleRect().contains(visiRect)" + alignmentPane.getVisibleRect().contains(visiRect)); if(! alignmentPane.getVisibleRect().contains(visiRect)){ alignmentPane.scrollRectToVisible(visiRect); } } } private AliCursor getAliCursor(){ if(aliCursor == null){ aliCursor = createNewAliCursor(); } return aliCursor; } public void moveCursorUp(boolean isShiftDown){ logger.info("Before Up Time from last endTim " + (System.currentTimeMillis() - alignmentPane.getEndTime()) + " milliseconds"); getAliCursor().moveUp(isShiftDown); logger.info("DoneUp Time from last endTim " + (System.currentTimeMillis() - alignmentPane.getEndTime()) + " milliseconds"); //requestRepaintCursor(); } public void moveCursorDown(boolean isShiftDown){ getAliCursor().moveDown(isShiftDown); //requestRepaintCursor(); } public void moveCursorLeft(boolean isShiftDown){ getAliCursor().moveLeft(isShiftDown); //requestRepaintCursor(); } public void moveCursorRight(boolean isShiftDown){ getAliCursor().moveRight(isShiftDown); //requestRepaintCursor(); } private class AliCursor{ int x; int y; Sequence cursorSeq; int posInSeq; public AliCursor(int x, int y) { setPosition(x, y); } public void setPosition(int x, int y){ this.x = x; this.y = y; savePosition(); } public void restorePosition(){ if(cursorSeq != null){ int xFromSeq = cursorSeq.getPosOfSelectedIndex(posInSeq); int yFromSeq = alignment.getSequenceIndex(cursorSeq); if(alignment.isPositionValid(xFromSeq ,yFromSeq)){ x = xFromSeq; y = yFromSeq; } } } public void savePosition(){ if(alignment != null && alignment.getSequences() != null){ if(alignment.isPositionValid(x, y)){ logger.info("savepos"); this.cursorSeq = alignment.getSequences().get(y); this.posInSeq = (int) cursorSeq.countSelectedPositions(0, x); } } } public void moveLeft(boolean isShiftDown){ restorePosition(); if(alignment.isPositionValid(x-1,y)){ if(isShiftDown){ // if moving into selection deselect previous if(alignment.getSelectionAt(x-1, y) == true){ alignment.clearColumnSelection(x); } // if moving into clear then select and leave previous else{ alignment.copySelectionFromPosX1toX2(x,x-1); } }else{ alignment.setSelectionAt(x-1, y, true); } x--; } savePosition(); } public void moveRight(boolean isShiftDown){ restorePosition(); if(alignment.isPositionValid(x+1,y)){ if(isShiftDown){ // if moving into selection deselect previous if(alignment.getSelectionAt(x+1, y) == true){ alignment.clearColumnSelection(x); } // if moving into clear then select and leave previous else{ alignment.copySelectionFromPosX1toX2(x, x+1); } }else{ alignment.setSelectionAt(x+1, y, true); } x++; } savePosition(); } public void moveUp(boolean isShiftDown){ restorePosition(); if(alignment.isPositionValid(x,y-1)){ if(isShiftDown){ // if moving into selection deselect previous if(alignment.getSelectionAt(x, y-1) == true){ alignment.setAllHorizontalSelectionAt(y, false); } // if moving into clear then select and leave previous else{ alignment.copySelectionFromSequenceTo(y, y-1); } }else{ alignment.setSelectionAt(x, y-1, true); } y--; } savePosition(); } public void moveDown(boolean isShiftDown){ restorePosition(); if(alignment.isPositionValid(x,y+1)){ if(isShiftDown){ // if moving into selection deselect previous if(alignment.getSelectionAt(x, y+1) == true){ alignment.setAllHorizontalSelectionAt(y, false); // if moving into clear then select and leave previous }else{ alignment.copySelectionFromSequenceTo(y,y+1); } }else{ alignment.setSelectionAt(x, y+1, true); } y++; } savePosition(); } } public void editAlignerALLSettings() { SettingsFrame settingsFrame = new SettingsFrame(this); settingsFrame.selectTab(SettingsFrame.TAB_ALIGN_ALL); settingsFrame.setVisible(true); } public void editAlignerADDSettings() { SettingsFrame settingsFrame = new SettingsFrame(this); settingsFrame.selectTab(SettingsFrame.TAB_ALIGN_ADD); settingsFrame.setVisible(true); } public void editExternalCommands() { SettingsFrame settingsFrame = new SettingsFrame(this); settingsFrame.selectTab(SettingsFrame.TAB_EXTERNAL_COMMANDS); settingsFrame.setVisible(true); } public void findPrimerSettings(){ SettingsFrame settingsFrame = new SettingsFrame(this); settingsFrame.selectTab(SettingsFrame.TAB_PRIMER); settingsFrame.setVisible(true); } public void openPreferencesGeneral() { SettingsFrame settingsFrame = new SettingsFrame(this); settingsFrame.selectTab(SettingsFrame.TAB_GENERAL); settingsFrame.setVisible(true); } public void runExternalCommand(CommandItem cmdItem){ cmdItem.reParseCommand(); runExternalCommandImplementation(cmdItem); } public void runExternalCommandImplementation(final CommandItem cmdItem){ // Output window final SubProcessWindow subProcessWin = new SubProcessWindow(aliViewWindow); //subProcessWin.init(); subProcessWin.setTitle(cmdItem.getName()); subProcessWin.setAlwaysOnTop(false); subProcessWin.placeFrameupperLeftLocationOfThis(aliViewWindow); if(cmdItem.isShowCommandWindow()){ subProcessWin.show(); } try { // Save current alignment in tempdir to make sure unsaved edits are included //File currentAlignmentTempFile = File.createTempFile("current-alignment", ".fasta"); //alignment.saveAlignmentAsFile(currentAlignmentTempFile, FileFormat.FASTA); // Save current alignment in tempdir (to be sure all unsaved changes are there) FileFormat currentTempFileFormat = cmdItem.getCurrentAlignmentFileFormat(); File currentAlignmentTempFile = AlignmentFile.createAliViewTempFile("current-alignment", currentTempFileFormat.getSuffix()); alignment.saveAlignmentAsFile(currentAlignmentTempFile, currentTempFileFormat); // Create a tempFile for new alignment File emptyTempFile = AlignmentFile.createAliViewTempFile("tempfile-for-new-alignment", ".tmp"); cmdItem.setParameterCurrentFile(currentAlignmentTempFile); cmdItem.setParameterOutputFile(emptyTempFile); Thread thread = new Thread(new Runnable(){ public void run(){ try { ExternalCommandExecutor.executeMultiple(cmdItem, subProcessWin); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); Messenger.showOKOnlyMessage(Messenger.ERROR_RUNNING_EXTERNAL_COMMAND, LF + e.getLocalizedMessage(), aliViewWindow); } logger.info("done external"); SwingUtilities.invokeLater(new Runnable() { public void run(){ boolean wasProcessInterruptedByUser = subProcessWin.wasSubProcessDestrouedByUser(); aliViewWindow.externalCommandCallback(cmdItem); subProcessWin.dispose(); } }); } }); // No locking of the GUI when running personal command // glassPane.setVisible(true); thread.start(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } protected void externalCommandCallback(CommandItem cmdItem) { logger.info("this method is not implemented yet"); } public boolean isEditMode(){ return alignment.isEditMode(); } public boolean requestEditMode(){ if(isEditMode() == false){ // optionpane /* String message = "Edit key/menu pressed (or mouse edit), " + LF + "do you want to allow edits?"; int retVal = JOptionPane.showConfirmDialog(aliViewWindow, message, "Edit mode?", JOptionPane.OK_CANCEL_OPTION); if(retVal == JOptionPane.OK_OPTION){ aliViewWindow.setEditMode(true); }else{ // do nothing } // return false after question always // return false; */ boolean allowEdit = Messenger.askAllowEditMode(); if(allowEdit){ aliViewWindow.setEditMode(true); }else{ // do nothing } /* // Skip asking if checkbox "hide this message" if(Settings.getHideEditModeMessage().getBooleanValue() == true){ aliViewWindow.setEditMode(true); // Ask user }else{ logger.info("ask user"); Messenger.showOKOnlyMessage(Messenger.EDIT_MODE_QUESTION, this); //boolean hideNextTimeSelected = Messenger.showOKCancelMessageWithCbx(Messenger.EDIT_MODE_QUESTION, false, this); //Settings.getHideEditModeMessage().putBooleanValue(false); int retVal = Messenger.getLastSelectedOption(); logger.info("retval=" + retVal); if(retVal == JOptionPane.OK_OPTION){ logger.info("set edit mode"); aliViewWindow.setEditMode(true); }else{ // do nothing } } */ // return false after question always // return false; } return isEditMode(); } public void printAlignment(){ PrinterJob job = PrinterJob.getPrinterJob(); // job.setJobName("Printing alignment from AliView"); PageFormat pf = job.defaultPage(); // Paper paper = new Paper(); // paper.setSize(595, 842); // paper.setImageableArea(43, 43, 509, 756); // paper.setSize(8.5 * 72, 11 * 72); // paper.setImageableArea(0.5 * 72, 0.0 * 72, 7.5 * 72, 10.5 * 72); // pf.setPaper(paper); // pf.setOrientation(PageFormat.LANDSCAPE); // Book book = new Book();//java.awt.print.Book // book.append(this, pf); // job.setPageable(book); // job.setPrintable(this); boolean ok = job.printDialog(); if (ok) { try { job.print(); } catch (PrinterException ex) { Messenger.showOKOnlyMessage(Messenger.ERROR_PRINTING, LF + ex.getLocalizedMessage(), aliViewWindow); ex.printStackTrace(); /* The job did not successfully complete */ } } } /* public void newAlignmentLoaded(){ // remove jmenu Dynamic loaded files aliViewMenuBar.removeDynamicLoadFilePagesMenu(); statusPanel.updateAll(); statusPanel.repaint(); //aliViewMenuBar } */ // // AlignmentListener // public void newSequences(AlignmentEvent alignmentEvent) { } public void alignmentMetaChanged(AlignmentEvent alignmentEvent) { } // // AlignmentDataListener // public void intervalAdded(ListDataEvent e) { if(e instanceof AlignmentDataEvent){ contentsChanged((AlignmentDataEvent)e); } } public void intervalRemoved(ListDataEvent e) { if(e instanceof AlignmentDataEvent){ contentsChanged((AlignmentDataEvent)e); } } public void contentsChanged(ListDataEvent e) { if(e instanceof AlignmentDataEvent){ contentsChanged((AlignmentDataEvent)e); } } public void contentsChanged(AlignmentDataEvent e) { logger.info("selectionChanged"); requestRepaintRect(e.getBounds()); } // // AlignmentSelectionListener // public void selectionChanged(AlignmentSelectionEvent e) { logger.info("selectionChanged"); requestRepaintRect(e.getBounds()); } public void requestRepaintRect(Rectangle rect) { int dx =(int) (alignmentPane.getCharWidth() * 3); int dy =(int) (alignmentPane.getCharHeight() * 1); // if small chars, redraw at least a few pix if(dx < 3 || dy < 1){ dx = 6; dy = 2; } Rectangle paneBounds = alignmentPane.matrixCoordToPaneCoord(rect); Rectangle grown = new Rectangle(paneBounds.x - dx, paneBounds.y - dy, paneBounds.getBounds().width + 2*dx, paneBounds.getBounds().height + 2*dy); alignmentPane.validateSize(); alignmentPane.validateSequenceOrder(); //alignmentPane.paintImmediately(paneBounds); //aliList.paintImmediately(aliList.getVisibleRect()); //alignmentPane.scrollRectToVisible(paneBounds); //logger.info("paneBounds" + paneBounds); alignmentPane.repaint(grown); //alignmentPane.repaint(); //aliList.repaint(); Rectangle visiRect = sequenceJList.getVisibleRect(); Rectangle drawListBounds = new Rectangle(visiRect.x,grown.y, visiRect.width, grown.height); // sequenceJList.scrollRectToVisible(drawListBounds); logger.info("drawListBounds" + drawListBounds); // sequenceJList.repaint(visiRect.x,paneBounds.y, visiRect.width, paneBounds.height); sequenceJList.repaint(drawListBounds); } public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)throws PrinterException{ double dpi = 72; double pixPerMM = PrintUtils.mmToPixel(1,dpi); double imagableX = pageFormat.getImageableX(); double imagableY = pageFormat.getImageableY(); double pgHeight = pageFormat.getImageableHeight(); double pgWidth = pageFormat.getImageableWidth(); Dimension pageSize = new Dimension(); pageSize.setSize(pgWidth, pgHeight); logger.info("x" + imagableX); logger.info("y" + imagableY); logger.info("width" + pgWidth); logger.info("height" + pgHeight); logger.info("thiswidth" + this.getWidth()); logger.info("thisheight" + this.getHeight()); double scaleFactor = PrintUtils.getScaleFactorToFit(this.getSize(),pageSize); logger.info(scaleFactor); // create a copy so nothing is altered in the original one Graphics2D g2 = (Graphics2D) graphics.create(); // // I tried to use a separate AffineTransform - but I didn't work out // but using the one already in the Graphics object works fine // // keep original transform so we can translate new in between the things to draw AffineTransform savedTrans = (AffineTransform) g2.getTransform().clone(); Rectangle rulerRect = alignmentPane.getRulerComponent().getVisibleRect(); double rulerHeight = rulerRect.getHeight(); logger.info("rulerHeight" + rulerHeight); Rectangle listVisible = listScrollPane.getViewport().getVisibleRect(); // resize a little bit so list doesnt get truncated listVisible.setSize(listVisible.width + 5, listVisible.height); logger.info("listVisible.width" + listVisible.width); // Print sequence List (actually the viewport of the scrollpane) g2.translate(imagableX, imagableY + (rulerHeight*scaleFactor)); g2.scale(scaleFactor, scaleFactor); g2.setClip(listVisible); listScrollPane.getViewport().paint(g2); double extraSpaceBTWListAndPane = 2; // Print ruler g2.setTransform((AffineTransform) savedTrans.clone()); g2.translate((listVisible.width + extraSpaceBTWListAndPane)*scaleFactor + imagableX, imagableY); g2.scale(scaleFactor, scaleFactor); g2.setClip(rulerRect); alignmentPane.getRulerComponent().paint(g2); // Print alignment (actually the viewport of the scrollpane) g2.setTransform((AffineTransform) savedTrans.clone()); g2.translate((listVisible.width + extraSpaceBTWListAndPane)*scaleFactor + imagableX, imagableY + (rulerHeight*scaleFactor)); g2.scale(scaleFactor, scaleFactor); g2.setClip(alignmentScrollPane.getViewport().getVisibleRect()); alignmentScrollPane.getViewport().paintAll(g2); logger.info(pageIndex); // clean up, dispose the created graphics g2.dispose(); // only print one page if(pageIndex > 0){ return Printable.NO_SUCH_PAGE; }else{ return Printable.PAGE_EXISTS; } } public Alignment getAlignment() { return alignment; } public void showAbout() { String version = AliView.getVersion(); logger.info("version=" + version); String message = "AliView version: " + version; JOptionPane.showMessageDialog(aliViewWindow, message, "About", JOptionPane.INFORMATION_MESSAGE); } public void checkNewVersion() { String version = AliView.getVersion(); HelpUtils.displayVersionDownload(version); } public void displayVersionHistory() { HelpUtils.displayVersionHistory(); } public void openBugReportPage() { HelpUtils.display(HelpUtils.BUG_OR_FEATURE, this); } public void openHelp() { HelpUtils.display(HelpUtils.TOP_HELP, this); } public void countStopCodons() { int count = alignment.countStopCodons(); Messenger.showCountStopCodonMessage(count, this); } public void startDebug() { Logger.getRootLogger().setLevel(Level.ALL); } public void requestGB() { System.gc(); } public void saveFastaIndex() { alignment.saveFastaIndex(); } public void expandSelectionRight() { alignment.selectionExtendRight(); } public void expandSelectionLeft() { alignment.selectionExtendLeft(); } public void phenotype2genotype() { // As default get last used stored directory String suggestedDir = Settings.getLoadAlignmentDirectory(); File suggestedFile = new File(suggestedDir); File selectedFile = FileUtilities.selectOpenFileViaChooser(suggestedFile,aliViewWindow.getParent()); if(selectedFile != null){ try { File fastaGenResultFile = new File(selectedFile.getParentFile(), selectedFile.getName() + "_genotype" + "." + FileFormat.FASTA.getSuffix()); Phenotype2Genootype gen2phen = new Phenotype2Genootype(); gen2phen.createGenotypeFasta(selectedFile, fastaGenResultFile); AliView.openAlignmentFile(fastaGenResultFile); //Settings.putLoadAlignmentDirectory(selectedFile.getParent()); } catch (Exception e) { e.printStackTrace(); Messenger.showOKOnlyMessage(Messenger.PHENOTYPE_IMAGE_OPEN_ERROR, LF + e.getLocalizedMessage(), this); } } } public void addNewSequence() { alignment.addNewSequence(); //requestRepaintAndRevalidateALL(); } public void setFontCaseUpper(boolean selected) { int fontCase = CharPixels.CASE_UNTOUCHED; if(selected){ fontCase = CharPixels.CASE_UPPER; } alignmentPane.setFontCase(fontCase); Settings.getFontCase().putIntValue(fontCase); requestRepaintAndRevalidateALL(); } public void showCharsetsRuler(boolean selected) { alignmentPane.setShowCharsetRuler(selected); Settings.getShowCharsetRuler().putBooleanValue(selected); requestRepaintAndRevalidateALL(); } public void editCharsets() { TextEditFrame frame = new TextEditFrame(this); TextEditPanelCharsets panel = new TextEditPanelCharsets(frame, this); frame.init(panel); frame.setVisible(true); } }