diff options
author | Max Weninger | 2012-02-07 07:38:23 +0000 |
---|---|---|
committer | Uwe Stieber | 2012-02-07 07:38:23 +0000 |
commit | edefa214b6c4507942056e49cce6a9e52aec383c (patch) | |
tree | 492849f1e6fd5971f573c40a38cdda99aac7a020 /target_explorer | |
parent | 6ac1b3f8af26ec38c29db9751c678b67d4e898d4 (diff) | |
download | org.eclipse.tcf-edefa214b6c4507942056e49cce6a9e52aec383c.tar.gz org.eclipse.tcf-edefa214b6c4507942056e49cce6a9e52aec383c.tar.xz org.eclipse.tcf-edefa214b6c4507942056e49cce6a9e52aec383c.zip |
Target Explorer: Bug 367481 - [TERMINALS] Add support for DND of terminal tabs between views
Diffstat (limited to 'target_explorer')
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 917f337c3..790bba719 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 74704149e..11539b688 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 967185bb5..f35f039ab 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) |