diff options
Diffstat (limited to 'plugins/org.eclipse.tcf.debug.ui/src')
14 files changed, 3017 insertions, 608 deletions
diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/ImageCache.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/ImageCache.java index c16467746..c195b5c61 100644 --- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/ImageCache.java +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/ImageCache.java @@ -30,7 +30,9 @@ public class ImageCache { public static final String IMG_TCF = "icons/tcf.gif", IMG_TARGET_TAB = "icons/target_tab.gif", + IMG_DOWNLOAD_TAB = "icons/download_tab.gif", IMG_TARGET_WIZARD = "icons/full/wizban/debug_wiz.png", + IMG_APPLICATION_TAB = "icons/application_tab.gif", IMG_ARGUMENTS_TAB = "icons/arguments_tab.gif", IMG_ATTRIBUTE = "icons/attribute.gif", IMG_PATH = "icons/path.gif", diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextListControl.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextListControl.java new file mode 100644 index 000000000..ee93d532b --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextListControl.java @@ -0,0 +1,653 @@ +/******************************************************************************* + * Copyright (c) 2011, 2013 Wind River Systems, Inc. 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.internal.debug.ui.launch; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +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.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.tcf.internal.debug.ui.ImageCache; +import org.eclipse.tcf.internal.debug.ui.model.TCFModel; +import org.eclipse.tcf.protocol.IChannel; +import org.eclipse.tcf.protocol.IChannel.IChannelListener; +import org.eclipse.tcf.protocol.IPeer; +import org.eclipse.tcf.protocol.IToken; +import org.eclipse.tcf.protocol.Protocol; +import org.eclipse.tcf.services.IProcesses; +import org.eclipse.tcf.services.IProcesses.ProcessContext; +import org.eclipse.tcf.services.IRunControl; +import org.eclipse.tcf.services.IRunControl.RunControlContext; +import org.eclipse.tcf.services.ISysMonitor; +import org.eclipse.tcf.services.ISysMonitor.SysMonitorContext; +import org.eclipse.tcf.util.TCFTask; + +public class ContextListControl { + + private final class ProcessListener implements IProcesses.ProcessesListener { + public void exited(final String process_id, int exit_code) { + onContextRemoved(process_id); + } + } + + private final class ContextListener implements IRunControl.RunControlListener { + @Override + public void contextAdded(RunControlContext[] contexts) { + for (RunControlContext ctx : contexts) { + onContextAdded(ctx.getParentID()); + } + } + @Override + public void contextChanged(RunControlContext[] contexts) { + } + @Override + public void contextRemoved(String[] context_ids) { + for (String id : context_ids) { + onContextRemoved(id); + } + } + @Override + public void contextSuspended(String context, String pc, String reason, Map<String, Object> params) { + } + @Override + public void contextResumed(String context) { + } + @Override + public void containerSuspended(String context, String pc, String reason, Map<String, Object> params, String[] suspended_ids) { + } + @Override + public void containerResumed(String[] context_ids) { + } + @Override + public void contextException(String context, String msg) { + } + } + + static class ContextInfo { + String name; + String id; + boolean is_attached; + boolean is_container; + boolean has_state; + long pid; + String[] cmd_line; + ContextInfo[] children; + Throwable children_error; + boolean children_pending; + boolean children_reload; + ContextInfo parent; + } + + private Composite composite; + private Tree ctx_tree; + private Display display; + private IChannel channel; + private String channel_state; + private final ContextInfo root_info = new ContextInfo(); + private final ProcessListener prs_listener = new ProcessListener(); + private final ContextListener ctx_listener = new ContextListener(); + private final boolean processes; + private String initial_selection; + + public ContextListControl(Composite parent, boolean processes) { + this.processes = processes; + display = parent.getDisplay(); + parent.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + Protocol.invokeAndWait(new Runnable() { + public void run() { + disconnectPeer(); + display = null; + } + }); + } + }); + createContextListArea(parent); + } + + public void setInput(final IPeer peer) { + assert Thread.currentThread() == display.getThread(); + channel = new TCFTask<IChannel>() { + public void run() { + disconnectPeer(); + done(connectPeer(peer)); + } + }.getE(); + root_info.children = null; + root_info.children_error = null; + root_info.children_pending = false; + root_info.children_reload = false; + loadChildren(root_info); + } + + public Control getControl() { + return composite; + } + + public Tree getTree() { + return ctx_tree; + } + + public ContextInfo getSelection() { + if (ctx_tree != null) { + initial_selection = null; + TreeItem[] items = ctx_tree.getSelection(); + if (items.length > 0) { + ContextInfo info = findInfo(items[0]); + return info; + } + } + return null; + } + + private void createContextListArea(Composite parent) { + Font font = parent.getFont(); + composite = new Composite(parent, SWT.NONE); + composite.setFont(font); + GridLayout layout = new GridLayout(1, false); + layout.marginWidth = 0; + layout.marginHeight = 0; + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true)); + + ctx_tree = new Tree(composite, SWT.VIRTUAL | SWT.BORDER | SWT.SINGLE); + GridData gd = new GridData(GridData.FILL_BOTH); + gd.minimumHeight = 150; + gd.minimumWidth = 470; + ctx_tree.setLayoutData(gd); + ctx_tree.setFont(font); + ctx_tree.addListener(SWT.SetData, new Listener() { + public void handleEvent(Event event) { + TreeItem item = (TreeItem)event.item; + ContextInfo info = findInfo(item); + if (info == null) { + updateItems(item.getParentItem(), false); + } + else { + fillItem(item, info); + } + } + }); + } + + protected void disconnectPeer() { + if (channel != null && channel.getState() != IChannel.STATE_CLOSED) { + channel.close(); + } + } + + protected IChannel connectPeer(IPeer peer) { + if (peer == null) return null; + final IChannel channel = peer.openChannel(); + channel.addChannelListener(new IChannelListener() { + public void congestionLevel(int level) { + } + public void onChannelClosed(final Throwable error) { + if (display != null) { + display.asyncExec(new Runnable() { + public void run() { + if (ContextListControl.this.channel != channel) return; + root_info.children_error = error; + loadChildren(root_info); + } + }); + } + } + public void onChannelOpened() { + if (processes) { + IProcesses service = channel.getRemoteService(IProcesses.class); + if (service != null) service.addListener(prs_listener); + } + else { + IRunControl service = channel.getRemoteService(IRunControl.class); + if (service != null) service.addListener(ctx_listener); + } + if (display != null) { + display.asyncExec(new Runnable() { + public void run() { + if (ContextListControl.this.channel != channel) return; + loadChildren(root_info); + updateItems(root_info); + } + }); + } + } + }); + return channel; + } + + private void updateItems(TreeItem parent_item, boolean reload) { + final ContextInfo parent_info = findInfo(parent_item); + if (parent_info == null) { + parent_item.setText("Invalid"); + } + else { + if (reload && parent_info.children_error != null) { + loadChildren(parent_info); + } + display.asyncExec(new Runnable() { + public void run() { + updateItems(parent_info); + } + }); + } + } + + private void updateItems(final ContextInfo parent) { + if (display == null) return; + assert Thread.currentThread() == display.getThread(); + TreeItem[] items = null; + boolean expanded = true; + if (parent.children == null || parent.children_error != null) { + if (parent == root_info) { + ctx_tree.deselectAll(); + ctx_tree.setItemCount(1); + items = ctx_tree.getItems(); + } + else { + TreeItem item = findItem(parent); + if (item == null) return; + expanded = item.getExpanded(); + item.setItemCount(1); + items = item.getItems(); + } + assert items.length == 1; + items[0].removeAll(); + items[0].setImage((Image)null); + items[0].setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); + if (parent.children_pending) { + items[0].setText("Pending..."); + } + else if (parent.children_error != null) { + String msg = TCFModel.getErrorMessage(parent.children_error, false); + items[0].setForeground(display.getSystemColor(SWT.COLOR_RED)); + items[0].setText(msg); + } + else if (channel_state != null) { + items[0].setText(channel_state); + } + else if (expanded) { + loadChildren(parent); + items[0].setText("Pending..."); + } + else { + items[0].setText(""); + } + } + else { + ContextInfo[] arr = parent.children; + if (parent == root_info) { + ctx_tree.setItemCount(arr.length); + items = ctx_tree.getItems(); + } + else { + TreeItem item = findItem(parent); + if (item == null) return; + expanded = item.getExpanded(); + item.setItemCount(expanded ? arr.length : 1); + items = item.getItems(); + } + if (expanded) { + assert items.length == arr.length; + for (int i = 0; i < items.length; i++) fillItem(items[i], arr[i]); + // auto-expand single children + if (items.length == 1 && !items[0].getExpanded()) { + items[0].setExpanded(true); + } + } + else { + items[0].setText(""); + } + } + if (initial_selection != null) { + setInitialSelection(initial_selection); + } + } + + private void loadChildren(final ContextInfo parent) { + assert Thread.currentThread() == display.getThread(); + final IChannel channel = this.channel; + parent.children_reload = true; + if (parent.children_pending) return; + parent.children_reload = false; + parent.children_pending = true; + Protocol.invokeLater(new Runnable() { + public void run() { + if (channel == null || channel.getState() != IChannel.STATE_OPEN) { + doneLoadChildren(channel, parent, null, new ContextInfo[0]); + } + else if (processes) { + loadProcessChildren(channel, parent); + } + else { + loadContextChildren(channel, parent); + } + } + }); + } + + private void loadProcessChildren(final IChannel channel, final ContextInfo parent) { + final IProcesses service = channel.getRemoteService(IProcesses.class); + final ISysMonitor sysmon = channel.getRemoteService(ISysMonitor.class); + if (service == null) { + doneLoadChildren(channel, parent, new Exception("Peer does not support Processes service"), null); + } + else if (!canHaveChildren(parent)) { + doneLoadChildren(channel, parent, null, new ContextInfo[0]); + } + else { + service.getChildren(parent.id, false, new IProcesses.DoneGetChildren() { + public void doneGetChildren(IToken token, Exception error, String[] context_ids) { + if (error != null) { + doneLoadChildren(channel, parent, error, null); + } + else if (context_ids == null || context_ids.length == 0) { + doneLoadChildren(channel, parent, null, new ContextInfo[0]); + } + else { + final List<ContextInfo> infos = new ArrayList<ContextInfo>(context_ids.length); + final Set<IToken> pending = new HashSet<IToken>(); + for (final String id : context_ids) { + final ContextInfo info = new ContextInfo(); + info.parent = parent; + info.id = id; + pending.add(service.getContext(id, new IProcesses.DoneGetContext() { + public void doneGetContext(IToken token, Exception error, ProcessContext context) { + if (context != null) { + info.name = context.getName(); + info.is_attached = context.isAttached(); + infos.add(info); + } + pending.remove(token); + if (!pending.isEmpty()) return; + doneLoadChildren(channel, parent, null, infos.toArray(new ContextInfo[infos.size()])); + } + })); + if (sysmon != null) { + pending.add(sysmon.getContext(id, new ISysMonitor.DoneGetContext() { + @Override + public void doneGetContext(IToken token, Exception error, SysMonitorContext context) { + if (context != null) { + info.pid = context.getPID(); + } + pending.remove(token); + if (!pending.isEmpty()) return; + doneLoadChildren(channel, parent, null, infos.toArray(new ContextInfo[infos.size()])); + } + })); + pending.add(sysmon.getCommandLine(id, new ISysMonitor.DoneGetCommandLine() { + @Override + public void doneGetCommandLine(IToken token, Exception error, String[] cmd_line) { + if (cmd_line != null) { + info.cmd_line = cmd_line; + } + pending.remove(token); + if (!pending.isEmpty()) return; + doneLoadChildren(channel, parent, null, infos.toArray(new ContextInfo[infos.size()])); + } + })); + } + } + } + } + }); + } + } + + private void loadContextChildren(final IChannel channel, final ContextInfo parent) { + final IRunControl service = channel.getRemoteService(IRunControl.class); + if (service == null) { + doneLoadChildren(channel, parent, new Exception("Peer does not support Run Control service"), null); + } + else if (!canHaveChildren(parent)) { + doneLoadChildren(channel, parent, null, new ContextInfo[0]); + } + else { + service.getChildren(parent.id, new IRunControl.DoneGetChildren() { + public void doneGetChildren(IToken token, Exception error, String[] context_ids) { + if (error != null) { + doneLoadChildren(channel, parent, error, null); + } + else if (context_ids != null && context_ids.length > 0) { + final List<ContextInfo> infos = new ArrayList<ContextInfo>(context_ids.length); + final Set<IToken> pending = new HashSet<IToken>(); + for (String id : context_ids) { + pending.add(service.getContext(id, new IRunControl.DoneGetContext() { + public void doneGetContext(IToken token, Exception error, RunControlContext context) { + if (context != null) { + ContextInfo info = new ContextInfo(); + info.parent = parent; + info.id = context.getID(); + info.name = context.getName(); + info.is_container = context.isContainer(); + info.has_state = context.hasState(); + info.is_attached = true; + infos.add(info); + } + pending.remove(token); + if (!pending.isEmpty()) return; + doneLoadChildren(channel, parent, null, infos.toArray(new ContextInfo[infos.size()])); + } + })); + } + } + else { + doneLoadChildren(channel, parent, null, new ContextInfo[0]); + } + } + }); + } + } + + private void doneLoadChildren(final IChannel channel, final ContextInfo parent, final Throwable error, final ContextInfo[] children) { + assert Protocol.isDispatchThread(); + assert error == null || children == null; + if (display == null) return; + final String state = getChannelState(channel); + display.asyncExec(new Runnable() { + public void run() { + if (ContextListControl.this.channel != channel) return; + assert parent.children_pending; + parent.children_pending = false; + if (state == null) { + parent.children = children; + parent.children_error = error; + if (parent.children_reload) { + loadChildren(parent); + } + } + else { + parent.children = null; + parent.children_reload = false; + } + channel_state = state; + updateItems(parent); + } + }); + } + + private String getChannelState(IChannel channel) { + if (channel == null) return "Not connected"; + switch (channel.getState()) { + case IChannel.STATE_OPENING: return "Connecting..."; + case IChannel.STATE_CLOSED: return "Disconnected"; + } + return null; + } + + private void onContextRemoved(final String id) { + if (display == null) return; + display.asyncExec(new Runnable() { + public void run() { + ContextInfo info = findInfo(root_info, id); + if (info != null && info.parent != null) loadChildren(info.parent); + } + }); + } + + private void onContextAdded(final String parent_id) { + if (display == null) return; + display.asyncExec(new Runnable() { + public void run() { + ContextInfo info = findInfo(root_info, parent_id); + if (info != null) loadChildren(info); + } + }); + } + + public String getFullName(ContextInfo info) { + if (info == null) return null; + String name = info.name; + if (name == null) name = info.id; + if (info.parent == root_info) return "/" + name; + if (info.parent == null) return null; + String path = getFullName(info.parent); + if (path == null) return null; + return path + '/' + name; + } + + private ContextInfo findInfoByFullName(ContextInfo parent, String name, boolean expand) { + if (name == null) return null; + if (name.startsWith("/")) return findInfoByFullName(root_info, name.substring(1), expand); + if (parent.children_pending) return null; + String head = name; + String tail = null; + int i = name.indexOf('/'); + if (i >= 0) { + head = name.substring(0, i); + tail = name.substring(i + 1); + } + ContextInfo[] children = parent.children; + if (children != null) { + for (ContextInfo info : children) { + if (head.equals(info.name)) { + if (tail == null) return info; + if (expand) { + TreeItem item = findItem(info); + if (item != null) item.setExpanded(true); + } + return findInfoByFullName(info, tail, expand); + } + } + } + else if (expand) { + loadChildren(parent); + } + return null; + } + + public ContextInfo findInfo(TreeItem item) { + assert Thread.currentThread() == display.getThread(); + if (item == null) return root_info; + return (ContextInfo)item.getData("TCFContextInfo"); + } + + public ContextInfo findInfo(ContextInfo parent, String id) { + assert Thread.currentThread() == display.getThread(); + if (id == null) return root_info; + if (id.equals(parent.id)) return parent; + ContextInfo[] children = parent.children; + if (children != null) { + for (ContextInfo info : children) { + ContextInfo found = findInfo(info, id); + if (found != null) return found; + } + } + return null; + } + + private TreeItem findItem(ContextInfo info) { + assert Thread.currentThread() == display.getThread(); + if (info == null) return null; + assert info.parent != null; + if (info.parent == root_info) { + TreeItem[] items = ctx_tree.getItems(); + for (TreeItem item : items) { + if (item.getData("TCFContextInfo") == info) return item; + } + return null; + } + TreeItem parent = findItem(info.parent); + if (parent == null) return null; + TreeItem[] items = parent.getItems(); + for (TreeItem item : items) { + if (item.getData("TCFContextInfo") == info) return item; + } + return null; + } + + private void fillItem(TreeItem item, ContextInfo info) { + assert Thread.currentThread() == display.getThread(); + Object data = item.getData("TCFContextInfo"); + if (data != null && data != info) item.removeAll(); + item.setData("TCFContextInfo", info); + StringBuffer bf = new StringBuffer(); + if (info.pid > 0) { + bf.append(info.pid); + bf.append(": "); + } + if (info.cmd_line != null && info.cmd_line.length > 0) { + for (String s : info.cmd_line) { + bf.append(' '); + bf.append(s); + } + } + else if (info.name != null) { + bf.append(info.name); + } + else { + bf.append(info.id); + } + item.setText(bf.toString()); + item.setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); + item.setImage(getImage(info)); + if (!canHaveChildren(info)) item.setItemCount(0); + else if (info.children == null || info.children_error != null) item.setItemCount(1); + else item.setItemCount(info.children.length); + } + + private boolean canHaveChildren(ContextInfo info) { + return !info.has_state && (info.is_container || info == root_info); + } + + private Image getImage(ContextInfo info) { + return ImageCache.getImage(info.has_state ? ImageCache.IMG_THREAD_UNKNOWN_STATE : ImageCache.IMG_PROCESS_RUNNING); + } + + public void setInitialSelection(String full_name) { + if (full_name == null) return; + if (full_name.length() == 0) return; + initial_selection = full_name; + ContextInfo info = findInfoByFullName(null, full_name, true); + if (info != null) { + TreeItem item = findItem(info); + if (item != null) { + ctx_tree.setSelection(item); + initial_selection = null; + } + } + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextSelection.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextSelection.java new file mode 100644 index 000000000..3337782ea --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextSelection.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2011, 2013 Wind River Systems, Inc. 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.internal.debug.ui.launch; + +public class ContextSelection { + public String fPeerId; + public String fContextId; + public String fContextFullName; + public String fContextName; + public boolean fIsAttached; +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextSelectionDialog.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextSelectionDialog.java new file mode 100644 index 000000000..5c284d425 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/ContextSelectionDialog.java @@ -0,0 +1,115 @@ +/******************************************************************************* + * Copyright (c) 2011, 2013 Wind River Systems, Inc. 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.internal.debug.ui.launch; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.window.IShellProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.tcf.internal.debug.ui.launch.PeerListControl.PeerInfo; +import org.eclipse.tcf.internal.debug.ui.launch.ContextListControl.ContextInfo; + +/** + * Dialog to select a peer and context. + */ +public class ContextSelectionDialog extends Dialog { + + private final boolean processes; + private ContextSelection selection; + private ContextListControl context_list; + + public ContextSelectionDialog(IShellProvider parentShell, boolean processes) { + super(parentShell); + this.processes = processes; + } + + public void setSelection(ContextSelection selection) { + this.selection = selection; + } + + public ContextSelection getSelection() { + return selection; + } + + @Override + protected void configureShell(Shell shell) { + shell.setText("Select Peer and Context"); + super.configureShell(shell); + } + + @Override + protected Control createContents(Composite parent) { + Control control = super.createContents(parent); + updateButtonState(); + return control; + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + new Label(composite, SWT.NONE).setText("Peers:"); + final PeerListControl peerList = new PeerListControl(composite) { + @Override + protected void onPeerSelected(PeerInfo info) { + handlePeerSelected(info); + } + }; + new Label(composite, SWT.NONE).setText("Contexts:"); + context_list = new ContextListControl(composite, processes); + context_list.getTree().addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + ContextInfo contextInfo = context_list.findInfo((TreeItem) e.item); + if (contextInfo != null) { + handleContextSelected(contextInfo); + } + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + widgetSelected(e); + if (getButton(IDialogConstants.OK_ID).isEnabled()) { + buttonPressed(IDialogConstants.OK_ID); + } + } + }); + if (selection.fPeerId != null) { + peerList.setInitialSelection(selection.fPeerId); + } + if (selection.fContextFullName != null) { + context_list.setInitialSelection(selection.fContextFullName); + } + return composite; + } + + private void updateButtonState() { + getButton(IDialogConstants.OK_ID).setEnabled(selection.fContextId != null); + } + + protected void handleContextSelected(ContextInfo info) { + selection.fContextId = info.id; + selection.fContextName = info.name; + selection.fContextFullName = context_list.getFullName(info); + selection.fIsAttached = info.is_attached; + updateButtonState(); + } + + protected void handlePeerSelected(PeerInfo info) { + selection.fPeerId = info.id; + context_list.setInput(info.peer); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/DownloadFileDialog.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/DownloadFileDialog.java new file mode 100644 index 000000000..dde60d720 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/DownloadFileDialog.java @@ -0,0 +1,400 @@ +/******************************************************************************* + * Copyright (c) 2013 Xilinx, Inc. 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: + * Xilinx - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.internal.debug.ui.launch; + +import java.math.BigInteger; +import java.util.Map; + +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.tcf.internal.debug.launch.TCFLaunchDelegate; +import org.eclipse.tcf.internal.debug.ui.ImageCache; +import org.eclipse.tcf.internal.debug.ui.model.TCFModel; +import org.eclipse.tcf.protocol.JSON; + +class DownloadFileDialog extends Dialog { + + private final Image image; + private final String peer_id; + private final Map<String,Object> map; + + private Text context_text; + private Text file_text; + private Text addr_text; + private Text size_text; + private Text offs_text; + private Button file_button; + private Button context_button; + private Button load_syms_button; + private Button relocate_button; + private Button download_button; + private Button set_pc_button; + private Button osa_button; + + DownloadFileDialog(Shell parentShell, String peer_id, Map<String,Object> map) { + super(parentShell); + this.image = ImageCache.getImage(ImageCache.IMG_DOWNLOAD_TAB); + this.peer_id = peer_id; + this.map = map; + } + + @Override + protected void configureShell(Shell shell) { + super.configureShell(shell); + shell.setText("Download File"); //$NON-NLS-1$ + shell.setImage(image); + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); + createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); + updateButtons(); + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite)super.createDialogArea(parent); + createFileFields(composite); + setData(); + composite.setSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT)); + return composite; + } + + private void createFileFields(Composite parent) { + Font font = parent.getFont(); + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(3, false); + composite.setFont(font); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + Label context_label = new Label(composite, SWT.NONE); + context_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + context_label.setFont(font); + context_label.setText("Context:"); //$NON-NLS-1$ + + context_text = new Text(composite, SWT.SINGLE | SWT.BORDER); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.widthHint = 400; + context_text.setLayoutData(gd); + context_text.setFont(font); + + context_text.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + updateButtons(); + } + }); + + context_button = new Button(composite, SWT.PUSH); + context_button.setText("Select..."); //$NON-NLS-1$ + context_button.setFont(font); + context_button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + context_button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + String context = context_text.getText().trim(); + ContextSelection selection = new ContextSelection(); + selection.fPeerId = peer_id; + selection.fContextFullName = context; + ContextSelectionDialog diag = new ContextSelectionDialog(DownloadFileDialog.this, false); + diag.setSelection(selection); + if (diag.open() == Window.OK) { + selection = diag.getSelection(); + context_text.setText(selection.fContextFullName); + } + } + }); + + Label file_label = new Label(composite, SWT.NONE); + file_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + file_label.setFont(font); + file_label.setText("File:"); //$NON-NLS-1$ + + file_text = new Text(composite, SWT.SINGLE | SWT.BORDER); + file_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + file_text.setFont(font); + + file_text.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + updateButtons(); + } + }); + + file_button = new Button(composite, SWT.PUSH); + file_button.setText("Browse..."); //$NON-NLS-1$ + file_button.setFont(font); + file_button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + file_button.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + String path = file_text.getText().trim(); + if (path.length() == 0) path = ResourcesPlugin.getWorkspace().getRoot().getLocation().toOSString(); + FileDialog dialog = new FileDialog(getShell(), SWT.NONE); + dialog.setFilterPath(path); + path = dialog.open(); + if (path != null) file_text.setText(path); + } + }); + + load_syms_button = new Button(composite, SWT.CHECK); + load_syms_button.setText("Load symbols"); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 3; + load_syms_button.setLayoutData(gd); + load_syms_button.setFont(font); + load_syms_button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent evt) { + updateButtons(); + } + }); + load_syms_button.setEnabled(true); + + relocate_button = new Button(composite, SWT.CHECK); + relocate_button.setText("Relocate the file"); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 3; + relocate_button.setLayoutData(gd); + relocate_button.setFont(font); + relocate_button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent evt) { + updateButtons(); + } + }); + relocate_button.setEnabled(true); + Composite rel_group = createRelocateGroup(composite); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 3; + rel_group.setLayoutData(gd); + + download_button = new Button(composite, SWT.CHECK); + download_button.setText("Download the file into the context memory"); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 3; + download_button.setLayoutData(gd); + download_button.setFont(font); + download_button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent evt) { + updateButtons(); + } + }); + download_button.setEnabled(true); + + set_pc_button = new Button(composite, SWT.CHECK); + set_pc_button.setText("Set PC to program entry address"); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 3; + set_pc_button.setLayoutData(gd); + set_pc_button.setFont(font); + set_pc_button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent evt) { + updateButtons(); + } + }); + set_pc_button.setEnabled(true); + + osa_button = new Button(composite, SWT.CHECK); + osa_button.setText("Enable OS awarennes - the file is an OS kernel"); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 3; + osa_button.setLayoutData(gd); + osa_button.setFont(font); + osa_button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent evt) { + updateButtons(); + } + }); + osa_button.setEnabled(true); + } + + private Composite createRelocateGroup(Composite parent) { + Font font = parent.getFont(); + + Group group = new Group(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.verticalSpacing = 0; + layout.numColumns = 2; + group.setLayout(layout); + group.setLayoutData(new GridData(GridData.FILL_BOTH)); + group.setFont(font); + group.setText("File location in the context memory"); + + Label addr_label = new Label(group, SWT.WRAP); + addr_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + addr_label.setFont(font); + addr_label.setText("Address:"); + + addr_text = new Text(group, SWT.SINGLE | SWT.BORDER); + addr_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + addr_text.setFont(font); + + Label size_label = new Label(group, SWT.WRAP); + size_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + size_label.setFont(font); + size_label.setText("Size:"); + + size_text = new Text(group, SWT.SINGLE | SWT.BORDER); + size_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + size_text.setFont(font); + + Label offset_label = new Label(group, SWT.WRAP); + offset_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); + offset_label.setFont(font); + offset_label.setText("File offset:"); + + offs_text = new Text(group, SWT.SINGLE | SWT.BORDER); + offs_text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + offs_text.setFont(font); + + return group; + } + + private String toHex(Number n) { + if (n == null) return null; + BigInteger x = JSON.toBigInteger(n); + String s = x.toString(16); + int l = 16 - s.length(); + if (l < 0) l = 0; + if (l > 16) l = 16; + return "0x0000000000000000".substring(0, 2 + l) + s; + } + + private void setString(Text text, String key) { + String s = (String)map.get(key); + if (s == null) s = ""; + text.setText(s); + } + + private void setBoolean(Button btn, String key) { + Boolean b = (Boolean)map.get(key); + if (b == null) btn.setSelection(false); + else btn.setSelection(b.booleanValue()); + } + + private void setNumber(Text text, String key) { + Number n = (Number)map.get(key); + if (n == null) text.setText(""); + else text.setText(toHex(n)); + } + + private void setData() { + setString(context_text, TCFLaunchDelegate.FILES_CONTEXT_FULL_NAME); + setString(file_text, TCFLaunchDelegate.FILES_FILE_NAME); + setBoolean(load_syms_button, TCFLaunchDelegate.FILES_LOAD_SYMBOLS); + setBoolean(relocate_button, TCFLaunchDelegate.FILES_RELOCATE); + setBoolean(download_button, TCFLaunchDelegate.FILES_DOWNLOAD); + setBoolean(set_pc_button, TCFLaunchDelegate.FILES_SET_PC); + setBoolean(osa_button, TCFLaunchDelegate.FILES_ENABLE_OSA); + setNumber(addr_text, TCFLaunchDelegate.FILES_ADDRESS); + setNumber(offs_text, TCFLaunchDelegate.FILES_OFFSET); + setNumber(size_text, TCFLaunchDelegate.FILES_SIZE); + updateButtons(); + } + + private void getBoolean(Button btn, String key) { + boolean b = btn.getSelection(); + if (!b) { + map.remove(key); + } + else { + map.put(key, Boolean.TRUE); + } + } + + private void getString(Text text, String key) { + String s = text.getText().trim(); + if (s == null || s.length() == 0) { + map.remove(key); + } + else { + map.put(key, s); + } + } + + private void getNumber(Text text, String key) { + String s = text.getText().trim(); + if (s == null || s.length() == 0) { + map.remove(key); + } + else if (s.startsWith("0x")) { + map.put(key, new BigInteger(s.substring(2), 16)); + } + else { + map.put(key, new BigInteger(s)); + } + } + + private void getData() { + getString(context_text, TCFLaunchDelegate.FILES_CONTEXT_FULL_NAME); + getString(file_text, TCFLaunchDelegate.FILES_FILE_NAME); + getBoolean(load_syms_button, TCFLaunchDelegate.FILES_LOAD_SYMBOLS); + getBoolean(relocate_button, TCFLaunchDelegate.FILES_RELOCATE); + getBoolean(download_button, TCFLaunchDelegate.FILES_DOWNLOAD); + getBoolean(set_pc_button, TCFLaunchDelegate.FILES_SET_PC); + getBoolean(osa_button, TCFLaunchDelegate.FILES_ENABLE_OSA); + getNumber(addr_text, TCFLaunchDelegate.FILES_ADDRESS); + getNumber(offs_text, TCFLaunchDelegate.FILES_OFFSET); + getNumber(size_text, TCFLaunchDelegate.FILES_SIZE); + } + + private void updateButtons() { + Button btn = getButton(IDialogConstants.OK_ID); + if (btn != null && context_text != null && file_text != null) { + String context = context_text.getText().trim(); + String file = file_text.getText().trim(); + btn.setEnabled(context.length() > 0 && file.length() > 0); + } + if (relocate_button != null) { + boolean reloc = relocate_button.getSelection(); + addr_text.setEnabled(reloc); + size_text.setEnabled(reloc); + offs_text.setEnabled(reloc); + } + } + + @Override + protected void okPressed() { + try { + getData(); + } + catch (Throwable x) { + MessageBox mb = new MessageBox(getShell(), SWT.ICON_ERROR | SWT.OK); + mb.setText("Invalid data"); //$NON-NLS-1$ + mb.setMessage(TCFModel.getErrorMessage(x, true)); + mb.open(); + return; + } + super.okPressed(); + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/FileSystemBrowserControl.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/FileSystemBrowserControl.java new file mode 100644 index 000000000..ce8da20bf --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/FileSystemBrowserControl.java @@ -0,0 +1,515 @@ +/******************************************************************************* + * Copyright (c) 2011, 2013 Wind River Systems, Inc. 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.internal.debug.ui.launch; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.core.runtime.Path; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.tcf.protocol.IChannel; +import org.eclipse.tcf.protocol.IChannel.IChannelListener; +import org.eclipse.tcf.protocol.IPeer; +import org.eclipse.tcf.protocol.IToken; +import org.eclipse.tcf.protocol.Protocol; +import org.eclipse.tcf.services.IFileSystem; +import org.eclipse.tcf.services.IFileSystem.DirEntry; +import org.eclipse.tcf.services.IFileSystem.FileSystemException; +import org.eclipse.tcf.services.IFileSystem.IFileHandle; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.PlatformUI; + +public class FileSystemBrowserControl { + + static class FileInfo { + String name; + String fullname; + boolean isDir; + FileInfo[] children; + Throwable children_error; + int index; + boolean children_pending; + FileInfo parent; + } + + private Tree fileTree; + private Display fDisplay; + private IPeer fPeer; + private final FileInfo fRootInfo = new FileInfo(); + private IChannel fChannel; + private IFileSystem fFileSystem; + private String fFileToSelect; + private LinkedList<String> fPathToSelect; + private FileInfo fLastSelectedFileInfo; + private final boolean fDirectoriesOnly; + + public FileSystemBrowserControl(Composite parent, boolean directoriesOnly) { + fDirectoriesOnly = directoriesOnly; + fDisplay = parent.getDisplay(); + parent.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + handleDispose(); + } + }); + createFileListArea(parent); + } + + public void setInput(IPeer peer) { + if (peer == fPeer) { + return; + } + if (fPeer != null) { + Protocol.invokeAndWait(new Runnable() { + public void run() { + disconnectPeer(); + } + }); + } + fileTree.setItemCount(0); + fRootInfo.children = null; + fPeer = peer; + if (fPeer != null) { + Protocol.invokeAndWait(new Runnable() { + public void run() { + connectPeer(); + } + }); + } + } + + public Tree getTree() { + return fileTree; + } + + private void createFileListArea(Composite parent) { + Font font = parent.getFont(); + Composite composite = new Composite(parent, SWT.NONE); + composite.setFont(font); + GridLayout layout = new GridLayout(1, false); + layout.marginWidth = 0; + layout.marginHeight = 0; + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true)); + + fileTree = new Tree(composite, SWT.VIRTUAL | SWT.BORDER | SWT.SINGLE); + GridData gd = new GridData(GridData.FILL_BOTH); + gd.minimumHeight = 300; + gd.minimumWidth = 350; + fileTree.setLayoutData(gd); + fileTree.setFont(font); + fileTree.addListener(SWT.SetData, new Listener() { + public void handleEvent(Event event) { + TreeItem item = (TreeItem)event.item; + FileInfo info = findFileInfo(item); + if (info == null) { + updateItems(item.getParentItem(), false); + } + else { + fillItem(item, info); + } + } + }); + } + + private void handleDispose() { + Protocol.invokeAndWait(new Runnable() { + public void run() { + disconnectPeer(); + fFileSystem = null; + fDisplay = null; + } + }); + } + + protected void disconnectPeer() { + if (fChannel != null && fChannel.getState() != IChannel.STATE_CLOSED) { + fChannel.close(); + } + } + + protected void connectPeer() { + final IChannel channel = fPeer.openChannel(); + fChannel = channel; + fFileSystem = null; + channel.addChannelListener(new IChannelListener() { + public void congestionLevel(int level) { + } + public void onChannelClosed(final Throwable error) { + if (fChannel != channel) return; + fChannel = null; + if (fDisplay != null) { + fDisplay.asyncExec(new Runnable() { + public void run() { + if (fRootInfo.children_pending) return; + fRootInfo.children = null; + fRootInfo.children_error = error; + updateItems(fRootInfo); + } + }); + } + } + public void onChannelOpened() { + if (fChannel != channel) return; + fFileSystem = fChannel.getRemoteService(IFileSystem.class); + if (fFileSystem != null) { + if (fFileToSelect != null && fFileToSelect.length() > 0) { + final LinkedList<String> filePath = new LinkedList<String>(); + filePath.addAll(Arrays.asList(fFileToSelect.split("[/\\\\]", -1))); + if (fFileToSelect.charAt(0) == '/') { + filePath.set(0, "/"); + } + fPathToSelect = filePath; + fLastSelectedFileInfo = fRootInfo; + } + } + if (fDisplay != null) { + fDisplay.asyncExec(new Runnable() { + public void run() { + if (fRootInfo.children_pending) return; + fRootInfo.children = null; + fRootInfo.children_error = null; + updateItems(fRootInfo); + } + }); + } + } + }); + } + + private void updateItems(TreeItem parent_item, boolean reload) { + final FileInfo parent_info = findFileInfo(parent_item); + if (parent_info == null) { + parent_item.setText("Invalid"); + } + else { + if (reload && parent_info.children_error != null) { + loadChildren(parent_info); + } + fDisplay.asyncExec(new Runnable() { + public void run() { + updateItems(parent_info); + } + }); + } + } + + private void updateItems(final FileInfo parent) { + if (fDisplay == null) return; + assert Thread.currentThread() == fDisplay.getThread(); + TreeItem[] items = null; + boolean expanded = true; + if (parent.children == null || parent.children_error != null) { + if (parent == fRootInfo) { + fileTree.setItemCount(1); + items = fileTree.getItems(); + } + else { + TreeItem item = findItem(parent); + if (item == null) return; + expanded = item.getExpanded(); + item.setItemCount(1); + items = item.getItems(); + } + assert items.length == 1; + items[0].removeAll(); + if (parent.children_pending) { + items[0].setForeground(fDisplay.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); + items[0].setText("Pending..."); + } + else if (parent.children_error != null) { + String msg = parent.children_error.getMessage(); + if (msg == null) msg = parent.children_error.getClass().getName(); + else msg = msg.replace('\n', ' '); + items[0].setForeground(fDisplay.getSystemColor(SWT.COLOR_RED)); + items[0].setText(msg); + items[0].setImage((Image) null); + } + else if (expanded) { + loadChildren(parent); + items[0].setForeground(fDisplay.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); + items[0].setText("Pending..."); + } + else { + items[0].setText(""); + } + } + else { + FileInfo[] arr = parent.children; + if (parent == fRootInfo) { + fileTree.setItemCount(arr.length); + items = fileTree.getItems(); + } + else { + TreeItem item = findItem(parent); + if (item == null) return; + expanded = item.getExpanded(); + item.setItemCount(expanded ? arr.length : 1); + items = item.getItems(); + } + if (expanded) { + assert items.length == arr.length; + for (int i = 0; i < items.length; i++) fillItem(items[i], arr[i]); + expandSelect(); + } + else { + items[0].setText(""); + } + } + } + + private void expandSelect() { + if (fPathToSelect == null) return; + if (fPathToSelect.isEmpty()) { + fPathToSelect = null; + fFileToSelect = null; + return; + } + do { + String name = fPathToSelect.getFirst(); + if (name.length() == 0) { + fPathToSelect.removeFirst(); + continue; + } + FileInfo info = findFileInfo(fLastSelectedFileInfo, name); + if (info == null) break; + TreeItem item = findItem(info); + if (item == null) break; + fPathToSelect.removeFirst(); + if (fPathToSelect.isEmpty()) { + fileTree.setSelection(item); + fileTree.showItem(item); + } else { + item.setExpanded(true); + fileTree.showItem(item); + } + fLastSelectedFileInfo = info; + } while (!fPathToSelect.isEmpty()); + } + + private void loadChildren(final FileInfo parent) { + assert Thread.currentThread() == fDisplay.getThread(); + if (parent.children_pending) return; + assert parent.children == null; + parent.children_pending = true; + parent.children_error = null; + Protocol.invokeLater(new Runnable() { + public void run() { + final IFileSystem fs = fFileSystem; + if (fs == null || !canHaveChildren(parent)) { + doneLoadChildren(parent, null, new FileInfo[0]); + return; + } + if (parent.fullname == null) { + fs.roots(new IFileSystem.DoneRoots() { + public void doneRoots(IToken token, FileSystemException error, DirEntry[] entries) { + if (error != null) { + doneLoadChildren(parent, error, null); + } else { + final List<FileInfo> fileInfos = new ArrayList<FileInfo>(entries.length); + for (DirEntry entry : entries) { + FileInfo info = new FileInfo(); + info.parent = parent; + String name = entry.filename; + int length = name.length(); + if (length > 1 && (name.endsWith("\\") || name.endsWith("/"))) { + name = name.substring(0, length - 1); + } + info.name = name; + info.fullname = entry.longname != null ? entry.longname : entry.filename; + info.isDir = entry.attrs != null ? entry.attrs.isDirectory() : false; + if (!fDirectoriesOnly || info.isDir) { + fileInfos.add(info); + } + } + doneLoadChildren(parent, null, fileInfos.toArray(new FileInfo[fileInfos.size()])); + } + } + }); + return; + } + fs.opendir(parent.fullname, new IFileSystem.DoneOpen() { + final List<FileInfo> fileInfos = new ArrayList<FileInfo>(); + public void doneOpen(IToken token, FileSystemException error, final IFileHandle handle) { + if (error != null) { + doneLoadChildren(parent, error, null); + return; + } + fs.readdir(handle, new IFileSystem.DoneReadDir() { + public void doneReadDir(IToken token, FileSystemException error, DirEntry[] entries, boolean eof) { + if (entries != null) { + for (DirEntry entry : entries) { + FileInfo info = new FileInfo(); + info.parent = parent; + info.name = entry.filename; + info.fullname = entry.longname != null ? entry.longname : (new Path(parent.fullname).append(info.name).toString()); + info.isDir = entry.attrs != null ? entry.attrs.isDirectory() : false; + if (!fDirectoriesOnly || info.isDir) { + fileInfos.add(info); + } + } + } + if (error != null || eof) { + fs.close(handle, new IFileSystem.DoneClose() { + public void doneClose(IToken token, FileSystemException error) { + // ignore error + } + }); + int size = fileInfos.size(); + if (size == 0 && error != null) { + doneLoadChildren(parent, error, null); + } else { + doneLoadChildren(parent, null, fileInfos.toArray(new FileInfo[size])); + } + } else { + fs.readdir(handle, this); + } + } + }); + } + }); + } + }); + } + + private void doneLoadChildren(final FileInfo parent, final Throwable error, final FileInfo[] children) { + assert Protocol.isDispatchThread(); + assert error == null || children == null; + if (fDisplay == null) return; + Arrays.sort(children, new Comparator<FileInfo>() { + public int compare(FileInfo o1, FileInfo o2) { + if (o1.isDir == o2.isDir) + return o1.name.compareTo(o2.name); + if (o1.isDir) return 1; + return -1; + }}); + int i = 0; + for (FileInfo fileInfo : children) { + fileInfo.index = i++; + } + fDisplay.asyncExec(new Runnable() { + public void run() { + assert parent.children_pending; + assert parent.children == null; + parent.children_pending = false; + parent.children = children; + parent.children_error = error; + updateItems(parent); + } + }); + } + + public FileInfo findFileInfo(TreeItem item) { + assert Thread.currentThread() == fDisplay.getThread(); + if (item == null) return fRootInfo ; + TreeItem parent = item.getParentItem(); + FileInfo info = findFileInfo(parent); + if (info == null) return null; + if (info.children == null) return null; + if (info.children_error != null) return null; + int i = parent == null ? fileTree.indexOf(item) : parent.indexOf(item); + if (i < 0 || i >= info.children.length) return null; + assert info.children[i].index == i; + return info.children[i]; + } + + private FileInfo findFileInfo(FileInfo parent, String name) { + assert Thread.currentThread() == fDisplay.getThread(); + if (name == null) return fRootInfo; + if (name.equals(parent.name)) return parent; + FileInfo[] childInfos = parent.children; + if (childInfos != null) { + for (FileInfo fileInfo : childInfos) { + FileInfo found = findFileInfo(fileInfo, name); + if (found != null) { + return found; + } + } + } + return null; + } + + private TreeItem findItem(FileInfo info) { + if (info == null) return null; + assert info.parent != null; + if (info.parent == fRootInfo) { + int n = fileTree.getItemCount(); + if (info.index >= n) return null; + return fileTree.getItem(info.index); + } + TreeItem i = findItem(info.parent); + if (i == null) return null; + int n = i.getItemCount(); + if (info.index >= n) return null; + return i.getItem(info.index); + } + + private void fillItem(TreeItem item, FileInfo info) { + assert Thread.currentThread() == fDisplay.getThread(); + Object data = item.getData("TCFContextInfo"); + if (data != null && data != info) item.removeAll(); + item.setData("TCFContextInfo", info); + String text = info.name != null ? info.name : info.fullname; + item.setText(text); + item.setForeground(fDisplay.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); + item.setImage(getImage(info)); + if (!canHaveChildren(info)) item.setItemCount(0); + else if (info.children == null || info.children_error != null) item.setItemCount(1); + else item.setItemCount(info.children.length); + } + + private boolean canHaveChildren(FileInfo info) { + return info.isDir || info == fRootInfo; + } + + private Image getImage(FileInfo info) { + if (info.isDir) { + return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER); + } else { + return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE); + } + } + + public void setInitialSelection(final String filename) { + fPathToSelect = null; + Protocol.invokeLater(new Runnable() { + public void run() { + fFileToSelect = filename; + } + }); + } + + public FileInfo getSelection() { + if (fileTree != null) { + TreeItem[] items = fileTree.getSelection(); + if (items.length > 0) { + FileInfo info = findFileInfo(items[0]); + return info; + } + } + return null; + } + +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/PeerListControl.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/PeerListControl.java new file mode 100644 index 000000000..82f7aadb8 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/PeerListControl.java @@ -0,0 +1,743 @@ +/******************************************************************************* + * Copyright (c) 2011, 2013 Wind River Systems, Inc. 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.internal.debug.ui.launch; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import org.eclipse.core.runtime.ListenerList; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.TreeEvent; +import org.eclipse.swt.events.TreeListener; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeColumn; +import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.tcf.internal.debug.launch.TCFUserDefPeer; +import org.eclipse.tcf.internal.debug.ui.Activator; +import org.eclipse.tcf.internal.debug.ui.ImageCache; +import org.eclipse.tcf.internal.debug.ui.model.TCFModel; +import org.eclipse.tcf.protocol.IChannel; +import org.eclipse.tcf.protocol.IPeer; +import org.eclipse.tcf.protocol.Protocol; +import org.eclipse.tcf.services.ILocator; + +// Cloned from TCFTargetTab +public class PeerListControl implements ISelectionProvider { + + private Tree peer_tree; + private final PeerInfo peer_info = new PeerInfo(); + private Display display; + private final ListenerList selection_listeners = new ListenerList(ListenerList.IDENTITY); + private String initial_peer_id; + + public static class PeerInfo { + public String id; + public IPeer peer; + + PeerInfo parent; + Map<String,String> attrs; + PeerInfo[] children; + boolean children_pending; + Throwable children_error; + IChannel channel; + ILocator locator; + LocatorListener listener; + Runnable item_update; + } + + private class LocatorListener implements ILocator.LocatorListener { + + private final PeerInfo parent; + + LocatorListener(PeerInfo parent) { + this.parent = parent; + } + + public void peerAdded(final IPeer peer) { + if (display == null) return; + final String id = peer.getID(); + final HashMap<String,String> attrs = new HashMap<String,String>(peer.getAttributes()); + display.asyncExec(new Runnable() { + public void run() { + if (parent.children_error != null) return; + PeerInfo[] arr = parent.children; + for (PeerInfo p : arr) assert !p.id.equals(id); + PeerInfo[] buf = new PeerInfo[arr.length + 1]; + System.arraycopy(arr, 0, buf, 0, arr.length); + PeerInfo info = new PeerInfo(); + info.parent = parent; + info.id = id; + info.attrs = attrs; + info.peer = peer; + buf[arr.length] = info; + parent.children = buf; + updateItems(parent); + } + }); + } + + public void peerChanged(final IPeer peer) { + if (display == null) return; + final String id = peer.getID(); + final HashMap<String,String> attrs = new HashMap<String,String>(peer.getAttributes()); + display.asyncExec(new Runnable() { + public void run() { + if (parent.children_error != null) return; + PeerInfo[] arr = parent.children; + for (int i = 0; i < arr.length; i++) { + if (arr[i].id.equals(id)) { + arr[i].attrs = attrs; + arr[i].peer = peer; + updateItems(parent); + } + } + } + }); + } + + public void peerRemoved(final String id) { + if (display == null) return; + display.asyncExec(new Runnable() { + public void run() { + if (parent.children_error != null) return; + PeerInfo[] arr = parent.children; + PeerInfo[] buf = new PeerInfo[arr.length - 1]; + int j = 0; + for (int i = 0; i < arr.length; i++) { + if (arr[i].id.equals(id)) { + final PeerInfo info = arr[i]; + Protocol.invokeLater(new Runnable() { + public void run() { + disconnectPeer(info); + } + }); + } + else { + buf[j++] = arr[i]; + } + } + parent.children = buf; + updateItems(parent); + } + }); + } + + public void peerHeartBeat(final String id) { + if (display == null) return; + display.asyncExec(new Runnable() { + public void run() { + if (parent.children_error != null) return; + PeerInfo[] arr = parent.children; + for (int i = 0; i < arr.length; i++) { + if (arr[i].id.equals(id)) { + if (arr[i].children_error != null) { + TreeItem item = findItem(arr[i]); + boolean visible = item != null; + while (visible && item != null) { + if (!item.getExpanded()) visible = false; + item = item.getParentItem(); + } + if (visible) loadChildren(arr[i]); + } + break; + } + } + } + }); + } + } + + public PeerListControl(Composite parent) { + display = parent.getDisplay(); + parent.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + handleDispose(); + } + }); + loadChildren(peer_info); + createPeerListArea(parent); + } + + public void setInitialSelection(String id) { + if (id == null) return; + if (id.length() == 0) return; + PeerInfo info = findPeerInfo(id); + if (info != null) { + setSelection(new StructuredSelection(info)); + fireSelectionChangedEvent(); + onPeerSelected(info); + } + else { + String p = id; + for (;;) { + int i = p.lastIndexOf('/'); + if (i < 0) break; + p = p.substring(0, i); + TreeItem item = findItem(p); + if (item != null) item.setExpanded(true); + } + initial_peer_id = id; + } + } + + public Tree getTree() { + return peer_tree; + } + + private void createPeerListArea(Composite parent) { + Font font = parent.getFont(); + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + composite.setFont(font); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1)); + + peer_tree = new Tree(composite, SWT.VIRTUAL | SWT.BORDER | SWT.SINGLE); + GridData gd = new GridData(GridData.FILL_BOTH); + gd.minimumHeight = 150; + gd.minimumWidth = 470; + peer_tree.setLayoutData(gd); + + for (int i = 0; i < 6; i++) { + TreeColumn column = new TreeColumn(peer_tree, SWT.LEAD, i); + column.setMoveable(true); + switch (i) { + case 0: + column.setText("Name"); + column.setWidth(160); + break; + case 1: + column.setText("OS"); + column.setWidth(100); + break; + case 2: + column.setText("User"); + column.setWidth(100); + break; + case 3: + column.setText("Transport"); + column.setWidth(60); + break; + case 4: + column.setText("Host"); + column.setWidth(100); + break; + case 5: + column.setText("Port"); + column.setWidth(40); + break; + } + } + + peer_tree.setHeaderVisible(true); + peer_tree.setFont(font); + peer_tree.addListener(SWT.SetData, new Listener() { + @Override + public void handleEvent(Event event) { + TreeItem item = (TreeItem)event.item; + PeerInfo info = findPeerInfo(item); + if (info == null) { + updateItems(item.getParentItem(), false); + } + else { + fillItem(item, info); + onPeerListChanged(); + } + } + }); + peer_tree.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetDefaultSelected(SelectionEvent e) { + TreeItem[] selections = peer_tree.getSelection(); + if (selections.length == 0) return; + final PeerInfo info = findPeerInfo(selections[0]); + if (info == null) return; + new PeerPropsDialog(peer_tree.getShell(), getImage(info), info.attrs, + info.peer instanceof TCFUserDefPeer).open(); + if (!(info.peer instanceof TCFUserDefPeer)) return; + Protocol.invokeLater(new Runnable() { + public void run() { + ((TCFUserDefPeer)info.peer).updateAttributes(info.attrs); + TCFUserDefPeer.savePeers(); + } + }); + } + @Override + public void widgetSelected(SelectionEvent e) { + fireSelectionChangedEvent(); + TreeItem[] selections = peer_tree.getSelection(); + if (selections.length > 0) { + assert selections.length == 1; + PeerInfo info = findPeerInfo(selections[0]); + if (info != null) { + initial_peer_id = null; + onPeerSelected(info); + } + } + onPeerListChanged(); + } + }); + peer_tree.addTreeListener(new TreeListener() { + @Override + public void treeCollapsed(TreeEvent e) { + updateItems((TreeItem)e.item, false); + } + @Override + public void treeExpanded(TreeEvent e) { + updateItems((TreeItem)e.item, true); + } + }); + } + + private void handleDispose() { + Protocol.invokeAndWait(new Runnable() { + public void run() { + disconnectPeer(peer_info); + display = null; + } + }); + } + + private void disconnectPeer(final PeerInfo info) { + assert Protocol.isDispatchThread(); + if (info.children != null) { + for (PeerInfo p : info.children) disconnectPeer(p); + } + if (info.listener != null) { + info.locator.removeListener(info.listener); + info.listener = null; + info.locator = null; + } + if (info.channel != null) { + info.channel.close(); + } + } + + private boolean canHaveChildren(PeerInfo parent) { + return parent == peer_info || parent.attrs.get(IPeer.ATTR_PROXY) != null; + } + + private void loadChildren(final PeerInfo parent) { + assert Thread.currentThread() == display.getThread(); + if (parent.children_pending) return; + assert parent.children == null; + parent.children_pending = true; + parent.children_error = null; + Protocol.invokeAndWait(new Runnable() { + public void run() { + assert parent.listener == null; + assert parent.channel == null; + if (!canHaveChildren(parent)) { + doneLoadChildren(parent, null, new PeerInfo[0]); + } + else if (parent == peer_info) { + peer_info.locator = Protocol.getLocator(); + doneLoadChildren(parent, null, createLocatorListener(peer_info)); + } + else { + final IChannel channel = parent.peer.openChannel(); + parent.channel = channel; + parent.channel.addChannelListener(new IChannel.IChannelListener() { + boolean opened = false; + boolean closed = false; + public void congestionLevel(int level) { + } + public void onChannelClosed(final Throwable error) { + assert !closed; + if (parent.channel != channel) return; + if (!opened) { + doneLoadChildren(parent, error, null); + } + else { + if (display != null) { + display.asyncExec(new Runnable() { + public void run() { + if (parent.children_pending) return; + parent.children = null; + parent.children_error = error; + updateItems(parent); + } + }); + } + } + closed = true; + parent.channel = null; + parent.locator = null; + parent.listener = null; + } + public void onChannelOpened() { + assert !opened; + assert !closed; + if (parent.channel != channel) return; + opened = true; + parent.locator = parent.channel.getRemoteService(ILocator.class); + if (parent.locator == null) { + parent.channel.terminate(new Exception("Service not supported: " + ILocator.NAME)); + } + else { + doneLoadChildren(parent, null, createLocatorListener(parent)); + } + } + }); + } + } + }); + } + + private PeerInfo[] createLocatorListener(PeerInfo peer) { + assert Protocol.isDispatchThread(); + Map<String,IPeer> map = peer.locator.getPeers(); + PeerInfo[] buf = new PeerInfo[map.size()]; + int n = 0; + for (IPeer p : map.values()) { + PeerInfo info = new PeerInfo(); + info.parent = peer; + info.id = p.getID(); + info.attrs = new HashMap<String,String>(p.getAttributes()); + info.peer = p; + buf[n++] = info; + } + peer.listener = new LocatorListener(peer); + peer.locator.addListener(peer.listener); + return buf; + } + + private void doneLoadChildren(final PeerInfo parent, final Throwable error, final PeerInfo[] children) { + assert Protocol.isDispatchThread(); + assert error == null || children == null; + if (display == null) return; + display.asyncExec(new Runnable() { + public void run() { + assert parent.children_pending; + assert parent.children == null; + parent.children_pending = false; + parent.children = children; + parent.children_error = error; + updateItems(parent); + } + }); + } + + private ArrayList<PeerInfo> filterPeerList(PeerInfo parent, boolean expanded) { + ArrayList<PeerInfo> lst = new ArrayList<PeerInfo>(); + HashMap<String,PeerInfo> local_agents = new HashMap<String,PeerInfo>(); + HashSet<String> ids = new HashSet<String>(); + for (PeerInfo p : parent.children) { + String id = p.attrs.get(IPeer.ATTR_AGENT_ID); + if (id == null) continue; + if (!"TCP".equals(p.attrs.get(IPeer.ATTR_TRANSPORT_NAME))) continue; + if (!"127.0.0.1".equals(p.attrs.get(IPeer.ATTR_IP_HOST))) continue; + local_agents.put(id, p); + ids.add(p.id); + } + for (PeerInfo p : parent.children) { + PeerInfo i = local_agents.get(p.attrs.get(IPeer.ATTR_AGENT_ID)); + if (i != null && i != p) continue; + lst.add(p); + } + if (parent != peer_info && expanded) { + for (PeerInfo p : peer_info.children) { + if (p.peer instanceof TCFUserDefPeer && !ids.contains(p.id)) { + PeerInfo x = new PeerInfo(); + x.parent = parent; + x.id = p.id; + x.attrs = p.attrs; + x.peer = p.peer; + ids.add(x.id); + lst.add(x); + } + } + } + return lst; + } + + private void updateItems(TreeItem parent_item, boolean reload) { + final PeerInfo parent_info = findPeerInfo(parent_item); + if (parent_info == null) { + parent_item.setText("Invalid"); + } + else { + if (reload && parent_info.children_error != null) { + loadChildren(parent_info); + } + display.asyncExec(new Runnable() { + public void run() { + updateItems(parent_info); + } + }); + } + } + + private void updateItems(final PeerInfo parent) { + if (display == null) return; + assert Thread.currentThread() == display.getThread(); + parent.item_update = new Runnable() { + public void run() { + if (display == null) return; + if (parent.item_update != this) return; + if (Thread.currentThread() != display.getThread()) { + display.asyncExec(this); + return; + } + parent.item_update = null; + TreeItem[] items = null; + boolean expanded = true; + if (parent.children == null || parent.children_error != null) { + if (parent == peer_info) { + peer_tree.setItemCount(1); + items = peer_tree.getItems(); + } + else { + TreeItem item = findItem(parent); + if (item == null) return; + expanded = item.getExpanded(); + item.setItemCount(1); + items = item.getItems(); + } + assert items.length == 1; + if (parent.children_pending) { + items[0].setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); + fillItem(items[0], "Connecting..."); + } + else if (parent.children_error != null) { + String msg = TCFModel.getErrorMessage(parent.children_error, false); + items[0].setForeground(display.getSystemColor(SWT.COLOR_RED)); + fillItem(items[0], msg); + } + else if (expanded) { + loadChildren(parent); + items[0].setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); + fillItem(items[0], "Connecting..."); + } + else { + Protocol.invokeAndWait(new Runnable() { + public void run() { + disconnectPeer(parent); + } + }); + fillItem(items[0], ""); + } + } + else { + ArrayList<PeerInfo> lst = null; + if (parent == peer_info) { + lst = filterPeerList(parent, expanded); + peer_tree.setItemCount(lst.size() > 0 ? lst.size() : 1); + items = peer_tree.getItems(); + } + else { + TreeItem item = findItem(parent); + if (item == null) return; + expanded = item.getExpanded(); + lst = filterPeerList(parent, expanded); + item.setItemCount(expanded && lst.size() > 0 ? lst.size() : 1); + items = item.getItems(); + } + if (expanded && lst.size() > 0) { + assert items.length == lst.size(); + for (int i = 0; i < items.length; i++) fillItem(items[i], lst.get(i)); + } + else if (expanded) { + fillItem(items[0], "No peers"); + } + else { + Protocol.invokeAndWait(new Runnable() { + public void run() { + disconnectPeer(parent); + } + }); + fillItem(items[0], ""); + } + } + onPeerListChanged(); + if (initial_peer_id != null) { + setInitialSelection(initial_peer_id); + } + } + }; + if (parent.children_pending) parent.item_update.run(); + else Protocol.invokeLater(200, parent.item_update); + } + + public TreeItem findItem(String path) { + assert Thread.currentThread() == display.getThread(); + if (path == null) return null; + int z = path.lastIndexOf('/'); + if (z < 0) { + int n = peer_tree.getItemCount(); + for (int i = 0; i < n; i++) { + TreeItem x = peer_tree.getItem(i); + PeerInfo p = (PeerInfo)x.getData("TCFPeerInfo"); + if (p != null && p.id.equals(path)) return x; + } + } + else { + TreeItem y = findItem(path.substring(0, z)); + if (y == null) return null; + String id = path.substring(z + 1); + int n = y.getItemCount(); + for (int i = 0; i < n; i++) { + TreeItem x = y.getItem(i); + PeerInfo p = (PeerInfo)x.getData("TCFPeerInfo"); + if (p != null && p.id.equals(id)) return x; + } + } + return null; + } + + public TreeItem findItem(PeerInfo info) { + if (info == null) return null; + assert info.parent != null; + if (info.parent == peer_info) { + int n = peer_tree.getItemCount(); + for (int i = 0; i < n; i++) { + TreeItem x = peer_tree.getItem(i); + if (x.getData("TCFPeerInfo") == info) return x; + } + } + else { + TreeItem y = findItem(info.parent); + if (y == null) return null; + int n = y.getItemCount(); + for (int i = 0; i < n; i++) { + TreeItem x = y.getItem(i); + if (x.getData("TCFPeerInfo") == info) return x; + } + } + return null; + } + + public String getPath(PeerInfo info) { + if (info == peer_info) return ""; + if (info.parent == peer_info) return info.id; + return getPath(info.parent) + "/" + info.id; + } + + public PeerInfo findPeerInfo(String path) { + TreeItem i = findItem(path); + if (i == null) return null; + return (PeerInfo)i.getData("TCFPeerInfo"); + } + + private PeerInfo findPeerInfo(TreeItem item) { + assert Thread.currentThread() == display.getThread(); + if (item == null) return peer_info; + return (PeerInfo)item.getData("TCFPeerInfo"); + } + + private void fillItem(TreeItem item, PeerInfo info) { + assert Thread.currentThread() == display.getThread(); + Object data = item.getData("TCFPeerInfo"); + if (data != null && data != info) item.removeAll(); + item.setData("TCFPeerInfo", info); + String text[] = new String[6]; + text[0] = info.attrs.get(IPeer.ATTR_NAME); + text[1] = info.attrs.get(IPeer.ATTR_OS_NAME); + text[2] = info.attrs.get(IPeer.ATTR_USER_NAME); + text[3] = info.attrs.get(IPeer.ATTR_TRANSPORT_NAME); + text[4] = info.attrs.get(IPeer.ATTR_IP_HOST); + text[5] = info.attrs.get(IPeer.ATTR_IP_PORT); + for (int i = 0; i < text.length; i++) { + if (text[i] == null) text[i] = ""; + } + item.setText(text); + item.setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); + item.setImage(getImage(info)); + if (!canHaveChildren(info)) item.setItemCount(0); + else if (info.children == null || info.children_error != null) item.setItemCount(1); + else item.setItemCount(info.children.length); + } + + private void fillItem(TreeItem item, String text) { + item.setText(text); + item.setData("TCFPeerInfo", null); + int n = peer_tree.getColumnCount(); + for (int i = 1; i < n; i++) item.setText(i, ""); + item.setImage((Image)null); + item.removeAll(); + } + + private Image getImage(PeerInfo info) { + return ImageCache.getImage(ImageCache.IMG_TARGET_TAB); + } + + public void addSelectionChangedListener(ISelectionChangedListener listener) { + selection_listeners.add(listener); + } + + public ISelection getSelection() { + TreeItem[] items = peer_tree.getSelection(); + PeerInfo[] peers = new PeerInfo[items.length]; + int i = 0; + for (TreeItem item : items) { + peers[i++] = findPeerInfo(item); + } + return new StructuredSelection(peers); + } + + public void removeSelectionChangedListener(ISelectionChangedListener listener) { + selection_listeners.remove(listener); + } + + public void setSelection(ISelection selection) { + peer_tree.deselectAll(); + if (selection instanceof IStructuredSelection) { + Object[] elements = ((IStructuredSelection) selection).toArray(); + for (Object object : elements) { + if (object instanceof PeerInfo) { + TreeItem item = findItem((PeerInfo) object); + if (item != null) { + peer_tree.select(item); + } + } + } + } + } + + private void fireSelectionChangedEvent() { + SelectionChangedEvent event = new SelectionChangedEvent(this, getSelection()); + Object[] listeners = selection_listeners.getListeners(); + for (Object listener : listeners) { + try { + ((ISelectionChangedListener) listener).selectionChanged(event); + } + catch (Exception e) { + Activator.log(e); + } + } + } + + protected void onPeerListChanged() { + } + + protected void onPeerSelected(PeerInfo info) { + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/RemoteFileSelectionDialog.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/RemoteFileSelectionDialog.java new file mode 100644 index 000000000..ca8b5e949 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/RemoteFileSelectionDialog.java @@ -0,0 +1,170 @@ +/******************************************************************************* + * Copyright (c) 2011, 2013 Wind River Systems, Inc. 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.internal.debug.ui.launch; + +import org.eclipse.core.runtime.Path; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.window.IShellProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusAdapter; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +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.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.tcf.internal.debug.ui.launch.FileSystemBrowserControl.FileInfo; +import org.eclipse.tcf.protocol.IPeer; + +/** + * Dialog to select a remote file. + */ +public class RemoteFileSelectionDialog extends Dialog { + + private String fSelection; + private FileSystemBrowserControl fFileList; + private IPeer fPeer; + private boolean fForSave; + private Text fFileNameText; + + public RemoteFileSelectionDialog(IShellProvider parentShell, int style) { + super(parentShell); + setShellStyle(getShellStyle() | SWT.RESIZE); + fForSave = (style & SWT.SAVE) != 0; + } + + public void setPeer(IPeer peer) { + fPeer = peer; + if (fFileList != null) { + fFileList.setInput(peer); + } + } + + public void setSelection(String fileSelection) { + fSelection = fileSelection; + } + + public String getSelection() { + return fSelection; + } + + @Override + protected void configureShell(Shell newShell) { + newShell.setText("Select File"); + super.configureShell(newShell); + } + + @Override + protected Control createContents(Composite parent) { + Control control = super.createContents(parent); + updateButtonState(); + return control; + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + fFileList = new FileSystemBrowserControl(composite, false); + fFileList.getTree().addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + FileInfo contextInfo = fFileList.findFileInfo((TreeItem) e.item); + if (contextInfo != null) { + handleFileSelected(contextInfo); + } + } + @Override + public void widgetDefaultSelected(SelectionEvent e) { + widgetSelected(e); + if (getButton(IDialogConstants.OK_ID).isEnabled()) { + buttonPressed(IDialogConstants.OK_ID); + } + } + }); + + if (fForSave) { + Composite fileNameComp = new Composite(composite, SWT.NONE); + fileNameComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + GridLayout layout = new GridLayout(2, false); + layout.marginWidth = 0; + fileNameComp.setLayout(layout); + new Label(fileNameComp, SWT.NONE).setText("File Name:"); + fFileNameText = new Text(fileNameComp, SWT.BORDER); + fFileNameText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + fFileNameText.addFocusListener(new FocusAdapter() { + @Override + public void focusLost(FocusEvent e) { + handleFileNameChanged(); + } + }); + } + + if (fSelection != null) { + fFileList.setInitialSelection(fSelection); + if (fFileNameText != null) { + String basename = new Path(fSelection).lastSegment(); + if (basename != null) { + fFileNameText.setText(basename); + } + } + } + if (fPeer != null) { + fFileList.setInput(fPeer); + } + return composite; + } + + private void updateButtonState() { + boolean enabled = fSelection != null; + if (enabled && fForSave) { + enabled = fFileNameText.getText().trim().length() > 0; + } + getButton(IDialogConstants.OK_ID).setEnabled(enabled); + } + + protected void handleFileNameChanged() { + if (fSelection != null) { + fSelection = new Path(fSelection).removeLastSegments(1).append(fFileNameText.getText().trim()).toString(); + updateButtonState(); + } + } + + protected void handleFileSelected(FileInfo fileInfo) { + if (fileInfo.isDir) { + if (fForSave) { + String basename = fFileNameText.getText().trim(); + if (basename.length() > 0) { + fSelection = new Path(fileInfo.fullname).append(basename).toString(); + } else { + fSelection = fileInfo.fullname; + } + } else { + fSelection = null; + } + } else { + fSelection = fileInfo.fullname; + if (fFileNameText != null) { + String basename = new Path(fSelection).lastSegment(); + if (basename != null) { + fFileNameText.setText(basename); + } + } + } + updateButtonState(); + } + +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFDownloadTab.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFDownloadTab.java new file mode 100644 index 000000000..e31dd31a1 --- /dev/null +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFDownloadTab.java @@ -0,0 +1,361 @@ +/******************************************************************************* + * Copyright (c) 2013 Xilinx, Inc. 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: + * Xilinx - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.internal.debug.ui.launch; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; +import org.eclipse.debug.ui.ILaunchConfigurationTab; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.tcf.internal.debug.launch.TCFLaunchDelegate; +import org.eclipse.tcf.internal.debug.ui.Activator; +import org.eclipse.tcf.internal.debug.ui.ImageCache; +import org.eclipse.tcf.protocol.JSON; +import org.eclipse.tcf.util.TCFTask; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.PlatformUI; + +public class TCFDownloadTab extends AbstractLaunchConfigurationTab { + + private TableViewer viewer; + private Button button_add; + private Button button_edit; + private Button button_remove; + private MenuItem item_add; + private MenuItem item_edit; + private MenuItem item_remove; + + private static final String[] column_ids = { + TCFLaunchDelegate.FILES_CONTEXT_FULL_NAME, + TCFLaunchDelegate.FILES_FILE_NAME, + }; + + private static final int[] column_size = { + 300, + 400, + }; + + private final List<Map<String,Object>> list = new ArrayList<Map<String,Object>>(); + + private static final String TAB_ID = "org.eclipse.tcf.launch.downloadTab"; //$NON-NLS-1$ + + private class FileListContentProvider implements IStructuredContentProvider { + + public Object[] getElements(Object input) { + return list.toArray(new Map[list.size()]); + } + + public void inputChanged(Viewer viewer, Object old_input, Object new_input) { + } + + public void dispose() { + } + } + + private class FileListLabelProvider extends LabelProvider implements ITableLabelProvider { + + public Image getColumnImage(Object element, int column) { + if (column == 0) return ImageCache.getImage(ImageCache.IMG_ATTRIBUTE); + return null; + } + + public String getColumnText(Object element, int column) { + @SuppressWarnings("unchecked") + Map<String,String> e = (Map<String,String>)element; + Object o = e.get(column_ids[column]); + if (o == null) return ""; //$NON-NLS-1$ + return o.toString(); + } + } + + private Exception init_error; + + public String getName() { + return "Download"; //$NON-NLS-1$ + } + + @Override + public Image getImage() { + return ImageCache.getImage(ImageCache.IMG_DOWNLOAD_TAB); + } + + @Override + public String getId() { + return TAB_ID; + } + + public void createControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(1, false); + composite.setFont(parent.getFont()); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 1, 1)); + createTable(composite); + setControl(composite); + } + + private void createTable(Composite parent) { + Font font = parent.getFont(); + Label map_label = new Label(parent, SWT.WRAP); + map_label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + map_label.setFont(font); + map_label.setText("Files to download during launch:"); //$NON-NLS-1$ + + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + layout.marginHeight = 0; + layout.marginWidth = 0; + composite.setFont(font); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 1, 1)); + + viewer = new TableViewer(composite, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION); + Table table = viewer.getTable(); + table.setLayoutData(new GridData(GridData.FILL_BOTH)); + table.setHeaderVisible(true); + table.setLinesVisible(true); + table.setFont(font); + viewer.setContentProvider(new FileListContentProvider()); + viewer.setLabelProvider(new FileListLabelProvider()); + viewer.setColumnProperties(column_ids); + + for (int i = 0; i < column_ids.length; i++) { + TableColumn c = new TableColumn(table, SWT.NONE, i); + c.setText(column_ids[i]); + c.setWidth(column_size[i]); + } + createTableButtons(composite); + viewer.addSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + updateLaunchConfigurationDialog(); + } + }); + + viewer.addDoubleClickListener(new IDoubleClickListener() { + @Override + public void doubleClick(DoubleClickEvent event) { + if (button_edit.isEnabled()) { + onEdit((IStructuredSelection)viewer.getSelection()); + } + } + }); + } + + private void createTableButtons(Composite parent) { + Font font = parent.getFont(); + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + composite.setFont(font); + composite.setLayout(layout); + GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL); + composite.setLayoutData(gd); + + Menu menu = new Menu(viewer.getTable()); + SelectionAdapter sel_adapter = null; + + button_add = new Button(composite, SWT.PUSH); + button_add.setText(" &Add... "); //$NON-NLS-1$ + gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); + button_add.setLayoutData(gd); + button_add.addSelectionListener(sel_adapter = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + Map<String,Object> m = new HashMap<String,Object>(); + DownloadFileDialog dialog = new DownloadFileDialog(getShell(), getPeerID(), m); + if (dialog.open() == Window.OK) { + list.add(m); + viewer.add(m); + viewer.setSelection(new StructuredSelection(m), true); + viewer.getTable().setFocus(); + updateLaunchConfigurationDialog(); + } + } + }); + item_add = new MenuItem(menu, SWT.PUSH); + item_add.setText("&Add..."); //$NON-NLS-1$ + item_add.addSelectionListener(sel_adapter); + item_add.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ADD)); + + button_edit = new Button(composite, SWT.PUSH); + button_edit.setText(" &Edit... "); //$NON-NLS-1$ + button_edit.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + button_edit.addSelectionListener(sel_adapter = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + onEdit((IStructuredSelection)viewer.getSelection()); + } + }); + item_edit= new MenuItem(menu, SWT.PUSH); + item_edit.setText("&Edit..."); //$NON-NLS-1$ + item_edit.addSelectionListener(sel_adapter); + + button_remove = new Button(composite, SWT.PUSH); + button_remove.setText(" &Remove "); //$NON-NLS-1$ + button_remove.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + button_remove.addSelectionListener(sel_adapter = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + for (Iterator<?> i = ((IStructuredSelection)viewer.getSelection()).iterator(); i.hasNext();) { + @SuppressWarnings("unchecked") + Map<String,String> m = (Map<String,String>)i.next(); + list.remove(m); + viewer.remove(m); + } + updateLaunchConfigurationDialog(); + } + }); + item_remove = new MenuItem(menu, SWT.PUSH); + item_remove.setText("&Remove"); //$NON-NLS-1$ + item_remove.addSelectionListener(sel_adapter); + item_remove.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_ETOOL_DELETE)); + + viewer.getTable().setMenu(menu); + } + + private void onEdit(IStructuredSelection selection) { + @SuppressWarnings("unchecked") + Map<String,Object> m = (Map<String,Object>)selection.getFirstElement(); + DownloadFileDialog dialog = new DownloadFileDialog(getShell(), getPeerID(), m); + dialog.open(); + viewer.refresh(m); + viewer.setSelection(new StructuredSelection(m), true); + viewer.getTable().setFocus(); + updateLaunchConfigurationDialog(); + } + + private String getPeerID() { + String peer_id = "TCP:127.0.0.1:1534"; + for (ILaunchConfigurationTab t : getLaunchConfigurationDialog().getTabs()) { + if (t instanceof TCFTargetTab) peer_id = ((TCFTargetTab)t).getPeerID(); + } + return peer_id; + } + + protected final TableViewer getViewer() { + return viewer; + } + + public void initializeFrom(ILaunchConfiguration config) { + setErrorMessage(null); + setMessage(null); + try { + list.clear(); + final String s = config.getAttribute(TCFLaunchDelegate.ATTR_FILES, ""); //$NON-NLS-1$ + list.addAll(new TCFTask<Collection<Map<String,Object>>>(10000) { + @Override + public void run() { + try { + ArrayList<Map<String,Object>> l = new ArrayList<Map<String,Object>>(); + if (s != null && s.length() > 0) { + @SuppressWarnings("unchecked") + Collection<Map<String,Object>> c = (Collection<Map<String,Object>>)JSON.parseOne(s.getBytes("UTF-8")); + for (Map<String,Object> m : c) l.add(new HashMap<String,Object>(m)); + } + done(l); + } + catch (Throwable e) { + error(e); + } + } + }.get()); + viewer.setInput(config); + button_remove.setEnabled(!viewer.getSelection().isEmpty()); + button_edit.setEnabled(((IStructuredSelection)viewer.getSelection()).size()==1); + item_remove.setEnabled(!viewer.getSelection().isEmpty()); + item_edit.setEnabled(((IStructuredSelection)viewer.getSelection()).size()==1); + } + catch (Exception e) { + init_error = e; + setErrorMessage("Cannot read launch configuration: " + e); //$NON-NLS-1$ + Activator.log(e); + } + } + + public void performApply(ILaunchConfigurationWorkingCopy config) { + if (list.size() == 0) { + config.removeAttribute(TCFLaunchDelegate.ATTR_FILES); + } + else { + String s = new TCFTask<String>(10000) { + @Override + public void run() { + try { + done(JSON.toJSON(list)); + } + catch (Throwable e) { + error(e); + } + } + }.getE(); + config.setAttribute(TCFLaunchDelegate.ATTR_FILES, s); + } + } + + public void setDefaults(ILaunchConfigurationWorkingCopy config) { + config.removeAttribute(TCFLaunchDelegate.ATTR_FILES); + } + + @Override + protected void updateLaunchConfigurationDialog() { + super.updateLaunchConfigurationDialog(); + button_remove.setEnabled(!viewer.getSelection().isEmpty()); + button_edit.setEnabled(((IStructuredSelection)viewer.getSelection()).size() == 1); + item_remove.setEnabled(!viewer.getSelection().isEmpty()); + item_edit.setEnabled(((IStructuredSelection)viewer.getSelection()).size() == 1); + } + + @Override + public boolean isValid(ILaunchConfiguration config) { + setMessage(null); + + if (init_error != null) { + setErrorMessage("Cannot read launch configuration: " + init_error); //$NON-NLS-1$ + return false; + } + + setErrorMessage(null); + return true; + } +} diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFMainTab.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFMainTab.java index 8952dadd6..803cd369c 100644 --- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFMainTab.java +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFMainTab.java @@ -66,6 +66,8 @@ public class TCFMainTab extends AbstractLaunchConfigurationTab { comp.setLayout(topLayout); createVerticalSpacer(comp, 1); + createHeader(comp); + createVerticalSpacer(comp, 1); createProjectGroup(comp); createApplicationGroup(comp); createWorkingDirGroup(comp); @@ -73,6 +75,13 @@ public class TCFMainTab extends AbstractLaunchConfigurationTab { createOptionButtons(comp, 1); } + private void createHeader(Composite parent) { + Label label = new Label(parent, SWT.NONE); + label.setText("Launching an application requires a target that supports Processes service"); + GridData gd = new GridData(); + label.setLayoutData(gd); + } + private void createProjectGroup(Composite parent) { Group group = new Group(parent, SWT.NONE); GridLayout layout = new GridLayout(); @@ -493,11 +502,11 @@ public class TCFMainTab extends AbstractLaunchConfigurationTab { } public String getName() { - return "Main"; + return "Application"; } @Override public Image getImage() { - return ImageCache.getImage(ImageCache.IMG_TCF); + return ImageCache.getImage(ImageCache.IMG_APPLICATION_TAB); } } diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFPathMapTab.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFPathMapTab.java index e02b3bcc3..2b35c3817 100644 --- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFPathMapTab.java +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFPathMapTab.java @@ -310,9 +310,9 @@ public class TCFPathMapTab extends AbstractLaunchConfigurationTab { protected void updateLaunchConfigurationDialog() { super.updateLaunchConfigurationDialog(); button_remove.setEnabled(!viewer.getSelection().isEmpty()); - button_edit.setEnabled(((IStructuredSelection)viewer.getSelection()).size()==1); + button_edit.setEnabled(((IStructuredSelection)viewer.getSelection()).size() == 1); item_remove.setEnabled(!viewer.getSelection().isEmpty()); - item_edit.setEnabled(((IStructuredSelection)viewer.getSelection()).size()==1); + item_edit.setEnabled(((IStructuredSelection)viewer.getSelection()).size() == 1); } @Override diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTabGroup.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTabGroup.java index 3d8f8c435..87a1dc941 100644 --- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTabGroup.java +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTabGroup.java @@ -24,8 +24,9 @@ public class TCFTabGroup extends AbstractLaunchConfigurationTabGroup { public void createTabs(ILaunchConfigurationDialog dialog, String mode) { setTabs(new ILaunchConfigurationTab[] { - new TCFMainTab(), new TCFTargetTab(), + new TCFDownloadTab(), + new TCFMainTab(), new TCFArgumentsTab(), new EnvironmentTab(), new TCFMemoryMapTab(), diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTargetTab.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTargetTab.java index c8738766f..60ef4b29c 100644 --- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTargetTab.java +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/launch/TCFTargetTab.java @@ -13,7 +13,6 @@ package org.eclipse.tcf.internal.debug.ui.launch; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; @@ -29,8 +28,6 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.TreeEvent; -import org.eclipse.swt.events.TreeListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; @@ -39,10 +36,8 @@ import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.MessageBox; @@ -50,7 +45,6 @@ import org.eclipse.swt.widgets.ProgressBar; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.Tree; -import org.eclipse.swt.widgets.TreeColumn; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.tcf.internal.debug.launch.TCFLaunchDelegate; import org.eclipse.tcf.internal.debug.launch.TCFLocalAgent; @@ -58,11 +52,10 @@ import org.eclipse.tcf.internal.debug.launch.TCFUserDefPeer; import org.eclipse.tcf.internal.debug.tests.TCFTestSuite; import org.eclipse.tcf.internal.debug.ui.Activator; import org.eclipse.tcf.internal.debug.ui.ImageCache; +import org.eclipse.tcf.internal.debug.ui.launch.PeerListControl.PeerInfo; import org.eclipse.tcf.internal.debug.ui.launch.setup.SetupWizardDialog; -import org.eclipse.tcf.protocol.IChannel; import org.eclipse.tcf.protocol.IPeer; import org.eclipse.tcf.protocol.Protocol; -import org.eclipse.tcf.services.ILocator; import org.eclipse.tcf.services.IMemoryMap; import org.eclipse.tcf.services.IPathMap; import org.eclipse.tcf.util.TCFTask; @@ -79,129 +72,13 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { private Button run_local_agent_button; private Button use_local_agent_button; private Text peer_id_text; + private PeerListControl peer_list; private Tree peer_tree; private Runnable update_peer_buttons; - private final PeerInfo peer_info = new PeerInfo(); private Display display; private Exception init_error; private String mem_map_cfg; - private static class PeerInfo { - PeerInfo parent; - String id; - Map<String,String> attrs; - PeerInfo[] children; - boolean children_pending; - Throwable children_error; - IPeer peer; - IChannel channel; - ILocator locator; - LocatorListener listener; - Runnable item_update; - } - - private class LocatorListener implements ILocator.LocatorListener { - - private final PeerInfo parent; - - LocatorListener(PeerInfo parent) { - this.parent = parent; - } - - public void peerAdded(final IPeer peer) { - if (display == null) return; - final String id = peer.getID(); - final HashMap<String,String> attrs = new HashMap<String,String>(peer.getAttributes()); - display.asyncExec(new Runnable() { - public void run() { - if (parent.children_error != null) return; - PeerInfo[] arr = parent.children; - for (PeerInfo p : arr) assert !p.id.equals(id); - PeerInfo[] buf = new PeerInfo[arr.length + 1]; - System.arraycopy(arr, 0, buf, 0, arr.length); - PeerInfo info = new PeerInfo(); - info.parent = parent; - info.id = id; - info.attrs = attrs; - info.peer = peer; - buf[arr.length] = info; - parent.children = buf; - updateItems(parent); - } - }); - } - - public void peerChanged(final IPeer peer) { - if (display == null) return; - final String id = peer.getID(); - final HashMap<String,String> attrs = new HashMap<String,String>(peer.getAttributes()); - display.asyncExec(new Runnable() { - public void run() { - if (parent.children_error != null) return; - PeerInfo[] arr = parent.children; - for (int i = 0; i < arr.length; i++) { - if (arr[i].id.equals(id)) { - arr[i].attrs = attrs; - arr[i].peer = peer; - updateItems(parent); - } - } - } - }); - } - - public void peerRemoved(final String id) { - if (display == null) return; - display.asyncExec(new Runnable() { - public void run() { - if (parent.children_error != null) return; - PeerInfo[] arr = parent.children; - PeerInfo[] buf = new PeerInfo[arr.length - 1]; - int j = 0; - for (int i = 0; i < arr.length; i++) { - if (arr[i].id.equals(id)) { - final PeerInfo info = arr[i]; - Protocol.invokeLater(new Runnable() { - public void run() { - disconnectPeer(info); - } - }); - } - else { - buf[j++] = arr[i]; - } - } - parent.children = buf; - updateItems(parent); - } - }); - } - - public void peerHeartBeat(final String id) { - if (display == null) return; - display.asyncExec(new Runnable() { - public void run() { - if (parent.children_error != null) return; - PeerInfo[] arr = parent.children; - for (int i = 0; i < arr.length; i++) { - if (arr[i].id.equals(id)) { - if (arr[i].children_error != null) { - TreeItem item = findItem(arr[i]); - boolean visible = item != null; - while (visible && item != null) { - if (!item.getExpanded()) visible = false; - item = item.getParentItem(); - } - if (visible) loadChildren(arr[i]); - } - break; - } - } - } - }); - } - } - public void createControl(Composite parent) { display = parent.getDisplay(); assert display != null; @@ -281,108 +158,18 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { peer_label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); peer_label.setFont(font); - loadChildren(peer_info); - createPeerListArea(group); - } - - private void createPeerListArea(Composite parent) { - Font font = parent.getFont(); - Composite composite = new Composite(parent, SWT.NONE); - GridLayout layout = new GridLayout(2, false); - composite.setFont(font); - composite.setLayout(layout); - composite.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 2, 1)); - - peer_tree = new Tree(composite, SWT.VIRTUAL | SWT.BORDER | SWT.SINGLE); - GridData gd = new GridData(GridData.FILL_BOTH); - gd.minimumHeight = 150; - gd.minimumWidth = 470; - peer_tree.setLayoutData(gd); - - for (int i = 0; i < 6; i++) { - TreeColumn column = new TreeColumn(peer_tree, SWT.LEAD, i); - column.setMoveable(true); - switch (i) { - case 0: - column.setText("Name"); - column.setWidth(160); - break; - case 1: - column.setText("OS"); - column.setWidth(100); - break; - case 2: - column.setText("User"); - column.setWidth(100); - break; - case 3: - column.setText("Transport"); - column.setWidth(60); - break; - case 4: - column.setText("Host"); - column.setWidth(100); - break; - case 5: - column.setText("Port"); - column.setWidth(40); - break; - } - } - - peer_tree.setHeaderVisible(true); - peer_tree.setFont(font); - peer_tree.addListener(SWT.SetData, new Listener() { - public void handleEvent(Event event) { - TreeItem item = (TreeItem)event.item; - PeerInfo info = findPeerInfo(item); - if (info == null) { - updateItems(item.getParentItem(), false); - } - else { - fillItem(item, info); - updateLaunchConfigurationDialog(); - } - } - }); - peer_tree.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetDefaultSelected(SelectionEvent e) { - final PeerInfo info = findPeerInfo(peer_id_text.getText()); - if (info == null) return; - new PeerPropsDialog(getShell(), getImage(), info.attrs, - info.peer instanceof TCFUserDefPeer).open(); - if (!(info.peer instanceof TCFUserDefPeer)) return; - Protocol.invokeLater(new Runnable() { - public void run() { - ((TCFUserDefPeer)info.peer).updateAttributes(info.attrs); - TCFUserDefPeer.savePeers(); - } - }); - } + peer_list = new PeerListControl(group) { @Override - public void widgetSelected(SelectionEvent e) { - TreeItem[] selections = peer_tree.getSelection(); - if (selections.length > 0) { - assert selections.length == 1; - PeerInfo info = findPeerInfo(selections[0]); - if (info != null) peer_id_text.setText(getPath(info)); - } + protected void onPeerListChanged() { updateLaunchConfigurationDialog(); } - }); - peer_tree.addTreeListener(new TreeListener() { - - public void treeCollapsed(TreeEvent e) { - updateItems((TreeItem)e.item, false); - } - - public void treeExpanded(TreeEvent e) { - updateItems((TreeItem)e.item, true); + @Override + protected void onPeerSelected(PeerInfo info) { + peer_id_text.setText(peer_list.getPath(info)); } - }); - - createPeerButtons(composite); + }; + peer_tree = peer_list.getTree(); + createPeerButtons(peer_tree.getParent()); } private void createPeerButtons(Composite parent) { @@ -425,7 +212,7 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { button_edit.addSelectionListener(sel_adapter = new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - final PeerInfo info = findPeerInfo(peer_id_text.getText()); + final PeerInfo info = peer_list.findPeerInfo(peer_id_text.getText()); if (info == null) return; if (new PeerPropsDialog(getShell(), getImage(), info.attrs, info.peer instanceof TCFUserDefPeer).open() != Window.OK) return; @@ -448,7 +235,7 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { button_remove.addSelectionListener(sel_adapter = new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - final PeerInfo info = findPeerInfo(peer_id_text.getText()); + final PeerInfo info = peer_list.findPeerInfo(peer_id_text.getText()); if (info == null) return; if (!(info.peer instanceof TCFUserDefPeer)) return; peer_id_text.setText(""); @@ -500,7 +287,7 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { public void run() { boolean local = use_local_agent_button.getSelection(); - PeerInfo info = findPeerInfo(peer_id_text.getText()); + PeerInfo info = peer_list.findPeerInfo(peer_id_text.getText()); button_new.setEnabled(!local); button_edit.setEnabled(info != null && !local); button_remove.setEnabled(info != null && info.peer instanceof TCFUserDefPeer && !local); @@ -530,7 +317,7 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { peer_tree.setEnabled(true); peer_id_text.setEnabled(true); String id = peer_id_text.getText(); - TreeItem item = findItem(id); + TreeItem item = peer_list.findItem(id); if (item != null) peer_tree.setSelection(item); else peer_tree.deselectAll(); } @@ -538,17 +325,6 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { super.updateLaunchConfigurationDialog(); } - @Override - public void dispose() { - Protocol.invokeAndWait(new Runnable() { - public void run() { - disconnectPeer(peer_info); - display = null; - } - }); - super.dispose(); - } - public String getName() { return "Target"; } @@ -568,9 +344,8 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { setMessage(null); try { String id = configuration.getAttribute(TCFLaunchDelegate.ATTR_PEER_ID, ""); - TreeItem item = findItem(id); - if (item != null) peer_tree.setSelection(item); peer_id_text.setText(id); + peer_list.setInitialSelection(id); run_local_agent_button.setSelection(configuration.getAttribute(TCFLaunchDelegate.ATTR_RUN_LOCAL_AGENT, false)); use_local_agent_button.setSelection(configuration.getAttribute(TCFLaunchDelegate.ATTR_USE_LOCAL_AGENT, true)); mem_map_cfg = configuration.getAttribute(TCFLaunchDelegate.ATTR_MEMORY_MAP, "null"); @@ -613,324 +388,8 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { return true; } - private void disconnectPeer(final PeerInfo info) { - assert Protocol.isDispatchThread(); - if (info.children != null) { - for (PeerInfo p : info.children) disconnectPeer(p); - } - if (info.listener != null) { - info.locator.removeListener(info.listener); - info.listener = null; - info.locator = null; - } - if (info.channel != null) { - info.channel.close(); - } - } - - private boolean canHaveChildren(PeerInfo parent) { - return parent == peer_info || parent.attrs.get(IPeer.ATTR_PROXY) != null; - } - - private void loadChildren(final PeerInfo parent) { - assert Thread.currentThread() == display.getThread(); - if (parent.children_pending) return; - assert parent.children == null; - parent.children_pending = true; - parent.children_error = null; - Protocol.invokeAndWait(new Runnable() { - public void run() { - assert parent.listener == null; - assert parent.channel == null; - if (!canHaveChildren(parent)) { - doneLoadChildren(parent, null, new PeerInfo[0]); - } - else if (parent == peer_info) { - peer_info.locator = Protocol.getLocator(); - doneLoadChildren(parent, null, createLocatorListener(peer_info)); - } - else { - final IChannel channel = parent.peer.openChannel(); - parent.channel = channel; - parent.channel.addChannelListener(new IChannel.IChannelListener() { - boolean opened = false; - boolean closed = false; - public void congestionLevel(int level) { - } - public void onChannelClosed(final Throwable error) { - assert !closed; - if (parent.channel != channel) return; - if (!opened) { - doneLoadChildren(parent, error, null); - } - else { - if (display != null) { - display.asyncExec(new Runnable() { - public void run() { - if (parent.children_pending) return; - parent.children = null; - parent.children_error = error; - updateItems(parent); - } - }); - } - } - closed = true; - parent.channel = null; - parent.locator = null; - parent.listener = null; - } - public void onChannelOpened() { - assert !opened; - assert !closed; - if (parent.channel != channel) return; - opened = true; - parent.locator = parent.channel.getRemoteService(ILocator.class); - if (parent.locator == null) { - parent.channel.terminate(new Exception("Service not supported: " + ILocator.NAME)); - } - else { - doneLoadChildren(parent, null, createLocatorListener(parent)); - } - } - }); - } - } - }); - } - - private PeerInfo[] createLocatorListener(PeerInfo peer) { - assert Protocol.isDispatchThread(); - Map<String,IPeer> map = peer.locator.getPeers(); - PeerInfo[] buf = new PeerInfo[map.size()]; - int n = 0; - for (IPeer p : map.values()) { - PeerInfo info = new PeerInfo(); - info.parent = peer; - info.id = p.getID(); - info.attrs = new HashMap<String,String>(p.getAttributes()); - info.peer = p; - buf[n++] = info; - } - peer.listener = new LocatorListener(peer); - peer.locator.addListener(peer.listener); - return buf; - } - - private void doneLoadChildren(final PeerInfo parent, final Throwable error, final PeerInfo[] children) { - assert Protocol.isDispatchThread(); - assert error == null || children == null; - if (display == null) return; - display.asyncExec(new Runnable() { - public void run() { - assert parent.children_pending; - assert parent.children == null; - parent.children_pending = false; - parent.children = children; - parent.children_error = error; - updateItems(parent); - } - }); - } - - private ArrayList<PeerInfo> filterPeerList(PeerInfo parent, boolean expanded) { - ArrayList<PeerInfo> lst = new ArrayList<PeerInfo>(); - HashMap<String,PeerInfo> local_agents = new HashMap<String,PeerInfo>(); - HashSet<String> ids = new HashSet<String>(); - for (PeerInfo p : parent.children) { - String id = p.attrs.get(IPeer.ATTR_AGENT_ID); - if (id == null) continue; - if (!"TCP".equals(p.attrs.get(IPeer.ATTR_TRANSPORT_NAME))) continue; - if (!"127.0.0.1".equals(p.attrs.get(IPeer.ATTR_IP_HOST))) continue; - local_agents.put(id, p); - ids.add(p.id); - } - for (PeerInfo p : parent.children) { - PeerInfo i = local_agents.get(p.attrs.get(IPeer.ATTR_AGENT_ID)); - if (i != null && i != p) continue; - lst.add(p); - } - if (parent != peer_info && expanded) { - for (PeerInfo p : peer_info.children) { - if (p.peer instanceof TCFUserDefPeer && !ids.contains(p.id)) { - PeerInfo x = new PeerInfo(); - x.parent = parent; - x.id = p.id; - x.attrs = p.attrs; - x.peer = p.peer; - ids.add(x.id); - lst.add(x); - } - } - } - return lst; - } - - private void updateItems(TreeItem parent_item, boolean reload) { - final PeerInfo parent_info = findPeerInfo(parent_item); - if (parent_info == null) { - parent_item.setText("Invalid"); - } - else { - if (reload && parent_info.children_error != null) { - loadChildren(parent_info); - } - display.asyncExec(new Runnable() { - public void run() { - updateItems(parent_info); - } - }); - } - } - - private void updateItems(final PeerInfo parent) { - if (display == null) return; - assert Thread.currentThread() == display.getThread(); - parent.item_update = new Runnable() { - public void run() { - if (display == null) return; - if (parent.item_update != this) return; - if (Thread.currentThread() != display.getThread()) { - display.asyncExec(this); - return; - } - parent.item_update = null; - TreeItem[] items = null; - boolean expanded = true; - if (parent.children == null || parent.children_error != null) { - if (parent == peer_info) { - peer_tree.setItemCount(1); - items = peer_tree.getItems(); - } - else { - TreeItem item = findItem(parent); - if (item == null) return; - expanded = item.getExpanded(); - item.setItemCount(1); - items = item.getItems(); - } - assert items.length == 1; - if (parent.children_pending) { - items[0].setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); - fillItem(items[0], "Connecting..."); - } - else if (parent.children_error != null) { - String msg = parent.children_error.getMessage(); - if (msg == null) msg = parent.children_error.getClass().getName(); - else msg = msg.replace('\n', ' '); - items[0].setForeground(display.getSystemColor(SWT.COLOR_RED)); - fillItem(items[0], msg); - } - else if (expanded) { - loadChildren(parent); - items[0].setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); - fillItem(items[0], "Connecting..."); - } - else { - Protocol.invokeAndWait(new Runnable() { - public void run() { - disconnectPeer(parent); - } - }); - fillItem(items[0], ""); - } - } - else { - ArrayList<PeerInfo> lst = null; - if (parent == peer_info) { - lst = filterPeerList(parent, expanded); - peer_tree.setItemCount(lst.size() > 0 ? lst.size() : 1); - items = peer_tree.getItems(); - } - else { - TreeItem item = findItem(parent); - if (item == null) return; - expanded = item.getExpanded(); - lst = filterPeerList(parent, expanded); - item.setItemCount(expanded && lst.size() > 0 ? lst.size() : 1); - items = item.getItems(); - } - if (expanded && lst.size() > 0) { - assert items.length == lst.size(); - for (int i = 0; i < items.length; i++) fillItem(items[i], lst.get(i)); - } - else if (expanded) { - fillItem(items[0], "No peers"); - } - else { - Protocol.invokeAndWait(new Runnable() { - public void run() { - disconnectPeer(parent); - } - }); - fillItem(items[0], ""); - } - } - updateLaunchConfigurationDialog(); - } - }; - if (parent.children_pending) parent.item_update.run(); - else Protocol.invokeLater(200, parent.item_update); - } - - private TreeItem findItem(String path) { - assert Thread.currentThread() == display.getThread(); - if (path == null) return null; - int z = path.lastIndexOf('/'); - if (z < 0) { - int n = peer_tree.getItemCount(); - for (int i = 0; i < n; i++) { - TreeItem x = peer_tree.getItem(i); - PeerInfo p = (PeerInfo)x.getData("TCFPeerInfo"); - if (p != null && p.id.equals(path)) return x; - } - } - else { - TreeItem y = findItem(path.substring(0, z)); - if (y == null) return null; - String id = path.substring(z + 1); - int n = y.getItemCount(); - for (int i = 0; i < n; i++) { - TreeItem x = y.getItem(i); - PeerInfo p = (PeerInfo)x.getData("TCFPeerInfo"); - if (p != null && p.id.equals(id)) return x; - } - } - return null; - } - - private TreeItem findItem(PeerInfo info) { - if (info == null) return null; - assert info.parent != null; - if (info.parent == peer_info) { - int n = peer_tree.getItemCount(); - for (int i = 0; i < n; i++) { - TreeItem x = peer_tree.getItem(i); - if (x.getData("TCFPeerInfo") == info) return x; - } - } - else { - TreeItem y = findItem(info.parent); - if (y == null) return null; - int n = y.getItemCount(); - for (int i = 0; i < n; i++) { - TreeItem x = y.getItem(i); - if (x.getData("TCFPeerInfo") == info) return x; - } - } - return null; - } - - private PeerInfo findPeerInfo(String path) { - TreeItem i = findItem(path); - if (i == null) return null; - return (PeerInfo)i.getData("TCFPeerInfo"); - } - - private PeerInfo findPeerInfo(TreeItem item) { - assert Thread.currentThread() == display.getThread(); - if (item == null) return peer_info; - return (PeerInfo)item.getData("TCFPeerInfo"); + public String getPeerID() { + return peer_id_text.getText(); } private void runDiagnostics(boolean loop) { @@ -955,7 +414,7 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { } } else { - PeerInfo info = findPeerInfo(peer_id_text.getText()); + PeerInfo info = peer_list.findPeerInfo(peer_id_text.getText()); if (info == null) return; peer = info.peer; } @@ -1066,46 +525,4 @@ public class TCFTargetTab extends AbstractLaunchConfigurationTab { } }); } - - private void fillItem(TreeItem item, PeerInfo info) { - assert Thread.currentThread() == display.getThread(); - Object data = item.getData("TCFPeerInfo"); - if (data != null && data != info) item.removeAll(); - item.setData("TCFPeerInfo", info); - String text[] = new String[6]; - text[0] = info.attrs.get(IPeer.ATTR_NAME); - text[1] = info.attrs.get(IPeer.ATTR_OS_NAME); - text[2] = info.attrs.get(IPeer.ATTR_USER_NAME); - text[3] = info.attrs.get(IPeer.ATTR_TRANSPORT_NAME); - text[4] = info.attrs.get(IPeer.ATTR_IP_HOST); - text[5] = info.attrs.get(IPeer.ATTR_IP_PORT); - for (int i = 0; i < text.length; i++) { - if (text[i] == null) text[i] = ""; - } - item.setText(text); - item.setForeground(display.getSystemColor(SWT.COLOR_LIST_FOREGROUND)); - item.setImage(ImageCache.getImage(getImageName(info))); - if (!canHaveChildren(info)) item.setItemCount(0); - else if (info.children == null || info.children_error != null) item.setItemCount(1); - else item.setItemCount(info.children.length); - } - - private void fillItem(TreeItem item, String text) { - item.setText(text); - item.setData("TCFPeerInfo", null); - int n = peer_tree.getColumnCount(); - for (int i = 1; i < n; i++) item.setText(i, ""); - item.setImage((Image)null); - item.removeAll(); - } - - private String getPath(PeerInfo info) { - if (info == peer_info) return ""; - if (info.parent == peer_info) return info.id; - return getPath(info.parent) + "/" + info.id; - } - - private String getImageName(PeerInfo info) { - return ImageCache.IMG_TARGET_TAB; - } } diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java index 056f21049..b2274c526 100644 --- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java +++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.tcf.internal.debug.ui.model; +import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -1962,6 +1963,9 @@ public class TCFModel implements ITCFModel, IElementContentProvider, IElementLab if (!multiline && error instanceof IErrorReport) { msg = Command.toErrorString(((IErrorReport)error).getAttributes()); } + else if (error instanceof UnknownHostException) { + msg = "Unknown host: " + error.getMessage(); + } else { msg = error.getLocalizedMessage(); } @@ -1976,8 +1980,8 @@ public class TCFModel implements ITCFModel, IElementContentProvider, IElementLab else if (ch != '.' && ch != ';') { buf.append(';'); } - buf.append("Caused by:"); - buf.append(multiline ? '\n' : ' '); + if (multiline) buf.append("Caused by:\n"); + else buf.append(' '); } } if (buf.length() > 0) { |