summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
authorMax Weninger2012-02-07 02:38:23 (EST)
committer Uwe Stieber2012-02-07 02:38:23 (EST)
commitedefa214b6c4507942056e49cce6a9e52aec383c (patch)
tree492849f1e6fd5971f573c40a38cdda99aac7a020
parent6ac1b3f8af26ec38c29db9751c678b67d4e898d4 (diff)
downloadorg.eclipse.tcf-edefa214b6c4507942056e49cce6a9e52aec383c.zip
org.eclipse.tcf-edefa214b6c4507942056e49cce6a9e52aec383c.tar.gz
org.eclipse.tcf-edefa214b6c4507942056e49cce6a9e52aec383c.tar.bz2
Target Explorer: Bug 367481 - [TERMINALS] Add support for DND of terminal tabs between views
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.ui.terminals/src/org/eclipse/tcf/te/ui/terminals/manager/ConsoleManager.java3
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.ui.terminals/src/org/eclipse/tcf/te/ui/terminals/tabs/TabFolderManager.java110
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.ui.terminals/src/org/eclipse/tcf/te/ui/terminals/view/TerminalsView.java292
3 files changed, 380 insertions, 25 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.ui.terminals/src/org/eclipse/tcf/te/ui/terminals/manager/ConsoleManager.java b/target_explorer/plugins/org.eclipse.tcf.te.ui.terminals/src/org/eclipse/tcf/te/ui/terminals/manager/ConsoleManager.java
index 917f337..790bba7 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.ui.terminals/src/org/eclipse/tcf/te/ui/terminals/manager/ConsoleManager.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.ui.terminals/src/org/eclipse/tcf/te/ui/terminals/manager/ConsoleManager.java
@@ -432,6 +432,9 @@ public class ConsoleManager {
// Show the tab folder page
view.switchToTabFolderControl();
+
+ // make sure the terminals view has the focus after opening a new terminal
+ view.setFocus();
}
/**
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.ui.terminals/src/org/eclipse/tcf/te/ui/terminals/tabs/TabFolderManager.java b/target_explorer/plugins/org.eclipse.tcf.te.ui.terminals/src/org/eclipse/tcf/te/ui/terminals/tabs/TabFolderManager.java
index 7470414..11539b6 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.ui.terminals/src/org/eclipse/tcf/te/ui/terminals/tabs/TabFolderManager.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.ui.terminals/src/org/eclipse/tcf/te/ui/terminals/tabs/TabFolderManager.java
@@ -49,7 +49,9 @@ import org.eclipse.tcf.te.ui.terminals.interfaces.ImageConsts;
import org.eclipse.tm.internal.terminal.control.ITerminalListener;
import org.eclipse.tm.internal.terminal.control.ITerminalViewControl;
import org.eclipse.tm.internal.terminal.control.TerminalViewControlFactory;
+import org.eclipse.tm.internal.terminal.emulator.VT100TerminalControl;
import org.eclipse.tm.internal.terminal.provisional.api.ITerminalConnector;
+import org.eclipse.tm.internal.terminal.provisional.api.ITerminalControl;
import org.eclipse.tm.internal.terminal.provisional.api.TerminalState;
import org.eclipse.tm.internal.terminal.view.TerminalPreferencePage;
import org.eclipse.tm.internal.terminal.view.TerminalViewPlugin;
@@ -381,6 +383,108 @@ public class TabFolderManager extends PlatformObject implements ISelectionProvid
}
/**
+ * Used for DnD of terminal tab items between terminal views
+ * <p>
+ * Create a new tab item in the "dropped" terminal view using the
+ * information stored in the given item.
+ *
+ * @param oldItem The old dragged tab item. Must not be <code>null</code>.
+ * @return The new dropped tab item.
+ */
+ public CTabItem cloneTabItemAfterDrop(CTabItem oldItem) {
+ Assert.isNotNull(oldItem);
+
+ ITerminalViewControl terminal = (ITerminalViewControl)oldItem.getData();
+ ITerminalConnector connector = terminal.getTerminalConnector();
+ Object data=oldItem.getData("customData"); //$NON-NLS-1$
+ String title=oldItem.getText();
+
+ // The result tab item
+ CTabItem item = null;
+
+ // Get the tab folder from the parent viewer
+ CTabFolder tabFolder = getTabFolder();
+ if (tabFolder != null) {
+ // Generate a unique title string for the new tab item (must be called before creating the item itself)
+ title = makeUniqueTitle(title, tabFolder);
+ // Create the tab item
+ item = new CTabItem(tabFolder, SWT.CLOSE);
+ // Set the tab item title
+ item.setText(title);
+ // Set the tab icon
+ Image image = getTabItemImage(connector, data);
+ if (image != null) item.setImage(image);
+
+ // Setup the tab item listeners
+ setupTerminalTabListeners(item);
+
+ // Create the composite to create the terminal control within
+ Composite composite = new Composite(tabFolder, SWT.NONE);
+ composite.setLayout(new FillLayout());
+ // Associate the composite with the tab item
+ item.setControl(composite);
+
+ // Refresh the layout
+ tabFolder.getParent().layout(true);
+
+ // change the "parent".
+ //
+ // Note: We have to cast to VT100TerminalControl here until setupTerminal is
+ // re-exposed to clients via the ITerminalControl.
+ Assert.isTrue(terminal instanceof VT100TerminalControl);
+ ((VT100TerminalControl)terminal).setupTerminal(composite);
+
+ item.setData(terminal);
+
+ // Associated the custom data node with the tab item (if any)
+ if (data != null) item.setData("customData", data); //$NON-NLS-1$
+
+ // Overwrite the text canvas help id
+ String contextHelpId = getParentView().getContextHelpId();
+ if (contextHelpId != null) {
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(terminal.getControl(), contextHelpId);
+ }
+
+ // Set the context menu
+ TabFolderMenuHandler menuHandler = (TabFolderMenuHandler)getParentView().getAdapter(TabFolderMenuHandler.class);
+ if (menuHandler != null) {
+ Menu menu = (Menu)menuHandler.getAdapter(Menu.class);
+ if (menu != null) {
+ // One weird occurrence of IllegalArgumentException: Widget has wrong parent.
+ // Inspecting the code, this seem extremely unlikely. The terminal is created
+ // from a composite parent, the composite parent from the tab folder and the menu
+ // from the tab folder. Means, at the end all should have the same menu shell, shouldn't they?
+ try {
+ terminal.getControl().setMenu(menu);
+ } catch (IllegalArgumentException e) {
+ // Log exception only if debug mode is set to 1.
+ if (UIPlugin.getTraceHandler().isSlotEnabled(1, null)) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ // Select the created item within the tab folder
+ tabFolder.setSelection(item);
+
+ // Set the connector
+ terminal.setConnector(connector);
+
+ // needed to get the focus and cursor
+ Assert.isTrue(terminal instanceof ITerminalControl);
+ ((ITerminalControl)terminal).setState(TerminalState.CONNECTED);
+
+ // Fire selection changed event
+ fireSelectionChanged();
+ }
+
+ // Return the create tab item finally.
+ return item;
+ }
+
+
+ /**
* Generate a unique title string based on the given proposal.
*
* @param proposal The proposal. Must not be <code>null</code>.
@@ -416,7 +520,11 @@ public class TabFolderManager extends PlatformObject implements ISelectionProvid
Assert.isNotNull(item);
// Create and associate the disposal listener
- item.addDisposeListener(doCreateTerminalTabDisposeListener(this));
+ DisposeListener disposeListener=doCreateTerminalTabDisposeListener(this);
+
+ // store the listener to make access easier e.g. needed in DnD
+ item.setData("disposeListener", disposeListener); //$NON-NLS-1$
+ item.addDisposeListener(disposeListener);
// Create and register the property change listener
final IPropertyChangeListener propertyChangeListener = doCreateTerminalTabPropertyChangeListener(item);
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.ui.terminals/src/org/eclipse/tcf/te/ui/terminals/view/TerminalsView.java b/target_explorer/plugins/org.eclipse.tcf.te.ui.terminals/src/org/eclipse/tcf/te/ui/terminals/view/TerminalsView.java
index 967185b..f35f039 100644
--- a/target_explorer/plugins/org.eclipse.tcf.te.ui.terminals/src/org/eclipse/tcf/te/ui/terminals/view/TerminalsView.java
+++ b/target_explorer/plugins/org.eclipse.tcf.te.ui.terminals/src/org/eclipse/tcf/te/ui/terminals/view/TerminalsView.java
@@ -14,11 +14,25 @@ import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.swt.dnd.ByteArrayTransfer;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DragSource;
+import org.eclipse.swt.dnd.DragSourceEvent;
+import org.eclipse.swt.dnd.DragSourceListener;
+import org.eclipse.swt.dnd.DropTarget;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.DropTargetListener;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
import org.eclipse.tcf.te.ui.terminals.interfaces.ITerminalsView;
import org.eclipse.tcf.te.ui.terminals.tabs.TabFolderManager;
import org.eclipse.tcf.te.ui.terminals.tabs.TabFolderMenuHandler;
@@ -37,9 +51,9 @@ public class TerminalsView extends ViewPart implements ITerminalsView {
// Reference to the main page book control
private PageBook pageBookControl;
// Reference to the tab folder maintaining the consoles
- private CTabFolder tabFolderControl;
+ /* default */ CTabFolder tabFolderControl;
// Reference to the tab folder manager
- private TabFolderManager tabFolderManager;
+ /* default */ TabFolderManager tabFolderManager;
// Reference to the tab folder menu handler
private TabFolderMenuHandler tabFolderMenuHandler;
// Reference to the tab folder toolbar handler
@@ -50,28 +64,253 @@ public class TerminalsView extends ViewPart implements ITerminalsView {
private boolean pinned = false;
/**
+ * "dummy" transfer just to store the information needed for the DnD
+ *
+ */
+ private static class TerminalTransfer extends ByteArrayTransfer {
+ // The static terminal transfer type name. Unique per terminals view instance.
+ private static final String TYPE_NAME = "terminal-transfer-format:" + System.currentTimeMillis() + ":" + LazyInstanceHolder.instance.hashCode(); //$NON-NLS-2$//$NON-NLS-1$
+ // Register the type name and remember the associated unique type id.
+ private static final int TYPEID = registerType(TYPE_NAME);
+
+ private CTabItem draggedFolderItem;
+ private TabFolderManager draggedTabFolderManager;
+
+ /*
+ * Thread save singleton instance creation.
+ */
+ private static class LazyInstanceHolder {
+ public static TerminalTransfer instance = new TerminalTransfer();
+ }
+
+ /**
+ * Constructor.
+ */
+ TerminalTransfer() {
+ }
+
+ /**
+ * Returns the singleton terminal transfer instance.
+ * @return
+ */
+ public static TerminalTransfer getInstance() {
+ return LazyInstanceHolder.instance;
+ }
+
+ /**
+ * Sets the dragged folder item.
+ *
+ * @param tabFolderItem The dragged folder item or <code>null</code>.
+ */
+ public void setDraggedFolderItem(CTabItem tabFolderItem) {
+ draggedFolderItem = tabFolderItem;
+ }
+
+ /**
+ * Returns the dragged folder item.
+ *
+ * @return The dragged folder item or <code>null</code>.
+ */
+ public CTabItem getDraggedFolderItem() {
+ return draggedFolderItem;
+ }
+
+ /**
+ * Sets the tab folder manager the associated folder item is dragged from.
+ *
+ * @param tabFolderManager The tab folder manager or <code>null</code>.
+ */
+ public void setTabFolderManager(TabFolderManager tabFolderManager) {
+ draggedTabFolderManager = tabFolderManager;
+ }
+
+ /**
+ * Returns the tab folder manager the associated folder item is dragged from.
+ *
+ * @return The tab folder manager or <code>null</code>.
+ */
+ public TabFolderManager getTabFolderManager() {
+ return draggedTabFolderManager;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.swt.dnd.Transfer#getTypeIds()
+ */
+ @Override
+ protected int[] getTypeIds() {
+ return new int[] { TYPEID };
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.swt.dnd.Transfer#getTypeNames()
+ */
+ @Override
+ protected String[] getTypeNames() {
+ return new String[] { TYPE_NAME };
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.swt.dnd.ByteArrayTransfer#javaToNative(java.lang.Object, org.eclipse.swt.dnd.TransferData)
+ */
+ @Override
+ public void javaToNative(Object data, TransferData transferData) {
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.swt.dnd.ByteArrayTransfer#nativeToJava(org.eclipse.swt.dnd.TransferData)
+ */
+ @Override
+ public Object nativeToJava(TransferData transferData) {
+ return null;
+ }
+ }
+
+ /**
* Constructor.
*/
public TerminalsView() {
super();
}
- /* (non-Javadoc)
+ /**
+ * Initialize the drag support.
+ */
+ private void addDragSupport() {
+ // The event listener is registered as filter. It will receive events from all widgets.
+ PlatformUI.getWorkbench().getDisplay().addFilter(SWT.DragDetect, new Listener() {
+ /* (non-Javadoc)
+ * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
+ */
+ @Override
+ public void handleEvent(Event event) {
+ // Handle events where a CTabFolder is the source only
+ if (!(event.widget instanceof CTabFolder)) return;
+
+ // only for own tab folders
+ if (event.widget != tabFolderControl) return;
+
+ final CTabFolder draggedFolder = (CTabFolder) event.widget;
+
+ int operations = DND.DROP_MOVE | DND.DROP_DEFAULT;
+ final DragSource dragSource = new DragSource(draggedFolder, operations);
+
+ // Initialize the terminal transfer type data
+ TerminalTransfer.getInstance().setDraggedFolderItem(tabFolderManager.getActiveTabItem());
+ TerminalTransfer.getInstance().setTabFolderManager(tabFolderManager);
+
+ Transfer[] transferTypes = new Transfer[] { TerminalTransfer.getInstance() };
+ dragSource.setTransfer(transferTypes);
+
+ // Add a drag source listener to cleanup after the drag operation finished
+ dragSource.addDragListener(new DragSourceListener() {
+ @Override
+ public void dragStart(DragSourceEvent event) {
+ }
+
+ @Override
+ public void dragSetData(DragSourceEvent event) {
+ }
+
+ @Override
+ public void dragFinished(DragSourceEvent event) {
+ // dispose this drag-source-listener by disposing its drag-source
+ dragSource.dispose();
+
+ // Inhibit the action of CTabFolder's default DragDetect-listeners,
+ // fire a mouse-click event on the widget that was dragged.
+ draggedFolder.notifyListeners(SWT.MouseUp, null);
+ }
+ });
+ }
+ });
+ }
+
+ /**
+ * Initialize the drop support on the terminals page book control.
+ */
+ private void addDropSupport() {
+ int operations = DND.DROP_MOVE | DND.DROP_DEFAULT;
+ final DropTarget target = new DropTarget(pageBookControl, operations);
+
+ Transfer[] transferTypes = new Transfer[] { TerminalTransfer.getInstance() };
+ target.setTransfer(transferTypes);
+
+ target.addDropListener(new DropTargetListener() {
+ @Override
+ public void dragEnter(DropTargetEvent event) {
+ // only if the drop target is different then the drag source
+ if (TerminalTransfer.getInstance().getTabFolderManager() == tabFolderManager) {
+ event.detail = DND.DROP_NONE;
+ }
+ else {
+ event.detail = DND.DROP_MOVE;
+ }
+ }
+
+ @Override
+ public void dragOver(DropTargetEvent event) {
+ }
+
+ @Override
+ public void dragOperationChanged(DropTargetEvent event) {
+ }
+
+ @Override
+ public void dragLeave(DropTargetEvent event) {
+ }
+
+ @Override
+ public void dropAccept(DropTargetEvent event) {
+ }
+
+ @Override
+ public void drop(DropTargetEvent event) {
+ if (TerminalTransfer.getInstance().getDraggedFolderItem() != null) {
+ CTabItem draggedItem = TerminalTransfer.getInstance().getDraggedFolderItem();
+
+ CTabItem item = tabFolderManager.cloneTabItemAfterDrop(draggedItem);
+ tabFolderManager.bringToTop(item);
+ switchToTabFolderControl();
+
+ // need to remove the dispose listener first
+ DisposeListener disposeListener = (DisposeListener) draggedItem.getData("disposeListener"); //$NON-NLS-1$
+ draggedItem.removeDisposeListener(disposeListener);
+ draggedItem.dispose();
+
+ // make sure the "new" terminals view has the focus after dragging a terminal
+ setFocus();
+ }
+ }
+ });
+ }
+
+ /*
+ * (non-Javadoc)
* @see org.eclipse.ui.part.WorkbenchPart#dispose()
*/
@Override
public void dispose() {
// Dispose the tab folder manager
- if (tabFolderManager != null) { tabFolderManager.dispose(); tabFolderManager = null; }
+ if (tabFolderManager != null) {
+ tabFolderManager.dispose();
+ tabFolderManager = null;
+ }
// Dispose the tab folder menu handler
- if (tabFolderMenuHandler != null) { tabFolderMenuHandler.dispose(); tabFolderMenuHandler = null; }
+ if (tabFolderMenuHandler != null) {
+ tabFolderMenuHandler.dispose();
+ tabFolderMenuHandler = null;
+ }
// Dispose the tab folder toolbar handler
- if (tabFolderToolbarHandler != null) { tabFolderToolbarHandler.dispose(); tabFolderToolbarHandler = null; }
+ if (tabFolderToolbarHandler != null) {
+ tabFolderToolbarHandler.dispose();
+ tabFolderToolbarHandler = null;
+ }
super.dispose();
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
* @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
*/
@Override
@@ -113,12 +352,16 @@ public class TerminalsView extends ViewPart implements ITerminalsView {
// Show the empty page control by default
switchToEmptyPageControl();
- String secondaryId=((IViewSite)getSite()).getSecondaryId();
- if(secondaryId!=null){
- String defaultTitle=getPartName();
+ String secondaryId = ((IViewSite) getSite()).getSecondaryId();
+ if (secondaryId != null) {
+ String defaultTitle = getPartName();
// set title
- setPartName(defaultTitle+ " "+secondaryId); //$NON-NLS-1$
+ setPartName(defaultTitle + " " + secondaryId); //$NON-NLS-1$
}
+
+ // Initialize DnD support
+ addDragSupport();
+ addDropSupport();
}
/**
@@ -139,8 +382,7 @@ public class TerminalsView extends ViewPart implements ITerminalsView {
protected void doConfigurePageBookControl(PageBook pagebook) {
Assert.isNotNull(pagebook);
- if (getContextHelpId() != null)
- PlatformUI.getWorkbench().getHelpSystem().setHelp(pagebook, getContextHelpId());
+ if (getContextHelpId() != null) PlatformUI.getWorkbench().getHelpSystem().setHelp(pagebook, getContextHelpId());
}
/**
@@ -201,10 +443,9 @@ public class TerminalsView extends ViewPart implements ITerminalsView {
// Set the tab gradient coloring from the global preferences
if (useGradientTabBackgroundColor()) {
tabFolder.setSelectionBackground(new Color[] {
- JFaceResources.getColorRegistry().get("org.eclipse.ui.workbench.ACTIVE_TAB_BG_START"), //$NON-NLS-1$
- JFaceResources.getColorRegistry().get("org.eclipse.ui.workbench.ACTIVE_TAB_BG_END") //$NON-NLS-1$
- },
- new int[] {100}, true);
+ JFaceResources.getColorRegistry().get("org.eclipse.ui.workbench.ACTIVE_TAB_BG_START"), //$NON-NLS-1$
+ JFaceResources.getColorRegistry().get("org.eclipse.ui.workbench.ACTIVE_TAB_BG_END") //$NON-NLS-1$
+ }, new int[] { 100 }, true);
}
// Apply the tab folder selection foreground color
tabFolder.setSelectionForeground(JFaceResources.getColorRegistry().get("org.eclipse.ui.workbench.ACTIVE_TAB_TEXT_COLOR")); //$NON-NLS-1$
@@ -214,8 +455,8 @@ public class TerminalsView extends ViewPart implements ITerminalsView {
}
/**
- * If <code>True</code> is returned, the inner tabs are colored with
- * gradient coloring set in the Eclipse workbench color settings.
+ * If <code>True</code> is returned, the inner tabs are colored with gradient coloring set in
+ * the Eclipse workbench color settings.
*
* @return <code>True</code> to use gradient tab colors, <code>false</code> otherwise.
*/
@@ -307,11 +548,14 @@ public class TerminalsView extends ViewPart implements ITerminalsView {
public Object getAdapter(Class adapter) {
if (CTabFolder.class.isAssignableFrom(adapter)) {
return tabFolderControl;
- } else if (TabFolderManager.class.isAssignableFrom(adapter)) {
+ }
+ else if (TabFolderManager.class.isAssignableFrom(adapter)) {
return tabFolderManager;
- } else if (TabFolderMenuHandler.class.isAssignableFrom(adapter)) {
+ }
+ else if (TabFolderMenuHandler.class.isAssignableFrom(adapter)) {
return tabFolderMenuHandler;
- } else if (TabFolderToolbarHandler.class.isAssignableFrom(adapter)) {
+ }
+ else if (TabFolderToolbarHandler.class.isAssignableFrom(adapter)) {
return tabFolderToolbarHandler;
}
@@ -322,8 +566,8 @@ public class TerminalsView extends ViewPart implements ITerminalsView {
* @see org.eclipse.tcf.te.ui.terminals.interfaces.ITerminalsView#setPinned(boolean)
*/
@Override
- public void setPinned(boolean pin) {
- this.pinned = pin;
+ public void setPinned(boolean pin) {
+ this.pinned = pin;
}
/* (non-Javadoc)