| /******************************************************************************* |
| * Copyright (c) 2001, 2004 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Jens Lukowski/Innoopract - initial renaming/restructuring |
| * |
| *******************************************************************************/ |
| package org.eclipse.wst.sse.ui.internal; |
| |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.IRegion; |
| import org.eclipse.jface.text.ITextViewer; |
| import org.eclipse.swt.custom.ST; |
| import org.eclipse.swt.custom.StyledText; |
| import org.eclipse.swt.dnd.DND; |
| import org.eclipse.swt.dnd.DropTargetAdapter; |
| import org.eclipse.swt.dnd.DropTargetEvent; |
| import org.eclipse.swt.dnd.FileTransfer; |
| import org.eclipse.swt.dnd.Transfer; |
| import org.eclipse.swt.dnd.TransferData; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.GC; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.widgets.Caret; |
| import org.eclipse.ui.IEditorPart; |
| import org.eclipse.wst.sse.ui.internal.TransferBuilder.TransferProxyForDelayLoading; |
| |
| /** |
| * ExtendedEditorDropTargetAdapter |
| */ |
| public class ExtendedEditorDropTargetAdapter extends DropTargetAdapter { |
| |
| private Point caret = null; |
| private String[] editorIds; |
| private int orgOffset = 0; |
| private IEditorPart targetEditor = null; |
| private ITextViewer textViewer = null; |
| |
| private Transfer[] transfers = null; |
| |
| private boolean useProxy; |
| |
| /** |
| * @deprecated use ExtendedEditorDropTargetAdapter(boolean useProxy) for |
| * the performance |
| */ |
| public ExtendedEditorDropTargetAdapter() { |
| this(false); |
| } |
| |
| public ExtendedEditorDropTargetAdapter(boolean useProxy) { |
| super(); |
| this.useProxy = useProxy; |
| } |
| |
| protected boolean doDrop(Transfer transfer, DropTargetEvent event) { |
| TransferBuilder tb = new TransferBuilder(useProxy); |
| |
| IDropAction[] as = null; |
| if (editorIds != null && editorIds.length > 0) |
| as = tb.getDropActions(editorIds, transfer); |
| else |
| as = tb.getDropActions(getTargetEditor().getClass().getName(), transfer); |
| |
| for (int i = 0; i < as.length; ++i) { |
| IDropAction da = as[i]; |
| Transfer actualTransfer; |
| if (transfer instanceof TransferProxyForDelayLoading) { |
| actualTransfer = ((TransferProxyForDelayLoading) transfer).getTransferClass(); |
| } |
| else { |
| actualTransfer = transfer; |
| } |
| if (actualTransfer instanceof FileTransfer) { |
| if (event.data == null) { |
| Logger.log(Logger.ERROR, "No data in DropTargetEvent from " + event.widget); //$NON-NLS-1$ |
| return false; |
| } |
| String[] strs = (String[]) event.data; |
| boolean[] bs = new boolean[strs.length]; |
| int c = 0; |
| for (int j = 0; j < strs.length; ++j) { |
| bs[j] = false; |
| if (da.isSupportedData(strs[j])) { |
| event.data = new String[]{strs[j]}; |
| if (!da.run(event, targetEditor)) { |
| bs[j] = true; |
| c++; |
| } |
| } else { |
| bs[j] = true; |
| c++; |
| } |
| } |
| if (c == 0) { |
| return true; |
| } |
| |
| int k = 0; |
| String[] rests = new String[c]; |
| for (int j = 0; j < strs.length; ++j) { |
| if (bs[j]) |
| rests[k++] = strs[j]; |
| } |
| event.data = rests; |
| } else if (da.isSupportedData(event.data)) { |
| if (da.run(event, targetEditor)) { |
| return true; |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| /** |
| */ |
| public void dragEnter(DropTargetEvent event) { |
| caret = null; |
| TransferData data = null; |
| Transfer[] ts = getTransfers(); |
| for (int i = 0; i < ts.length; i++) { |
| for (int j = 0; j < event.dataTypes.length; j++) { |
| if (ts[i].isSupportedType(event.dataTypes[j])) { |
| data = event.dataTypes[j]; |
| break; |
| } |
| } |
| if (data != null) { |
| event.currentDataType = data; |
| break; |
| } |
| } |
| |
| if (textViewer != null) { |
| orgOffset = textViewer.getTextWidget().getCaretOffset(); |
| } |
| } |
| |
| public void dragLeave(DropTargetEvent event) { |
| if (textViewer != null) { |
| StyledText st = textViewer.getTextWidget(); |
| st.setCaretOffset(orgOffset); |
| st.redraw(); |
| st.update(); |
| } |
| } |
| |
| /** |
| */ |
| public void dragOver(DropTargetEvent event) { |
| event.operations &= ~DND.DROP_MOVE; |
| event.detail = DND.DROP_COPY; |
| |
| if (textViewer != null) { |
| Point pt = toControl(new Point(event.x, event.y)); |
| StyledText st = textViewer.getTextWidget(); |
| |
| // auto scroll |
| Rectangle ca = st.getClientArea(); |
| int margin = st.getLineHeight(); |
| |
| if (pt.y < margin) { // up |
| st.invokeAction(ST.LINE_UP); |
| } else if (pt.y > ca.height - margin) { // down |
| st.invokeAction(ST.LINE_DOWN); |
| } |
| |
| // draw insertion point |
| int offset = getDropOffset(st, pt); |
| if (offset != st.getCaretOffset()) { |
| st.setCaretOffset(offset); |
| st.setSelection(offset); |
| } |
| |
| Point newCaret = st.getLocationAtOffset(offset); |
| if (newCaret.equals(caret)) |
| return; |
| |
| Caret ct = st.getCaret(); |
| Point size = ct.getSize(); |
| |
| GC gc = new GC(st); |
| gc.setLineWidth(size.x); |
| |
| // erase old caret |
| if (caret != null) { |
| Color originalForeground = gc.getForeground(); |
| gc.setForeground(st.getBackground()); |
| gc.drawRectangle(caret.x, caret.y, size.x, size.y); |
| gc.setForeground(originalForeground); |
| } |
| |
| st.redraw(); |
| st.update(); |
| |
| // draw new caret |
| caret = newCaret; |
| if (ct.getImage() != null) |
| gc.drawImage(ct.getImage(), caret.x, caret.y); |
| else { |
| gc.drawLine(caret.x, caret.y, caret.x, caret.y + size.y); |
| } |
| |
| gc.dispose(); |
| } |
| } |
| |
| /** |
| */ |
| public void drop(DropTargetEvent event) { |
| if (event.operations == DND.DROP_NONE) |
| return; |
| |
| if (textViewer != null) { |
| Point pt = toControl(new Point(event.x, event.y)); |
| StyledText st = textViewer.getTextWidget(); |
| |
| int offset = getDropOffset(st, pt); |
| if (offset != st.getCaretOffset()) { |
| st.setCaretOffset(offset); |
| } |
| |
| // ISelectionProvider sp = textViewer.getSelectionProvider(); |
| // ISelection sel = new TextSelection(offset, 0); |
| // sp.setSelection(sel); |
| textViewer.setSelectedRange(offset, 0); |
| } |
| |
| Transfer[] ts = getTransfers(); |
| for (int i = 0; i < ts.length; i++) { |
| if (ts[i].isSupportedType(event.currentDataType)) { |
| if (doDrop(ts[i], event)) { |
| break; |
| } |
| } |
| } |
| } |
| |
| protected int getDropOffset(DropTargetEvent event) { |
| Point pt = getTextViewer().getTextWidget().toControl(new Point(event.x, event.y)); |
| StyledText st = textViewer.getTextWidget(); |
| return getDropOffset(st, pt); |
| } |
| |
| private int getDropOffset(StyledText st, Point pt) { |
| int offset = st.getCaretOffset(); |
| try { |
| offset = st.getOffsetAtLocation(pt); |
| } catch (IllegalArgumentException e) { |
| // This is normal case if mouse cursor is on outside of valid |
| // text. |
| boolean found = false; |
| Point p = new Point((pt.x > 0 ? pt.x : 0), pt.y); |
| // search nearest character |
| for (; p.x > -1; p.x--) { |
| try { |
| offset = st.getOffsetAtLocation(p); |
| |
| /* |
| * Now that a valid offset has been found, try to place at |
| * the end of the line |
| */ |
| if (textViewer != null && textViewer.getDocument() != null) { |
| IRegion lineInfo = null; |
| try { |
| lineInfo = textViewer.getDocument().getLineInformationOfOffset(offset); |
| } catch (BadLocationException e1) { |
| } |
| if (lineInfo != null) |
| offset = lineInfo.getOffset() + lineInfo.getLength(); |
| } |
| |
| found = true; |
| break; |
| } catch (IllegalArgumentException ex) { |
| } |
| } |
| |
| if (!found) { |
| offset = st.getCharCount(); |
| } |
| } |
| return offset; |
| } |
| |
| public IEditorPart getTargetEditor() { |
| return targetEditor; |
| } |
| |
| public ITextViewer getTextViewer() { |
| return textViewer; |
| } |
| |
| /** |
| * @return org.eclipse.swt.dnd.Transfer[] |
| */ |
| public Transfer[] getTransfers() { |
| if (transfers == null) { |
| TransferBuilder tb = new TransferBuilder(useProxy); |
| if (editorIds == null || editorIds.length == 0) |
| transfers = tb.getDropTargetTransfers(getTargetEditor().getClass().getName()); |
| else |
| transfers = tb.getDropTargetTransfers(editorIds); |
| } |
| return transfers; |
| } |
| |
| /** |
| */ |
| public void setTargetEditor(IEditorPart targetEditor) { |
| this.targetEditor = targetEditor; |
| } |
| |
| public void setTargetIDs(String[] ids) { |
| editorIds = ids; |
| } |
| |
| public void setTextViewer(ITextViewer textViewer) { |
| this.textViewer = textViewer; |
| } |
| |
| private Point toControl(Point point) { |
| return (textViewer != null ? textViewer.getTextWidget().toControl(point) : point); |
| } |
| } |