From: Patrick Plitzner Date: Wed, 13 Apr 2016 11:29:46 +0000 (+0200) Subject: Merge branch 'LibrAlign' into develop X-Git-Tag: 4.0.0^2~30 X-Git-Url: https://dev.e-taxonomy.eu/gitweb/taxeditor.git/commitdiff_plain/d4e581eb9d7a1717edd1bb8d24f3c3374645bf69?hp=0aeb6effa85da754cd4efb48f0953b0bf2662243 Merge branch 'LibrAlign' into develop --- diff --git a/.gitattributes b/.gitattributes index c7b12732e..877a615a0 100644 --- a/.gitattributes +++ b/.gitattributes @@ -963,6 +963,10 @@ eu.etaxonomy.taxeditor.help/src/eu/etaxonomy/taxeditor/help/Activator.java -text eu.etaxonomy.taxeditor.help/toc.xml -text eu.etaxonomy.taxeditor.help/tocgettingstarted.xml -text eu.etaxonomy.taxeditor.help/tocnameparser.xml -text +eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/editor/AlignmentEditorActionUpdater.java -text +eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/AbstractFocusedAlignmentAreaHandler.java -text +eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/AlignmentEditorCutHandler.java -text +eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/AlignmentEditorPasteHandler.java -text eu.etaxonomy.taxeditor.navigation/.classpath -text eu.etaxonomy.taxeditor.navigation/.project -text eu.etaxonomy.taxeditor.navigation/META-INF/MANIFEST.MF -text @@ -1984,4 +1988,4 @@ src/site/site.xml -text eu.etaxonomy.taxeditor.cdmlib/.classpath merge=ours eu.etaxonomy.taxeditor.cdmlib/build.properties merge=ours eu.etaxonomy.taxeditor/eu.etaxonomy.taxeditor.product merge=ours -eu.etaxonomy.taxeditor/eu.etaxonomy.taxeditor.product.with.jre merge=ours \ No newline at end of file +eu.etaxonomy.taxeditor/eu.etaxonomy.taxeditor.product.with.jre merge=ours diff --git a/eu.etaxonomy.taxeditor.molecular/plugin.xml b/eu.etaxonomy.taxeditor.molecular/plugin.xml index 27b08389f..78b734fd1 100644 --- a/eu.etaxonomy.taxeditor.molecular/plugin.xml +++ b/eu.etaxonomy.taxeditor.molecular/plugin.xml @@ -264,6 +264,42 @@ class="eu.etaxonomy.taxeditor.molecular.handler.ChangePherogramQualityOutputType" commandId="eu.etaxonomy.taxeditor.molecular.pherogramComponent.changeQualityOutput"> + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/editor/AlignmentEditor.java b/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/editor/AlignmentEditor.java index 4934d9a37..57608d5d8 100644 --- a/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/editor/AlignmentEditor.java +++ b/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/editor/AlignmentEditor.java @@ -10,6 +10,7 @@ package eu.etaxonomy.taxeditor.molecular.editor; +import info.bioinfweb.commons.swt.SWTUtils; import info.bioinfweb.libralign.alignmentarea.AlignmentArea; import info.bioinfweb.libralign.alignmentarea.selection.SelectionModel; import info.bioinfweb.libralign.alignmentarea.tokenpainter.NucleotideTokenPainter; @@ -52,16 +53,16 @@ import java.util.TreeMap; import org.biojava.bio.chromatogram.ChromatogramFactory; import org.biojava.bio.chromatogram.UnsupportedChromatogramFormatException; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.jface.action.Action; import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.commands.ICommandService; import org.eclipse.ui.part.EditorPart; @@ -128,13 +129,16 @@ public class AlignmentEditor extends EditorPart { setDirty(); } }; + private final AlignmentEditorActionUpdater ACTION_UPDATER = new AlignmentEditorActionUpdater(); + public final Clipboard CLIPBOARD = new Clipboard(Display.getCurrent()); //TODO Move to global EDITor class. + private MultipleAlignmentsContainer alignmentsContainer = null; private final Map cdmMap = new TreeMap(); //TODO Move this to ContigSequenceDataProvider private boolean dirty = false; - - public AlignmentEditor() { + public AlignmentEditor() + { super(); conversationHolder = CdmStore.createConversation(); //conversationHolder = null; @@ -151,34 +155,34 @@ public class AlignmentEditor extends EditorPart { private void registerEditSettingListener(MultipleAlignmentsContainer container) { - container.getEditSettings().addListener(new EditSettingsListener() { - @Override - public void workingModeChanged(EditSettingsChangeEvent e) {} // Currently nothing to do + container.getEditSettings().addListener(new EditSettingsListener() { + @Override + public void workingModeChanged(EditSettingsChangeEvent e) {} // Currently nothing to do - @Override - public void insertLeftInDataAreaChanged(EditSettingsChangeEvent e) { - updateStatusBar(); - refreshToolbarElement(ToggleLeftRightInsertionHandler.COMMAND_ID); - } + @Override + public void insertLeftInDataAreaChanged(EditSettingsChangeEvent e) { + updateStatusBar(); + refreshToolbarElement(ToggleLeftRightInsertionHandler.COMMAND_ID); + } - @Override - public void insertChanged(EditSettingsChangeEvent e) { - updateStatusBar(); - refreshToolbarElement(ToggleInsertOverwriteHandler.COMMAND_ID); - } - }); + @Override + public void insertChanged(EditSettingsChangeEvent e) { + updateStatusBar(); + refreshToolbarElement(ToggleInsertOverwriteHandler.COMMAND_ID); + } + }); } - private AlignmentArea createIndexArea(MultipleAlignmentsContainer container, AlignmentArea labeledArea) { + private AlignmentArea createIndexArea(MultipleAlignmentsContainer container, AlignmentArea labeledArea) { AlignmentArea result = new AlignmentArea(container); result.setAllowVerticalScrolling(false); result.getDataAreas().getTopAreas().add(new SequenceIndexArea(result.getContentArea(), labeledArea)); return result; - } + } - private AlignmentArea createEditableAlignmentArea(MultipleAlignmentsContainer container, boolean allowVerticalScrolling) { + private AlignmentArea createEditableAlignmentArea(MultipleAlignmentsContainer container, boolean allowVerticalScrolling) { AlignmentArea result = new AlignmentArea(container); result.setAllowVerticalScrolling(allowVerticalScrolling); @@ -195,12 +199,12 @@ public class AlignmentEditor extends EditorPart { private AlignmentArea createConsensusHintArea(MultipleAlignmentsContainer container, AlignmentArea labeledArea) { - AlignmentArea result = new AlignmentArea(container); - result.setAllowVerticalScrolling(false); - result.getDataAreas().getBottomAreas().add( - new ConsensusSequenceArea(result.getContentArea(), labeledArea)); - return result; - } + AlignmentArea result = new AlignmentArea(container); + result.setAllowVerticalScrolling(false); + result.getDataAreas().getBottomAreas().add( + new ConsensusSequenceArea(result.getContentArea(), labeledArea)); + return result; + } private MultipleAlignmentsContainer getAlignmentsContainer() { @@ -209,9 +213,12 @@ public class AlignmentEditor extends EditorPart { AlignmentAreaList list = alignmentsContainer.getAlignmentAreas(); AlignmentArea readsArea = createEditableAlignmentArea(alignmentsContainer, true); + readsArea.getSelection().addSelectionListener(ACTION_UPDATER); list.add(createIndexArea(alignmentsContainer, readsArea)); list.add(readsArea); // Make sure READS_AREA_INDEX is correct. - list.add(createEditableAlignmentArea(alignmentsContainer, false)); // Make sure COMSENSUS_AREA_INDEX is correct. + AlignmentArea editableConsensusArea = createEditableAlignmentArea(alignmentsContainer, false); + editableConsensusArea.getSelection().addSelectionListener(ACTION_UPDATER); + list.add(editableConsensusArea); // Make sure COMSENSUS_AREA_INDEX is correct. list.add(createConsensusHintArea(alignmentsContainer, readsArea)); registerEditSettingListener(alignmentsContainer); @@ -225,11 +232,49 @@ public class AlignmentEditor extends EditorPart { } - private AlignmentArea getEditableConsensusArea() { + public AlignmentArea getEditableConsensusArea() { return getAlignmentsContainer().getAlignmentAreas().get(EDITABLE_CONSENSUS_AREA_INDEX); } + /** + * Checks whether {@link #getReadsArea()} or {@link #getEditableConsensusArea()} currently + * have the user focus and returns the according component. + * + * @return either the reads or the consensus alignment area or {@code null} if none of these + * components is currently focused + */ + public AlignmentArea getFocusedArea() { + AlignmentArea result = getReadsArea(); + if (hasFocus(result)) { + return result; + } + else { + result = getEditableConsensusArea(); + if (hasFocus(result)) { + return result; + } + else { + return null; + } + } + } + + + /** + * Checks whether the specified alignment area or one of its subcomponents currently has the + * focus. + * + * @param area the alignment area to be checked (Can only be {@link #getReadsArea()} or + * {@link #getEditableConsensusArea()}.) + * @return {@code true} if the specified component is focused and is either equal to + * {@link #getReadsArea()} or {@link #getEditableConsensusArea()}or {@code false} otherwise + */ + private boolean hasFocus(AlignmentArea area) { + return SWTUtils.childHasFocus((Composite)area.getToolkitComponent()); + } + + public boolean hasPherogram(int sequenceID) { return getReadsArea().getDataAreas().getSequenceAreas(sequenceID).size() > PHEROGRAM_AREA_INDEX; } @@ -312,12 +357,11 @@ public class AlignmentEditor extends EditorPart { } - /* (non-Javadoc) - * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) - */ @Override public void createPartControl(Composite parent) { SWTComponentFactory.getInstance().getSWTComponent(getAlignmentsContainer(), parent, SWT.NONE); + Display.getCurrent().addFilter(SWT.FocusIn, ACTION_UPDATER); + Display.getCurrent().addFilter(SWT.FocusOut, ACTION_UPDATER); updateStatusBar(); if (getEditorInput() instanceof AlignmentEditorInput) { @@ -340,7 +384,17 @@ public class AlignmentEditor extends EditorPart { } - private void updateStatusBar() { + @Override + public void dispose() { + Display.getCurrent().removeFilter(SWT.FocusIn, ACTION_UPDATER); + Display.getCurrent().removeFilter(SWT.FocusOut, ACTION_UPDATER); + CLIPBOARD.dispose(); + ((AlignmentEditorInput)getEditorInput()).dispose(); + super.dispose(); + } + + + private void updateStatusBar() { IActionBars bars = getEditorSite().getActionBars(); bars.getStatusLineManager().setMessage("Edit mode: " + (getReadsArea().getEditSettings().isInsert() ? "Insert" : "Overwrite") + " " + @@ -360,9 +414,6 @@ public class AlignmentEditor extends EditorPart { } - /* (non-Javadoc) - * @see org.eclipse.ui.part.EditorPart#doSave(org.eclipse.core.runtime.IProgressMonitor) - */ @Override public void doSave(IProgressMonitor monitor) { if (getEditorInput() instanceof AlignmentEditorInput) { @@ -432,40 +483,17 @@ public class AlignmentEditor extends EditorPart { } - /* (non-Javadoc) - * @see org.eclipse.ui.part.EditorPart#doSaveAs() - */ @Override public void doSaveAs() {} - /* (non-Javadoc) - * @see org.eclipse.ui.part.EditorPart#init(org.eclipse.ui.IEditorSite, org.eclipse.ui.IEditorInput) - */ @Override public void init(IEditorSite site, IEditorInput input) throws PartInitException { setSite(site); setInput(input); - System.out.println("AlignmentEditor.init(): " + ActionFactory.COPY.getId()); - site.getActionBars().setGlobalActionHandler(ActionFactory.COPY.getId(), new Action(ActionFactory.COPY.getId()) { - @Override - public boolean isEnabled() { - System.out.println("isEnabled()"); - return true; - } - - @Override - public void run() { - System.out.println("run"); - super.run(); - } - }); } - /* (non-Javadoc) - * @see org.eclipse.ui.part.EditorPart#isDirty() - */ @Override public boolean isDirty() { return dirty; @@ -478,9 +506,6 @@ public class AlignmentEditor extends EditorPart { } - /* (non-Javadoc) - * @see org.eclipse.ui.part.EditorPart#isSaveAsAllowed() - */ @Override public boolean isSaveAsAllowed() { return false; // "Save as" not allowed. @@ -489,17 +514,12 @@ public class AlignmentEditor extends EditorPart { @Override public void setFocus() { - if(conversationHolder!=null){ + if(conversationHolder != null){ conversationHolder.bind(); } ((AlignmentEditorInput)getEditorInput()).bind(); } - @Override - public void dispose() { - ((AlignmentEditorInput)getEditorInput()).dispose(); - } - public boolean isInsertMode() { return getAlignmentsContainer().getEditSettings().isInsert(); } diff --git a/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/editor/AlignmentEditorActionUpdater.java b/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/editor/AlignmentEditorActionUpdater.java new file mode 100644 index 000000000..7993a08c4 --- /dev/null +++ b/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/editor/AlignmentEditorActionUpdater.java @@ -0,0 +1,55 @@ +package eu.etaxonomy.taxeditor.molecular.editor; + + +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.actions.ActionFactory; +import org.eclipse.ui.commands.ICommandService; + +import eu.etaxonomy.taxeditor.molecular.handler.AbstractAlignmentEditorHandler; +import info.bioinfweb.libralign.alignmentarea.selection.SelectionChangeEvent; +import info.bioinfweb.libralign.alignmentarea.selection.SelectionListener; + + + +/** + * Listener used to update copy/paste events associated with {@link AlignmentEditor}. + * + * @author Ben Stöver + * @date 25.08.2015 + */ +public class AlignmentEditorActionUpdater implements SelectionListener, Listener { + private static final String[] IDS = {ActionFactory.COPY.getCommandId(), ActionFactory.CUT.getCommandId(), + ActionFactory.PASTE.getCommandId()}; + + + private void updateEvents() { + ICommandService service = (ICommandService)PlatformUI.getWorkbench().getService(ICommandService.class); + for (int i = 0; i < IDS.length; i++) { + service.refreshElements(IDS[i], null); + } + } + + + @Override + public void handleEvent(Event event) { + AlignmentEditor editor = AbstractAlignmentEditorHandler.getActiveAlignmentEditor(); + if (editor != null) { + updateEvents(); + } + } + + + @Override + public void selectionChanged(SelectionChangeEvent e) { + AlignmentEditor editor = AbstractAlignmentEditorHandler.getActiveAlignmentEditor(); + if (editor != null) { + if ((e.getSource() == editor.getReadsArea().getSelection()) || + (e.getSource() == editor.getEditableConsensusArea().getSelection())) { + + updateEvents(); + } + } + } +} diff --git a/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/AbstractAlignmentEditorHandler.java b/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/AbstractAlignmentEditorHandler.java index 0c8a6edb1..1d44449b9 100644 --- a/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/AbstractAlignmentEditorHandler.java +++ b/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/AbstractAlignmentEditorHandler.java @@ -29,15 +29,26 @@ import eu.etaxonomy.taxeditor.molecular.editor.AlignmentEditor; * @date 19.06.2015 */ public abstract class AbstractAlignmentEditorHandler extends AbstractHandler { - @Override - public Object execute(ExecutionEvent event) throws ExecutionException { + public static AlignmentEditor getActiveAlignmentEditor() { IEditorPart activeEditor = AbstractUtility.getActiveEditor(); if (activeEditor instanceof AlignmentEditor) { - doExecute(event, (AlignmentEditor)activeEditor); + return (AlignmentEditor)activeEditor; + } + else { + return null; + } + } + + + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + AlignmentEditor editor = getActiveAlignmentEditor(); + if (editor != null) { + doExecute(event, editor); } return null; } - public abstract void doExecute(ExecutionEvent event, AlignmentEditor editor) throws ExecutionException; + protected abstract void doExecute(ExecutionEvent event, AlignmentEditor editor) throws ExecutionException; } diff --git a/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/AbstractFocusedAlignmentAreaHandler.java b/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/AbstractFocusedAlignmentAreaHandler.java new file mode 100644 index 000000000..1fc418aae --- /dev/null +++ b/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/AbstractFocusedAlignmentAreaHandler.java @@ -0,0 +1,24 @@ +package eu.etaxonomy.taxeditor.molecular.handler; + + +import info.bioinfweb.libralign.alignmentarea.AlignmentArea; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; + +import eu.etaxonomy.taxeditor.molecular.editor.AlignmentEditor; + + + +public abstract class AbstractFocusedAlignmentAreaHandler extends AbstractAlignmentEditorHandler { + @Override + protected void doExecute(ExecutionEvent event, AlignmentEditor editor) throws ExecutionException { + AlignmentArea focusedArea = editor.getFocusedArea(); + if (focusedArea != null) { + doExecute2(event, editor, focusedArea); + } + } + + + protected abstract void doExecute2(ExecutionEvent event, AlignmentEditor editor, AlignmentArea focusedArea); +} diff --git a/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/AlignmentEditorCopyHandler.java b/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/AlignmentEditorCopyHandler.java new file mode 100644 index 000000000..381cf3536 --- /dev/null +++ b/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/AlignmentEditorCopyHandler.java @@ -0,0 +1,62 @@ +package eu.etaxonomy.taxeditor.molecular.handler; + + +import java.util.Map; + +import info.bioinfweb.libralign.alignmentarea.AlignmentArea; +import info.bioinfweb.libralign.alignmentarea.selection.SelectionModel; +import info.bioinfweb.libralign.model.AlignmentModelUtils; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.ui.commands.IElementUpdater; +import org.eclipse.ui.menus.UIElement; + +import eu.etaxonomy.taxeditor.molecular.editor.AlignmentEditor; + + + +/** + * Handler that copies the currently selected nucleotides from an alignment editor to the clipboard. + *

+ * The copied contents either come from the single reads or the consensus sequence alignment area, + * depending on which component currently has the focus. If none of these components has the focus, + * nothing will be copied, even if nucleotides are currently selected. + *

+ * If the selection contains parts of multiple sequence, these are separated by the line separator + * of the current operating system. + * + * @author Ben Stöver + * @date 25.08.2015 + */ +public class AlignmentEditorCopyHandler extends AbstractFocusedAlignmentAreaHandler implements IElementUpdater { + @Override + @SuppressWarnings("unchecked") + protected void doExecute2(ExecutionEvent event, AlignmentEditor editor, AlignmentArea focusedArea) { + SelectionModel selection = focusedArea.getSelection(); + if (!selection.isEmpty()) { + editor.CLIPBOARD.setContents(new Object[]{AlignmentModelUtils.selectionAsString(focusedArea, false)}, + new Transfer[]{TextTransfer.getInstance()}); + } + } + + + @Override + public boolean isEnabled() { + AlignmentEditor editor = getActiveAlignmentEditor(); + if (editor != null) { + AlignmentArea focusedArea = editor.getFocusedArea(); + if (focusedArea != null) { + return !focusedArea.getSelection().isEmpty(); + } + } + return false; + } + + + @Override + public void updateElement(UIElement element, @SuppressWarnings("rawtypes") Map parameters) { + setBaseEnabled(isEnabled()); + } +} diff --git a/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/AlignmentEditorCutHandler.java b/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/AlignmentEditorCutHandler.java new file mode 100644 index 000000000..2236686fb --- /dev/null +++ b/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/AlignmentEditorCutHandler.java @@ -0,0 +1,31 @@ +package eu.etaxonomy.taxeditor.molecular.handler; + + +import info.bioinfweb.libralign.alignmentarea.AlignmentArea; + +import org.eclipse.core.commands.ExecutionEvent; + +import eu.etaxonomy.taxeditor.molecular.editor.AlignmentEditor; + + + +/** + * Handler that cuts the currently selected nucleotides from an alignment editor to the clipboard. + *

+ * The cut contents either come from the single reads or the consensus sequence alignment area, + * depending on which component currently has the focus. If none of these components has the focus, + * nothing will be cut, even if nucleotides are currently selected. + *

+ * If the selection contains parts of multiple sequence, these are separated by the line separator + * of the current operating system. + * + * @author Ben Stöver + * @date 25.08.2015 + */ +public class AlignmentEditorCutHandler extends AlignmentEditorCopyHandler { + @Override + protected void doExecute2(ExecutionEvent event, AlignmentEditor editor, AlignmentArea focusedArea) { + super.doExecute2(event, editor, focusedArea); // Copy selected contents. + focusedArea.getActionProvider().deleteSelection(); + } +} diff --git a/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/AlignmentEditorPasteHandler.java b/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/AlignmentEditorPasteHandler.java new file mode 100644 index 000000000..ca037657c --- /dev/null +++ b/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/AlignmentEditorPasteHandler.java @@ -0,0 +1,129 @@ +package eu.etaxonomy.taxeditor.molecular.handler; + + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Scanner; + +import info.bioinfweb.libralign.alignmentarea.AlignmentArea; +import info.bioinfweb.libralign.alignmentarea.order.SequenceOrder; +import info.bioinfweb.libralign.alignmentarea.selection.SelectionModel; +import info.bioinfweb.libralign.model.AlignmentModel; +import info.bioinfweb.libralign.model.AlignmentModelUtils; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.ui.commands.IElementUpdater; +import org.eclipse.ui.handlers.HandlerUtil; +import org.eclipse.ui.menus.UIElement; + +import eu.etaxonomy.taxeditor.molecular.editor.AlignmentEditor; + + + +/** + * Handler that pastes the current contents of the clipboard into an active instance of {@link AlignmentEditor}. + * + * @author Ben Stöver + * @date 26.08.2015 + */ +public class AlignmentEditorPasteHandler extends AbstractFocusedAlignmentAreaHandler implements IElementUpdater { + private void pasteString(AlignmentArea area, int sequenceID, String content) { + area.getActionProvider().deleteSelection(); // Overwrite selected tokens. + area.getActionProvider().elongateSequence(sequenceID, area.getSelection().getCursorColumn()); + + AlignmentModel alignmentModel = (AlignmentModel)area.getAlignmentModel(); + alignmentModel.insertTokensAt(sequenceID, area.getSelection().getCursorColumn(), + AlignmentModelUtils.charSequenceToTokenList(content, alignmentModel.getTokenSet(), + true, alignmentModel.getTokenSet().getGapToken())); + } + + + @Override + protected void doExecute2(ExecutionEvent event, AlignmentEditor editor, AlignmentArea focusedArea) { + SelectionModel selection = focusedArea.getSelection(); + String clipboardText = (String)editor.CLIPBOARD.getContents(TextTransfer.getInstance()); + if (clipboardText != null) { + List lines = new ArrayList(); + Scanner scanner = new Scanner(clipboardText); + try { + while (scanner.hasNext()) { + lines.add(scanner.nextLine()); + } + if (lines.get(lines.size() - 1).equals("")) { + lines.remove(lines.size() - 1); + } + } + finally { + scanner.close(); + } + + if (!lines.isEmpty()) { //TODO Can lines be empty? (Can an empty string "" be copied to the clipboard?) + if (selection.getCursorHeight() == 1) { // If the consensus sequence is focused, this is the only possible case. + int sequenceID = focusedArea.getSequenceOrder().idByIndex(selection.getCursorRow()); + if (lines.size() == 1) { + pasteString(focusedArea, sequenceID, lines.get(0)); + } + else { + MessageDialog dialog = new MessageDialog(HandlerUtil.getActiveWorkbenchWindow(event).getShell(), //TODO Can the window be null? + "Pasting multiple lines", null, + "The text to be pasted contains mutlitple lines (" + lines.size() + + ") although the current cursor height is one. What do you want to do?", + MessageDialog.QUESTION, + new String[]{"Ingnore line breaks and paste as one sequence", + "Only paste the first line from the clipboard", "Cancel"}, + 0); + //TODO Does the dialog have to be disposed in some way? + + switch (dialog.open()) { + case 0: // Paste all lines in one sequence. + pasteString(focusedArea, sequenceID, clipboardText); + break; + case 1: // Paste only first line. + pasteString(focusedArea, sequenceID, lines.get(0)); + break; + } + } + } + else { + if (selection.getCursorHeight() == lines.size()) { + SequenceOrder order = focusedArea.getSequenceOrder(); + for (int i = 0; i < selection.getCursorHeight(); i++) { + pasteString(focusedArea, order.idByIndex(selection.getCursorRow() + i), lines.get(i)); // Multiple calls of deleteSelection() in here are unnecessary, but should have no effect. + } + } + else { + MessageDialog.openError(HandlerUtil.getActiveWorkbenchWindow(event).getShell(), //TODO Can the window be null? + "Unable to paste multiple lines", + "The current cursor height (" + selection.getCursorHeight() + + ") does not match the number of lines to be pasted (" + lines.size() + ")." + + System.getProperty("line.separator") + System.getProperty("line.separator") + + "You can either change the cursor height accordingly or set the cursor height to one " + + "allowing you to paste all lines from the clipboad into one sequence."); + } + } + } + } + } + + + @Override + public boolean isEnabled() { + AlignmentEditor editor = getActiveAlignmentEditor(); + if (editor != null) { + AlignmentArea focusedArea = editor.getFocusedArea(); + return (focusedArea != null); + } + else { + return false; + } + } + + + @Override + public void updateElement(UIElement element, @SuppressWarnings("rawtypes") Map parameters) { + setBaseEnabled(isEnabled()); + } +} diff --git a/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/EditSequenceHandler.java b/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/EditSequenceHandler.java index 69597f13d..5c26e4a22 100644 --- a/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/EditSequenceHandler.java +++ b/eu.etaxonomy.taxeditor.molecular/src/main/java/eu/etaxonomy/taxeditor/molecular/handler/EditSequenceHandler.java @@ -24,9 +24,9 @@ import eu.etaxonomy.taxeditor.molecular.editor.AlignmentEditorInput; * @author pplitzner */ public class EditSequenceHandler extends AbstractHandler { + private org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(EditSequenceHandler.class); - org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(EditSequenceHandler.class); - + @Override public Object execute(ExecutionEvent event) throws ExecutionException { ISelection currentSelection = HandlerUtil.getCurrentSelection(event);