/******************************************************************************* * 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); } }