From 3e3378e2ccfea39a2b161600c5a2029716acd1b7 Mon Sep 17 00:00:00 2001 From: amwaterhouse Date: Tue, 14 Nov 2006 15:25:29 +0000 Subject: [PATCH] Commands, history, consensus, refresh updated --- src/jalview/appletgui/APopupMenu.java | 18 +- src/jalview/appletgui/AlignFrame.java | 461 +++++++++++++++---------- src/jalview/appletgui/AlignViewport.java | 492 ++++++++++++++++++++------- src/jalview/appletgui/AlignmentPanel.java | 28 ++ src/jalview/appletgui/IdCanvas.java | 4 +- src/jalview/appletgui/IdPanel.java | 2 +- src/jalview/appletgui/PaintRefresher.java | 199 +++++++++-- src/jalview/appletgui/RedundancyPanel.java | 99 +++--- src/jalview/appletgui/RotatableCanvas.java | 4 +- src/jalview/appletgui/SeqCanvas.java | 2 +- src/jalview/appletgui/SeqPanel.java | 228 +++++++------ src/jalview/appletgui/SequenceRenderer.java | 3 + src/jalview/appletgui/TreeCanvas.java | 10 +- 13 files changed, 1034 insertions(+), 516 deletions(-) diff --git a/src/jalview/appletgui/APopupMenu.java b/src/jalview/appletgui/APopupMenu.java index 8afc841..e837ec8 100755 --- a/src/jalview/appletgui/APopupMenu.java +++ b/src/jalview/appletgui/APopupMenu.java @@ -67,6 +67,8 @@ public class APopupMenu Sequence seq; MenuItem revealAll = new MenuItem(); + MenuItem menuItem1 = new MenuItem(); + Menu menu1 = new Menu(); public APopupMenu(AlignmentPanel apanel, final Sequence seq, Vector links) { @@ -347,19 +349,16 @@ public class APopupMenu hideSeqs.setLabel("Hide Sequences"); repGroup.setLabel("Represent Group with"); revealAll.setLabel("Reveal All"); - + menuItem1.setLabel("Create Sequence Feature"); + menu1.setLabel("Group"); add(groupMenu); this.add(seqMenu); this.add(hideSeqs); this.add(revealAll); groupMenu.add(editMenu); groupMenu.add(outputmenu); - groupMenu.addSeparator(); - groupMenu.add(unGroupMenuItem); - groupMenu.add(colourMenu); - groupMenu.add(showBoxes); - groupMenu.add(showText); - groupMenu.add(showColourText); + groupMenu.add(menuItem1); + groupMenu.add(menu1); colourMenu.add(noColourmenuItem); colourMenu.add(clustalColour); colourMenu.add(BLOSUM62Colour); @@ -417,6 +416,11 @@ public class APopupMenu editMenu.add(toggleCase); seqMenu.add(pdb); seqMenu.add(repGroup); + menu1.add(unGroupMenuItem); + menu1.add(colourMenu); + menu1.add(showBoxes); + menu1.add(showText); + menu1.add(showColourText); toggleCase.addActionListener(this); pdb.addActionListener(this); hideSeqs.addActionListener(this); diff --git a/src/jalview/appletgui/AlignFrame.java b/src/jalview/appletgui/AlignFrame.java index 147c2dd..ff7646f 100755 --- a/src/jalview/appletgui/AlignFrame.java +++ b/src/jalview/appletgui/AlignFrame.java @@ -61,6 +61,9 @@ public class AlignFrame extends Frame implements ActionListener, viewport = new AlignViewport(al, applet); alignPanel = new AlignmentPanel(this, viewport); + viewport.updateConservation(alignPanel); + viewport.updateConsensus(alignPanel); + annotationPanelMenuItem.setState(viewport.showAnnotation); seqLimits.setState(viewport.showJVSuffix); @@ -114,17 +117,6 @@ public class AlignFrame extends Frame implements ActionListener, alignPanel.scalePanel.addKeyListener(this); alignPanel.annotationPanel.addKeyListener(this); - viewport.addPropertyChangeListener(new java.beans.PropertyChangeListener() - { - public void propertyChange(java.beans.PropertyChangeEvent evt) - { - if (evt.getPropertyName().equals("alignment")) - { - alignmentChanged(); - } - } - }); - if(embedded) { @@ -475,9 +467,9 @@ public void itemStateChanged(ItemEvent evt) else if(source==invertColSel) { viewport.invertColumnSelection(); alignPanel.repaint(); } else if(source==remove2LeftMenuItem) - remove2LeftMenuItem_actionPerformed(); + trimAlignment(true); else if(source==remove2RightMenuItem) - remove2RightMenuItem_actionPerformed(); + trimAlignment(false); else if(source==removeGappedColumnMenuItem) removeGappedColumnMenuItem_actionPerformed(); else if(source==removeAllGapsMenuItem) @@ -664,27 +656,73 @@ public void itemStateChanged(ItemEvent evt) this.dispose(); } - Stack historyList = new Stack(); - Stack redoList = new Stack(); + /** + * DOCUMENT ME! + */ void updateEditMenuBar() { + + if (viewport.historyList.size() > 0) + { + undoMenuItem.setEnabled(true); + CommandI command = (CommandI) viewport.historyList.peek(); + undoMenuItem.setLabel("Undo " + command.getDescription()); + } + else + { + undoMenuItem.setEnabled(false); + undoMenuItem.setLabel("Undo"); + } + + if (viewport.redoList.size() > 0) + { + redoMenuItem.setEnabled(true); + + CommandI command = (CommandI) viewport.redoList.peek(); + redoMenuItem.setLabel("Redo " + command.getDescription()); + } + else + { + redoMenuItem.setEnabled(false); + redoMenuItem.setLabel("Redo"); + } } + public void addHistoryItem(CommandI command) + { + if(command.getSize()>0) + { + viewport.historyList.push(command); + viewport.redoList.removeAllElements(); + updateEditMenuBar(); + viewport.hasHiddenColumns = viewport.colSel.getHiddenColumns() != null; + } + } protected void undoMenuItem_actionPerformed() { + CommandI command = (CommandI)viewport.historyList.pop(); + viewport.redoList.push(command); + command.undoCommand(); + + viewport.hasHiddenColumns = viewport.colSel.getHiddenColumns() != null; + updateEditMenuBar(); + viewport.firePropertyChange("alignment", null, + viewport.getAlignment().getSequences()); } protected void redoMenuItem_actionPerformed() { + CommandI command = (CommandI) viewport.redoList.pop(); + viewport.historyList.push(command); + command.doCommand(); + viewport.hasHiddenColumns = viewport.colSel.getHiddenColumns()!=null; + updateEditMenuBar(); + viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences()); } - // used by undo and redo - void restoreHistoryItem(CommandI command) - { - } public void moveSelectedSequences(boolean up) { @@ -836,8 +874,6 @@ public void itemStateChanged(ItemEvent evt) protected void pasteThis_actionPerformed() { - // addHistoryItem(new HistoryItem("Paste Sequences", viewport.alignment, - // HistoryItem.PASTE)); paste(false); } @@ -857,26 +893,16 @@ public void itemStateChanged(ItemEvent evt) String name = st.nextToken(); int start = Integer.parseInt(st.nextToken()); int end = Integer.parseInt(st.nextToken()); - Sequence sequence = new Sequence(name, st.nextToken(), start, end); - - if (!newAlignment) - { - viewport.alignment.addSequence(sequence); - } - else - { - seqs.addElement(sequence); - } + seqs.addElement(new Sequence(name, st.nextToken(), start, end)); + } + SequenceI[] newSeqs = new SequenceI[seqs.size()]; + for (int i = 0; i < seqs.size(); i++) + { + newSeqs[i] = (SequenceI) seqs.elementAt(i); } if (newAlignment) { - SequenceI[] newSeqs = new SequenceI[seqs.size()]; - for (int i = 0; i < seqs.size(); i++) - { - newSeqs[i] = (SequenceI) seqs.elementAt(i); - } - String newtitle = new String("Copied sequences"); if (getTitle().startsWith("Copied sequences")) { @@ -905,6 +931,16 @@ public void itemStateChanged(ItemEvent evt) } else { + //!newAlignment + addHistoryItem(new EditCommand( + "Add sequences", + EditCommand.PASTE, + newSeqs, + 0, + viewport.alignment.getWidth(), + viewport.alignment) + ); + viewport.setEndSeq(viewport.alignment.getHeight()); viewport.alignment.getWidth(); viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences()); @@ -924,63 +960,62 @@ public void itemStateChanged(ItemEvent evt) protected void delete_actionPerformed() { - //addHistoryItem(new HistoryItem("Delete Sequences", viewport.alignment, - // HistoryItem.HIDE)); - if (viewport.getSelectionGroup() == null) + + SequenceGroup sg = viewport.getSelectionGroup(); + if (sg == null) { return; } - - SequenceGroup sg = viewport.getSelectionGroup(); - boolean allSequences = false; - if(sg.getSize(false)==viewport.alignment.getHeight()) - allSequences = true; - + Vector seqs = new Vector(); + SequenceI seq; for (int i = 0; i < sg.getSize(false); i++) { - SequenceI seq = sg.getSequenceAt(i); - int index = viewport.getAlignment().findIndex(seq); - seq.deleteChars(sg.getStartRes(), sg.getEndRes() + 1); + seq = sg.getSequenceAt(i); + seqs.addElement(seq); + } - // If the cut affects all sequences, remove highlighted columns - if (allSequences) - { - viewport.getColumnSelection().removeElements(sg.getStartRes(), - sg.getEndRes() + 1); - } + // If the cut affects all sequences, remove highlighted columns + if (sg.getSize(false) == viewport.alignment.getHeight()) + { + viewport.getColumnSelection().removeElements(sg.getStartRes(), + sg.getEndRes() + 1); + } + + + SequenceI [] cut = new SequenceI[seqs.size()]; + for(int i=0; i 0) + { + if(trimLeft) + column = colSel.getMin(); + else + column = colSel.getMax(); - public void removeGappedColumnMenuItem_actionPerformed() - { - } + SequenceI [] seqs; + if(viewport.getSelectionGroup()!=null) + seqs = viewport.getSelectionGroup().getSequencesAsArray(true); + else + seqs = viewport.alignment.getSequencesArray(); - public void removeAllGapsMenuItem_actionPerformed() - { + + TrimRegionCommand trimRegion; + if(trimLeft) + { + trimRegion = new TrimRegionCommand("Remove Left", + TrimRegionCommand.TRIM_LEFT, + seqs, + column, + viewport.alignment, + viewport.colSel, + viewport.selectionGroup); + viewport.setStartRes(0); + } + else + { + trimRegion = new TrimRegionCommand("Remove Right", + TrimRegionCommand.TRIM_RIGHT, + seqs, + column, + viewport.alignment, + viewport.colSel, + viewport.selectionGroup); + } + + statusBar.setText("Removed "+trimRegion.getSize()+" columns."); + + + addHistoryItem(trimRegion); + + Vector groups = viewport.alignment.getGroups(); + + for (int i = 0; i < groups.size(); i++) + { + SequenceGroup sg = (SequenceGroup) groups.elementAt(i); + + if ( (trimLeft && !sg.adjustForRemoveLeft(column)) + || (!trimLeft && !sg.adjustForRemoveRight(column))) + { + viewport.alignment.deleteGroup(sg); + } + } + + viewport.firePropertyChange("alignment", null, + viewport.getAlignment().getSequences()); + } } - public void alignmentChanged() + + public void removeGappedColumnMenuItem_actionPerformed() { - viewport.alignment.padGaps(); - if(viewport.autocalculateConsensus) + int start = 0, end = viewport.alignment.getWidth()-1; + + SequenceI[] seqs; + if (viewport.getSelectionGroup() != null) { - viewport.updateConsensus(); - viewport.updateConservation(); + seqs = viewport.getSelectionGroup().getSequencesAsArray(true); + start = viewport.getSelectionGroup().getStartRes(); + end = viewport.getSelectionGroup().getEndRes(); } + else + seqs = viewport.alignment.getSequencesArray(); - resetAllColourSchemes(); - if(alignPanel.overviewPanel!=null) - alignPanel.overviewPanel.updateOverviewImage(); - viewport.alignment.adjustSequenceAnnotations(); - alignPanel.repaint(); + RemoveGapColCommand removeGapCols = + new RemoveGapColCommand("Remove Gapped Columns", + seqs, + start, end, + viewport.getGapCharacter()); + + addHistoryItem(removeGapCols); + + statusBar.setText("Removed "+removeGapCols.getSize()+" empty columns."); + + //This is to maintain viewport position on first residue + //of first sequence + SequenceI seq = viewport.alignment.getSequenceAt(0); + int startRes = seq.findPosition(viewport.startRes); + // ShiftList shifts; + // viewport.getAlignment().removeGaps(shifts=new ShiftList()); + // edit.alColumnChanges=shifts.getInverse(); + // if (viewport.hasHiddenColumns) + // viewport.getColumnSelection().compensateForEdits(shifts); + viewport.setStartRes(seq.findIndex(startRes)-1); + viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences()); + } - void resetAllColourSchemes() + public void removeAllGapsMenuItem_actionPerformed() { - ColourSchemeI cs = viewport.globalColourScheme; - if(cs!=null) + int start = 0, end = viewport.alignment.getWidth()-1; + + SequenceI[] seqs; + if (viewport.getSelectionGroup() != null) { - if (cs instanceof ClustalxColourScheme) - { - ( (ClustalxColourScheme) viewport.getGlobalColourScheme()). - resetClustalX(viewport.alignment.getSequences(), - viewport.alignment.getWidth()); - } + seqs = viewport.getSelectionGroup().getSequencesAsArray(true); + start = viewport.getSelectionGroup().getStartRes(); + end = viewport.getSelectionGroup().getEndRes(); + } + else + seqs = viewport.alignment.getSequencesArray(); - cs.setConsensus(viewport.hconsensus); - if (cs.conservationApplied()) - { - Alignment al = (Alignment) viewport.alignment; - Conservation c = new Conservation("All", - ResidueProperties.propHash, 3, - al.getSequences(), 0, - al.getWidth() - 1); - c.calculate(); - c.verdict(false, viewport.ConsPercGaps); + //This is to maintain viewport position on first residue + //of first sequence + SequenceI seq = viewport.alignment.getSequenceAt(0); + int startRes = seq.findPosition(viewport.startRes); - cs.setConservation(c); - } - } + addHistoryItem(new RemoveGapsCommand("Remove Gaps", + seqs, + start, end, + viewport.getGapCharacter())); - int s, sSize = viewport.alignment.getGroups().size(); - for(s=0; s 1) - { - mouseOver = "[" + maxRes + "] "; - maxRes = "+"; - } + static boolean UPDATING_CONSENSUS = false; + static boolean UPDATING_CONSERVATION = false; - mouseOver += (int) value + "%"; - annotations[i] = new Annotation(maxRes, mouseOver, ' ', value); + boolean updatingConsensus = false; - } + boolean updatingConservation = false; - if (consensus == null) + /** + * DOCUMENT ME! + */ + public void updateConservation(final AlignmentPanel ap) + { + if (alignment.isNucleotide() || conservation==null) + return; + + conservationThread = new ConservationThread(ap); + conservationThread.start(); + } + + /** + * DOCUMENT ME! + */ + public void updateConsensus(final AlignmentPanel ap) + { + consensusThread = new ConsensusThread(ap); + consensusThread.start(); + } + + + class ConsensusThread extends Thread + { + AlignmentPanel ap; + public ConsensusThread(AlignmentPanel ap) { - consensus = new AlignmentAnnotation("Consensus", - "PID", annotations, 0f, 100f, AlignmentAnnotation.BAR_GRAPH); - if (showConsensus) - { - alignment.addAnnotation(consensus); - } + this.ap = ap; } - else + public void run() { - consensus.annotations = annotations; - } + updatingConsensus = true; + while (UPDATING_CONSENSUS) + { + try + { + if (ap != null) + { + ap.repaint(); + } + + Thread.sleep(200); + } + catch (Exception ex) + { + ex.printStackTrace(); + } + } + + + UPDATING_CONSENSUS = true; + + try + { + int aWidth = alignment.getWidth(); + if(aWidth<0) + return; + + consensus.annotations = null; + consensus.annotations = new Annotation[aWidth]; + - if(globalColourScheme!=null) + hconsensus = new Hashtable[aWidth]; + AAFrequency.calculate(alignment.getSequencesArray(), + 0, + alignment.getWidth(), + hconsensus); + + for (int i = 0; i < aWidth; i++) + { + float value = 0; + if (ignoreGapsInConsensusCalculation) + value = ( (Float) hconsensus[i].get(AAFrequency.PID_NOGAPS)). + floatValue(); + else + value = ( (Float) hconsensus[i].get(AAFrequency.PID_GAPS)). + floatValue(); + + String maxRes = hconsensus[i].get(AAFrequency.MAXRESIDUE).toString(); + String mouseOver = hconsensus[i].get(AAFrequency.MAXRESIDUE) + " "; + + if (maxRes.length() > 1) + { + mouseOver = "[" + maxRes + "] "; + maxRes = "+"; + } + + mouseOver += ( (int) value + "%"); + consensus.annotations[i] = new Annotation(maxRes, mouseOver, ' ', value); + } + + + if (globalColourScheme != null) globalColourScheme.setConsensus(hconsensus); + } + catch (OutOfMemoryError error) + { + alignment.deleteAnnotation(consensus); + + consensus = null; + hconsensus = null; + System.out.println("Out of memory calculating consensus!!"); + System.gc(); + } + UPDATING_CONSENSUS = false; + updatingConsensus = false; + + if (ap != null) + { + ap.repaint(); + } + } } + /** * get the consensus sequence as displayed under the PID consensus annotation row. * @return consensus sequence as a new sequence object @@ -367,9 +520,8 @@ public class AlignViewport * get the consensus sequence as displayed under the PID consensus annotation row. * @return consensus sequence as a new sequence object */ - public SequenceI getConsensusSeq() { - if (consensus==null) - updateConsensus(); + public SequenceI getConsensusSeq() + { if (consensus==null) return null; StringBuffer seqs=new StringBuffer(); @@ -712,7 +864,7 @@ public class AlignViewport public void setIgnoreGapsConsensus(boolean b) { ignoreGapsInConsensusCalculation = b; - updateConsensus(); + updateConsensus(null); if (globalColourScheme!=null) { globalColourScheme.setThreshold(globalColourScheme.getThreshold(), @@ -1084,4 +1236,84 @@ public class AlignViewport sequenceColours.put(seq, col); } + public String getSequenceSetId() + { + if (sequenceSetID == null) + sequenceSetID = alignment.hashCode() + ""; + + return sequenceSetID; + } + + public void alignmentChanged(AlignmentPanel ap) + { + alignment.padGaps(); + + if (hconsensus != null && autocalculateConsensus) + { + updateConsensus(ap); + updateConservation(ap); + } + + //Reset endRes of groups if beyond alignment width + int alWidth = alignment.getWidth(); + Vector groups = alignment.getGroups(); + if(groups!=null) + { + for(int i=0; ialWidth) + sg.setEndRes(alWidth-1); + } + } + + if(selectionGroup!=null && selectionGroup.getEndRes()>alWidth) + selectionGroup.setEndRes(alWidth-1); + + resetAllColourSchemes(); + + alignment.adjustSequenceAnnotations(); + } + + void resetAllColourSchemes() + { + ColourSchemeI cs = globalColourScheme; + if(cs!=null) + { + if (cs instanceof ClustalxColourScheme) + { + ( (ClustalxColourScheme) cs). + resetClustalX(alignment.getSequences(), + alignment.getWidth()); + } + + cs.setConsensus(hconsensus); + if (cs.conservationApplied()) + { + Alignment al = (Alignment) alignment; + Conservation c = new Conservation("All", + ResidueProperties.propHash, 3, + al.getSequences(), 0, + al.getWidth() - 1); + c.calculate(); + c.verdict(false, ConsPercGaps); + + cs.setConservation(c); + } + } + + int s, sSize = alignment.getGroups().size(); + for(s=0; s0) + a1 = source.getHiddenSequences().getFullAlignment().getSequencesArray(); + else + a1 = source.getSequencesArray(); -} + SequenceI[] a2; + if (comp.getHiddenSequences().getSize() > 0) + a2 = comp.getHiddenSequences().getFullAlignment().getSequencesArray(); + else + a2 = comp.getSequencesArray(); + int i, iSize=a1.length, j, jSize=a2.length; + boolean exists = false; + for(i=0; i 0) + a2 = comp.getHiddenSequences().getFullAlignment().getSequencesArray(); + else + a2 = comp.getSequencesArray(); + } + } + + iSize=a1.length; + jSize=a2.length; + + for(j=0; j 0) + { + SequenceI [] deleted = new SequenceI[del.size()]; - for (int i = 0; i < redundancy.length; i++) - { - if (value <= redundancy[i]) - { - SequenceI seq = originalSequences[i]; - ap.av.alignment.deleteSequence(seq); - del.addElement(seq); - if (sg != null) - { - sg.deleteSequence(seq, false); - } - } - } + int width = 0; + for (int i = 0; i < del.size(); i++) + { + deleted[i] = (SequenceI)del.elementAt(i); + if(deleted[i].getLength()>width) + width = deleted[i].getLength(); + } + EditCommand cut = new EditCommand("Remove Redundancy", + EditCommand.CUT, deleted,0,width,ap.av.alignment); - // This has to be done before the restoreHistoryItem method of alignFrame will - // actually restore these sequences. - if (del.size() > 0) + for (int i = 0; i < del.size(); i++) + { + ap.av.alignment.deleteSequence( deleted[i] ); + PaintRefresher.Refresh(this, + ap.av.getSequenceSetId(), + true, + true); + if (sg != null) { - for (int i = 0, j = del.size(); i < j; i++) - { - SequenceI sq = (SequenceI) del.elementAt(i); - sq.deleteChars(0, sq.getLength()); - } + sg.deleteSequence(deleted[i], false); } + } + + historyList.push(cut); - ap.av.firePropertyChange("alignment", null, ap.av.getAlignment().getSequences()); - ap.alignFrame.updateEditMenuBar(); + ap.alignFrame.addHistoryItem(cut); + + ap.av.firePropertyChange("alignment", null, ap.av.getAlignment().getSequences()); + } } public void undoButton_actionPerformed() { - // HistoryItem hi = (HistoryItem) historyList.pop(); - // ap.alignFrame.restoreHistoryItem(hi); + CommandI command = (CommandI) historyList.pop(); + command.undoCommand(); + + if (ap.av.historyList.contains(command)) + { + ap.av.historyList.removeElement(command); + ap.alignFrame.updateEditMenuBar(); + } + + ap.repaint(); if (historyList.size() == 0) { undoButton.setEnabled(false); - } - ap.alignFrame.updateEditMenuBar(); + } } public void valueField_actionPerformed(ActionEvent e) diff --git a/src/jalview/appletgui/RotatableCanvas.java b/src/jalview/appletgui/RotatableCanvas.java index 667653f..f411a63 100755 --- a/src/jalview/appletgui/RotatableCanvas.java +++ b/src/jalview/appletgui/RotatableCanvas.java @@ -99,7 +99,7 @@ public class RotatableCanvas { this.points = points; this.npoint = npoint; - PaintRefresher.Register(this, av.alignment); + PaintRefresher.Register(this, av.getSequenceSetId()); prefsize = getPreferredSize(); orig = new float[npoint][3]; @@ -498,7 +498,7 @@ public class RotatableCanvas { av.getSelectionGroup().addOrRemove(found, true); av.getSelectionGroup().setEndRes(av.alignment.getWidth()-1); - PaintRefresher.Refresh(this, av.alignment); + PaintRefresher.Refresh(this, av.getSequenceSetId()); } else { diff --git a/src/jalview/appletgui/SeqCanvas.java b/src/jalview/appletgui/SeqCanvas.java index 0f8f930..4f32678 100755 --- a/src/jalview/appletgui/SeqCanvas.java +++ b/src/jalview/appletgui/SeqCanvas.java @@ -49,7 +49,7 @@ public class SeqCanvas this.av = av; fr = new FeatureRenderer(av); sr = new SequenceRenderer(av); - PaintRefresher.Register(this, av.alignment); + PaintRefresher.Register(this, av.getSequenceSetId()); } public AlignViewport getViewport() diff --git a/src/jalview/appletgui/SeqPanel.java b/src/jalview/appletgui/SeqPanel.java index 0596468..8e70e35 100755 --- a/src/jalview/appletgui/SeqPanel.java +++ b/src/jalview/appletgui/SeqPanel.java @@ -24,6 +24,7 @@ import java.awt.event.*; import jalview.datamodel.*; import jalview.schemes.*; +import jalview.commands.*; import java.util.Vector; @@ -60,6 +61,8 @@ public class SeqPanel boolean mouseWheelPressed = false; Point lastMousePress; + EditCommand editCommand; + public SeqPanel(AlignViewport avp, AlignmentPanel p) { this.av = avp; @@ -78,13 +81,20 @@ public class SeqPanel void endEditing() { + if (editCommand!=null && editCommand.getSize() > 0) + { + ap.alignFrame.addHistoryItem(editCommand); + av.firePropertyChange("alignment", null, + av.getAlignment().getSequences()); + } + startseq = -1; lastres = -1; - seqEditOccurred = false; editingSeqs = false; groupEditing = false; keyboardNo1 = null; keyboardNo2 = null; + editCommand = null; } void setCursorRow() @@ -250,7 +260,7 @@ public class SeqPanel startseq = seqCanvas.cursorY; lastres = seqCanvas.cursorX; editSequence(true, seqCanvas.cursorX+getKeyboardNo(keyboardNo1)); - editOccurred(); + endEditing(); } void deleteGapAtCursor(boolean group) @@ -259,7 +269,7 @@ public class SeqPanel startseq = seqCanvas.cursorY; lastres = seqCanvas.cursorX+getKeyboardNo(keyboardNo1); editSequence(false, seqCanvas.cursorX); - editOccurred(); + endEditing(); } void numberPressed(char value) @@ -380,8 +390,6 @@ public class SeqPanel return; } - editOccurred(); - endEditing(); ap.repaint(); } @@ -724,9 +732,20 @@ public class SeqPanel SequenceI seq = av.alignment.getSequenceAt(startseq); StringBuffer message = new StringBuffer(); if (groupEditing) - message.append("Edit group:"); + { + message.append("Edit group:"); + if (editCommand == null) + editCommand = new EditCommand("Edit Group"); + } else - message.append("Edit sequence: "+seq.getName()); + { + message.append("Edit sequence: " + seq.getName()); + String label = seq.getName(); + if(label.length()>10) + label = label.substring(0,10); + if(editCommand==null) + editCommand = new EditCommand("Edit "+label); + } if(insertGap) message.append(" insert "); @@ -806,7 +825,6 @@ public class SeqPanel } - if (groupEditing) { Vector vseqs = sg.getSequences(true); @@ -913,65 +931,100 @@ public class SeqPanel } } - - for (g = 0; g < groupSize; g++) - { if (insertGap) { // dragging to the right - for (int j = lastres; j < startres; j++) + if (fixedColumns && fixedRight != -1) { - if (fixedColumns && fixedRight != -1) + for (int j = lastres; j < startres; j++) { - insertChar(j, groupSeqs[g], fixedRight); + insertChar(j, groupSeqs, fixedRight); } - else - insertChar(j, groupSeqs[g]); + } + else + { + editCommand.appendEdit(EditCommand.INSERT_GAP, + groupSeqs, + startres, startres-lastres, + av.getGapCharacter(), + true); } } else { // dragging to the left - for (int j = lastres; j > startres; j--) + if (fixedColumns && fixedRight != -1) { - if (fixedColumns && fixedRight != -1) + for (int j = lastres; j > startres; j--) { - deleteChar(startres, groupSeqs[g], fixedRight); - } - else - { - deleteChar(startres, groupSeqs[g]); + deleteChar(startres, groupSeqs, fixedRight); } } + else + editCommand.appendEdit(EditCommand.DELETE_GAP, + groupSeqs, + startres, lastres - startres, + av.getGapCharacter(), + true); + } - } - } else /////Editing a single sequence/////////// + } + else /////Editing a single sequence/////////// { if (insertGap) { // dragging to the right - for (int j = lastres; j < startres; j++) + if (fixedColumns && fixedRight != -1) { - if (fixedColumns && fixedRight != -1) + for (int j = lastres; j < startres; j++) { - insertChar(j, seq, fixedRight); + insertChar(j, new SequenceI[]{seq}, fixedRight); } - else - insertChar(j, seq); + } + else + { + editCommand.appendEdit(EditCommand.INSERT_GAP, + new SequenceI[] + {seq}, + lastres, startres-lastres, + av.getGapCharacter(), + true); } } else { // dragging to the left - for (int j = lastres; j > startres; j--) + if (fixedColumns && fixedRight != -1) { - if (fixedColumns && fixedRight != -1) + for (int j = lastres; j > startres; j--) + { + if (!jalview.util.Comparison.isGap(seq.getCharAt(startres))) + { + endEditing(); + break; + } + deleteChar(startres, new SequenceI[]{seq}, fixedRight); + } + } + else + { + //could be a keyboard edit trying to delete none gaps + int max=0; + for(int m = startres; m0) { - deleteChar(startres, seq); + editCommand.appendEdit(EditCommand.DELETE_GAP, + new SequenceI[] + {seq}, + startres, max, + av.getGapCharacter(), + true); } } } @@ -982,26 +1035,18 @@ public class SeqPanel } - /** - * DOCUMENT ME! - * - * @param j DOCUMENT ME! - * @param seq DOCUMENT ME! - */ - void insertChar(int j, SequenceI seq) - { - seq.insertCharAt(j, av.getGapCharacter()); - seqEditOccurred = true; - } - void insertChar(int j, SequenceI seq, int fixedColumn) + void insertChar(int j, SequenceI [] seq, int fixedColumn) + { + int blankColumn = fixedColumn; + for(int s=0; s j, theres a boundary after the gap insertion - int blankColumn = fixedColumn; + for (blankColumn = fixedColumn; blankColumn > j; blankColumn--) { - if (jalview.util.Comparison.isGap(seq.getCharAt(blankColumn))) + if (jalview.util.Comparison.isGap(seq[s].getCharAt(blankColumn))) { //Theres a space, so break and insert the gap break; @@ -1010,81 +1055,41 @@ public class SeqPanel if (blankColumn <= j) { + blankColumn = fixedColumn; endEditing(); return; } - - if (!jalview.util.Comparison.isGap(seq.getCharAt(blankColumn))) - { - //Just Checking - System.out.println("Tried removing residue (INSERT)"+seq.getCharAt(fixedColumn)); - return; - } - - seq.deleteCharAt(blankColumn); - seq.insertCharAt(j, av.getGapCharacter()); - seqEditOccurred = true; } - void deleteChar(int j, SequenceI seq, int fixedColumn) - { - if (!jalview.util.Comparison.isGap(seq.getCharAt(j))) - { - ap.alignFrame.statusBar.setText( - "End editing: Tried removing residue " + seq.getCharAt(j)); - return; - } - seq.deleteCharAt(j); - seq.insertCharAt(fixedColumn, av.getGapCharacter()); - seqEditOccurred = true; - } + editCommand.appendEdit(EditCommand.DELETE_GAP, + seq, + blankColumn, 1, av.getGapCharacter(), true); - /** - * DOCUMENT ME! - * - * @param j DOCUMENT ME! - * @param seq DOCUMENT ME! - */ - void deleteChar(int j, SequenceI seq) - { - if (!jalview.util.Comparison.isGap(seq.getCharAt(j))) - { - ap.alignFrame.statusBar.setText( - "End editing: Tried removing residue " + seq.getCharAt(j)); - return; - } + editCommand.appendEdit(EditCommand.INSERT_GAP, + seq, + j, 1, av.getGapCharacter(), + true); - seq.deleteCharAt(j); - seqEditOccurred = true; - seqCanvas.repaint(); - } + } - /** - * DOCUMENT ME! - * - * @param i DOCUMENT ME! - */ - void editOccurred() - { - if (!seqEditOccurred) - { - ap.alignFrame.historyList.pop(); - ap.alignFrame.updateEditMenuBar(); - } + void deleteChar(int j, SequenceI [] seq, int fixedColumn) + { - endEditing(); + editCommand.appendEdit(EditCommand.DELETE_GAP, + seq, + j, 1, av.getGapCharacter(), true); - av.firePropertyChange("alignment", null,av.getAlignment().getSequences()); + editCommand.appendEdit(EditCommand.INSERT_GAP, + seq, + fixedColumn, 1, av.getGapCharacter(), true); + } - } ////////////////////////////////////////// /////Everything below this is for defining the boundary of the rubberband ////////////////////////////////////////// public void doMousePressedDefineMode(MouseEvent evt) { - - if (scrollThread != null) { scrollThread.running = false; @@ -1226,6 +1231,13 @@ public class SeqPanel stretchGroup.getWidth()); } + if (stretchGroup.cs instanceof Blosum62ColourScheme + || stretchGroup.cs instanceof PIDColourScheme + || stretchGroup.cs.conservationApplied() + || stretchGroup.cs.getThreshold() > 0) + stretchGroup.recalcConservation(); + + if (stretchGroup.cs.conservationApplied()) { SliderPanel.setConservationSlider(ap, stretchGroup.cs, @@ -1241,7 +1253,7 @@ public class SeqPanel changeEndRes = false; changeStartRes = false; stretchGroup = null; - PaintRefresher.Refresh(av.alignment); + PaintRefresher.Refresh(ap, av.getSequenceSetId()); ap.repaint(); } diff --git a/src/jalview/appletgui/SequenceRenderer.java b/src/jalview/appletgui/SequenceRenderer.java index 510b32f..480a506 100755 --- a/src/jalview/appletgui/SequenceRenderer.java +++ b/src/jalview/appletgui/SequenceRenderer.java @@ -99,6 +99,9 @@ public class SequenceRenderer public void drawSequence(SequenceI seq, SequenceGroup[] sg, int start, int end, int y1) { + if(seq==null) + return; + allGroups = sg; drawBoxes(seq, start, end, y1); diff --git a/src/jalview/appletgui/TreeCanvas.java b/src/jalview/appletgui/TreeCanvas.java index 1c1e7cf..8b68489 100755 --- a/src/jalview/appletgui/TreeCanvas.java +++ b/src/jalview/appletgui/TreeCanvas.java @@ -65,7 +65,7 @@ public class TreeCanvas addMouseMotionListener(this); setLayout(null); - PaintRefresher.Register(this, av.alignment); + PaintRefresher.Register(this, av.getSequenceSetId()); } public void treeSelectionChanged(SequenceI sequence) @@ -472,7 +472,7 @@ public class TreeCanvas } } - PaintRefresher.Refresh(this, av.alignment); + PaintRefresher.Refresh(this, av.getSequenceSetId()); repaint(); } } @@ -514,7 +514,7 @@ public class TreeCanvas if (ob instanceof SequenceI) { treeSelectionChanged( (Sequence) ob); - PaintRefresher.Refresh(this, av.alignment); + PaintRefresher.Refresh(this, av.getSequenceSetId()); repaint(); return; } @@ -533,14 +533,14 @@ public class TreeCanvas av.setSelectionGroup(null); av.alignment.deleteAllGroups(); - av.sequenceColours.clear(); + av.sequenceColours=null; colourGroups(); } } - PaintRefresher.Refresh(this, av.alignment); + PaintRefresher.Refresh(this, av.getSequenceSetId()); repaint(); } -- 1.7.10.2