diff options
Diffstat (limited to 'target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal')
108 files changed, 11463 insertions, 0 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/ImageConsts.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/ImageConsts.java new file mode 100644 index 000000000..e46b3eaec --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/ImageConsts.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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.te.tcf.filesystem.ui.internal; + +/** + * File system plug-in Image registry constants. + */ +public interface ImageConsts { + + // ***** The directory structure constants ***** + + /** + * The root directory where to load the images from, relative to + * the bundle directory. + */ + public final static String IMAGE_DIR_ROOT = "icons/"; //$NON-NLS-1$ + + /** + * The directory where to load model object images from, + * relative to the image root directory. + */ + public final static String IMAGE_DIR_OBJ = "obj16/"; //$NON-NLS-1$ + + /** + * The directory where to load model object images from, + * relative to the image root directory. + */ + public final static String IMAGE_DIR_OBJ32 = "obj32/"; //$NON-NLS-1$ + + /** + * The directory where to load the decorator image from. + */ + public final static String IMAGE_DIR_OVR = "ovr/"; //$NON-NLS-1$ + + // ***** The image constants ***** + + /** + * The key to access the base folder object image. + */ + public static final String FOLDER = "Folder"; //$NON-NLS-1$ + + /** + * The key to access the base root node object image. + */ + public static final String ROOT = "Root"; //$NON-NLS-1$ + + /** + * The key to access the base root folder object image (closed). + */ + public static final String ROOT_DRIVE = "RootDrive"; //$NON-NLS-1$ + + /** + * The key to access the image of compare editor. + */ + public static final String COMPARE_EDITOR = "CompareEditor"; //$NON-NLS-1$ + + /** + * The key to access the title image of "replace folder confirm" dialog. + */ + public static final String REPLACE_FOLDER_CONFIRM = "ReplaceFolderConfirm"; //$NON-NLS-1$ + + /** + * The key to access the title image of "confirm read only delete" dialog. + */ + public static final String DELETE_READONLY_CONFIRM = "ConfirmReadOnlyDelete"; //$NON-NLS-1$ + + /** + * The key to access the banner image of the advanced attributes dialog. + */ + public static final String BANNER_IMAGE = "BannerImage"; //$NON-NLS-1$ + + /** + * The key to access the error image used in the tool tip popped up during renaming. + */ + public static final String ERROR_IMAGE = "ErrorImage"; //$NON-NLS-1$ + + public static final String REFRESH_IMAGE = "RefreshImage"; //$NON-NLS-1$ +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/adapters/FSTreeNodeAdapterFactory.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/adapters/FSTreeNodeAdapterFactory.java new file mode 100644 index 000000000..6f2cf59af --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/adapters/FSTreeNodeAdapterFactory.java @@ -0,0 +1,121 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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.te.tcf.filesystem.ui.internal.adapters; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.core.runtime.PlatformObject; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.columns.FSTreeElementLabelProvider; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.search.FSTreeNodeSearchable; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNode; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNodeProvider; +import org.eclipse.tcf.te.ui.interfaces.ILazyLoader; +import org.eclipse.tcf.te.ui.interfaces.ISearchable; +import org.eclipse.ui.IActionFilter; +import org.eclipse.ui.IPersistableElement; + +/** + * The adapter factory of <code>FSTreeNode</code> over <code>IActionFilter</code> + */ +public class FSTreeNodeAdapterFactory implements IAdapterFactory { + private static ILabelProvider nodeLabelProvider = new FSTreeElementLabelProvider(); + // The fFilters map caching fFilters for FS nodes. + private Map<FSTreeNode, NodeStateFilter> filters; + + public static class FSTreeNodePeerNodeProvider extends PlatformObject implements IPeerNodeProvider { + private final FSTreeNode node; + + /** + * Constructor + */ + public FSTreeNodePeerNodeProvider(FSTreeNode node) { + Assert.isNotNull(node); + this.node = node; + } + + /** + * Returns the associated file system tree node. + * + * @return The associated file system tree node. + */ + public final FSTreeNode getFSTreeNode() { + return node; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNodeProvider#getPeerModel() + */ + @Override + public final IPeerNode getPeerNode() { + return node.peerNode; + } + } + + /** + * Constructor. + */ + public FSTreeNodeAdapterFactory() { + this.filters = Collections.synchronizedMap(new HashMap<FSTreeNode, NodeStateFilter>()); + } + + /* + * (non-Javadoc) + * @see org.eclipse.core.runtime.IAdapterFactory#getAdapter(java.lang.Object, java.lang.Class) + */ + @Override + public Object getAdapter(Object adaptableObject, Class adapterType) { + if (adaptableObject instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode) adaptableObject; + if (adapterType == IActionFilter.class) { + NodeStateFilter filter = filters.get(node); + if (filter == null) { + filter = new NodeStateFilter(node); + filters.put(node, filter); + } + return filter; + } + else if (adapterType == ILabelProvider.class) { + return nodeLabelProvider; + } + else if (adapterType == IPersistableElement.class && UIPlugin.isExpandedPersisted()) { + return new PersistableNode(node); + } + else if (adapterType == ILazyLoader.class) { + return new FSTreeNodeLoader(node); + } + else if (adapterType == IPeerNodeProvider.class) { + return new FSTreeNodePeerNodeProvider(node); + } + else if (adapterType == IPeerNode.class) { + return new FSTreeNodePeerNodeProvider(node).getPeerNode(); + } + else if (adapterType == ISearchable.class) { + return new FSTreeNodeSearchable(node); + } + } + return null; + } + + /* + * (non-Javadoc) + * @see org.eclipse.core.runtime.IAdapterFactory#getAdapterList() + */ + @Override + public Class[] getAdapterList() { + return new Class[] { IActionFilter.class, ILabelProvider.class, IPersistableElement.class, ILazyLoader.class, ISearchable.class, IPeerNodeProvider.class }; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/adapters/FSTreeNodeFactory.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/adapters/FSTreeNodeFactory.java new file mode 100644 index 000000000..3b3a67e01 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/adapters/FSTreeNodeFactory.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2012, 2014 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.te.tcf.filesystem.ui.internal.adapters; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.IOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.NullOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpParsePath; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNode; +import org.eclipse.tcf.te.tcf.locator.interfaces.services.IPeerModelLookupService; +import org.eclipse.tcf.te.tcf.locator.model.ModelManager; +import org.eclipse.ui.IElementFactory; +import org.eclipse.ui.IMemento; + +/** + * The element factory for FSTreeNode used to restore FSTreeNodes persisted + * for expanded states. + */ +public class FSTreeNodeFactory implements IElementFactory { + /* + * (non-Javadoc) + * @see org.eclipse.ui.IElementFactory#createElement(org.eclipse.ui.IMemento) + */ + @Override + public IAdaptable createElement(IMemento memento) { + String peerId = memento.getString("peerId"); //$NON-NLS-1$ + IPeerNode peerNode = ModelManager.getPeerModel().getService(IPeerModelLookupService.class).lkupPeerModelById(peerId); + if(peerNode != null) { + String path = memento.getString("path"); //$NON-NLS-1$ + if(path == null) { + return org.eclipse.tcf.te.tcf.filesystem.core.model.ModelManager.getRuntimeModel(peerNode).getRoot(); + } + OpParsePath op = new OpParsePath(peerNode, path); + IOpExecutor executor = new NullOpExecutor(); + IStatus status = executor.execute(op); + if(status.isOK()) { + return op.getResult(); + } + } + return null; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/adapters/FSTreeNodeLoader.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/adapters/FSTreeNodeLoader.java new file mode 100644 index 000000000..e04fc7740 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/adapters/FSTreeNodeLoader.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.adapters; + +import java.lang.reflect.InvocationTargetException; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.exceptions.TCFException; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.NullOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpRefreshRoots; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.Operation; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.ui.interfaces.ILazyLoader; + +/** + * The implementation of ILazyLoader for FSTreeNode check its data availability + * and load its children if not ready. + */ +public class FSTreeNodeLoader implements ILazyLoader { + // The node to be checked. + private FSTreeNode node; + /** + * Constructor + * + * @param node The file/folder node. + */ + public FSTreeNodeLoader(FSTreeNode node) { + this.node = node; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.interfaces.ILazyLoader#isDataLoaded() + */ + @Override + public boolean isDataLoaded() { + return node.isFile() || (node.isSystemRoot() || node.isDirectory()) && node.childrenQueried; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.interfaces.ILazyLoader#loadData(org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + public void loadData(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { + try { + if(node.isFile()) return; + if (node.isSystemRoot()) { + new NullOpExecutor().execute(new OpRefreshRoots(node)); + } + else { + new Operation().getChildren(node); + } + } + catch (TCFException e) { + throw new InvocationTargetException(e); + } + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.interfaces.ILazyLoader#isLeaf() + */ + @Override + public boolean isLeaf() { + return node.isFile(); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/adapters/NodeStateFilter.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/adapters/NodeStateFilter.java new file mode 100644 index 000000000..1ca440246 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/adapters/NodeStateFilter.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * 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.te.tcf.filesystem.ui.internal.adapters; + +import java.util.List; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpClipboard; +import org.eclipse.tcf.te.tcf.filesystem.core.model.CacheState; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.ui.IActionFilter; + +/** + * This action filter wraps an FSTreeNode and test its attribute of "cache.state". + * It serves as the expression filter of decorations of Target Explorer. + */ +public class NodeStateFilter implements IActionFilter { + private FSTreeNode node; + + /** + * Constructor. + * + * @param node + * The wrapped tree node. Must not be <code>null</code>. + */ + public NodeStateFilter(FSTreeNode node) { + Assert.isNotNull(node); + this.node = node; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IActionFilter#testAttribute(java.lang.Object, java.lang.String, java.lang.String) + */ + @Override + public boolean testAttribute(Object target, String name, String value) { + if (name.equals("cache.state") && node.isFile()) { //$NON-NLS-1$ + if(UIPlugin.isAutoSaving()) + return false; + CacheState state = node.getCacheState(); + if (value == null) + value = CacheState.consistent.name(); + return value.equals(state.name()); + } + else if (name.equals("edit.cut")) { //$NON-NLS-1$ + OpClipboard cb = UIPlugin.getClipboard(); + if (!cb.isEmpty()) { + if (cb.isCutOp()) { + List<FSTreeNode> files = cb.getFiles(); + for (FSTreeNode file : files) { + if (node == file) return true; + } + } + } + } + else if (name.equals("hidden")) { //$NON-NLS-1$ + if (value == null) value = "true"; //$NON-NLS-1$ + boolean result = false; + if (!node.isRoot()) { + if (node.isWindowsNode()) { + result = node.isHidden(); + } + else { + result = node.name.startsWith("."); //$NON-NLS-1$ + } + } + return Boolean.toString(result).equals(value); + } + return false; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/adapters/PeerNodeViewerInput.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/adapters/PeerNodeViewerInput.java new file mode 100644 index 000000000..bdb3580c1 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/adapters/PeerNodeViewerInput.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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.te.tcf.filesystem.ui.internal.adapters; + +import org.eclipse.tcf.te.core.interfaces.IViewerInput; +import org.eclipse.tcf.te.core.utils.PropertyChangeProvider; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNode; + +/** + * The viewer input of an IPeerNode instance. + */ +public class PeerNodeViewerInput extends PropertyChangeProvider implements IViewerInput { + // The peer model. + private IPeerNode peerNode; + + /** + * Create an instance with a peer model. + * + * @param peerNode The peer model. + */ + public PeerNodeViewerInput(IPeerNode peerNode) { + this.peerNode = peerNode; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.interfaces.IViewerInput#getInputId() + */ + @Override + public String getInputId() { + return peerNode.getPeerId(); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/adapters/PersistableNode.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/adapters/PersistableNode.java new file mode 100644 index 000000000..8cc6698d4 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/adapters/PersistableNode.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2012 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.te.tcf.filesystem.ui.internal.adapters; + +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.ui.IMemento; +import org.eclipse.ui.IPersistableElement; + +/** + * The adapter class of FSTreeNode for IPersistableElement, used to + * persist an FSTreeNode. + */ +public class PersistableNode implements IPersistableElement { + // The node to be persisted. + private FSTreeNode node; + /** + * Create an instance. + * + * @param node The node to be persisted. + */ + public PersistableNode(FSTreeNode node) { + this.node = node; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.IPersistable#saveState(org.eclipse.ui.IMemento) + */ + @Override + public void saveState(IMemento memento) { + memento.putString("peerId", node.peerNode.getPeerId()); //$NON-NLS-1$ + String path = null; + if (!node.isSystemRoot()) path = node.getLocation(); + if (path != null) memento.putString("path", path); //$NON-NLS-1$ + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.IPersistableElement#getFactoryId() + */ + @Override + public String getFactoryId() { + return "org.eclipse.tcf.te.tcf.filesystem.ui.nodeFactory"; //$NON-NLS-1$ + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/adapters/ViewerInputAdapterFactory.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/adapters/ViewerInputAdapterFactory.java new file mode 100644 index 000000000..5107a78d1 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/adapters/ViewerInputAdapterFactory.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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.te.tcf.filesystem.ui.internal.adapters; + +import java.util.concurrent.atomic.AtomicReference; + +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.tcf.protocol.Protocol; +import org.eclipse.tcf.te.core.interfaces.IPropertyChangeProvider; +import org.eclipse.tcf.te.core.interfaces.IViewerInput; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNode; + +/** + * The adapter factory for IViewerInput. + */ +public class ViewerInputAdapterFactory implements IAdapterFactory { + // The key to store and access the the viewer input object. + private static final String VIEWER_INPUT_KEY = UIPlugin.getUniqueIdentifier()+".peer.viewerInput"; //$NON-NLS-1$ + + /* + * (non-Javadoc) + * @see org.eclipse.core.runtime.IAdapterFactory#getAdapter(java.lang.Object, java.lang.Class) + */ + @Override + public Object getAdapter(Object adaptableObject, Class adapterType) { + if(adaptableObject instanceof IPeerNode) { + if (IViewerInput.class.equals(adapterType) + || IPropertyChangeProvider.class.equals(adapterType)) { + IPeerNode peerNode = (IPeerNode) adaptableObject; + return getViewerInput(peerNode); + } + } + return null; + } + + /** + * Get a viewer input from the specified peer model. + * + * @param peerNode The peer model to get the viewer input from. + * @return The peer model's viewer input. + */ + PeerNodeViewerInput getViewerInput(final IPeerNode peerNode) { + if (peerNode != null) { + if (Protocol.isDispatchThread()) { + PeerNodeViewerInput model = (PeerNodeViewerInput) peerNode.getProperty(VIEWER_INPUT_KEY); + if (model == null) { + model = new PeerNodeViewerInput(peerNode); + peerNode.setProperty(VIEWER_INPUT_KEY, model); + } + return model; + } + final AtomicReference<PeerNodeViewerInput> reference = new AtomicReference<PeerNodeViewerInput>(); + Protocol.invokeAndWait(new Runnable() { + @Override + public void run() { + reference.set(getViewerInput(peerNode)); + } + }); + return reference.get(); + } + return null; + } + + /* + * (non-Javadoc) + * @see org.eclipse.core.runtime.IAdapterFactory#getAdapterList() + */ + @Override + public Class[] getAdapterList() { + return new Class[] { IViewerInput.class, IPropertyChangeProvider.class }; + } + +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/autosave/SaveAllListener.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/autosave/SaveAllListener.java new file mode 100644 index 000000000..74ec4d7d8 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/autosave/SaveAllListener.java @@ -0,0 +1,131 @@ +/******************************************************************************* + * 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: + * William Chen (Wind River) - [345552] Edit the remote files with a proper editor + *******************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.ui.internal.autosave; + +import java.io.File; +import java.net.URI; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IExecutionListener; +import org.eclipse.core.commands.NotHandledException; +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.SafeRunner; +import org.eclipse.jface.util.SafeRunnable; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.IOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.NullOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpParsePath; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpUpload; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.operations.UiExecutor; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IURIEditorInput; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * The execution listener of command "SAVE ALL", which synchronizes the local + * file with the one on the target server after it is saved. + */ +public class SaveAllListener implements IExecutionListener { + // Dirty nodes that should be saved and synchronized. + List<FSTreeNode> fDirtyNodes; + /** + * Create the listener listening to command "SAVE ALL". + */ + public SaveAllListener() { + this.fDirtyNodes = new ArrayList<FSTreeNode>(); + } + + /* (non-Javadoc) + * @see org.eclipse.core.commands.IExecutionListener#postExecuteSuccess(java.lang.String, java.lang.Object) + */ + @Override + public void postExecuteSuccess(String commandId, Object returnValue) { + if (!fDirtyNodes.isEmpty()) { + if (UIPlugin.isAutoSaving()) { + FSTreeNode[] nodes = fDirtyNodes.toArray(new FSTreeNode[fDirtyNodes.size()]); + IOpExecutor executor = new UiExecutor(); + executor.execute(new OpUpload(nodes)); + } + else { + SafeRunner.run(new SafeRunnable(){ + @Override + public void handleException(Throwable e) { + // Ignore exception + } + @Override + public void run() throws Exception { + for (FSTreeNode dirtyNode : fDirtyNodes) { + dirtyNode.refresh(); + } + }}); + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.core.commands.IExecutionListener#preExecute(java.lang.String, org.eclipse.core.commands.ExecutionEvent) + */ + @Override + public void preExecute(String commandId, ExecutionEvent event) { + fDirtyNodes.clear(); + // In Eclipse 4.x, the HandlerUtil.getActiveWorkbenchWindow(event) may return null + IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindow(event); + if (window == null) window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + IWorkbenchPage page = window.getActivePage(); + IEditorPart[] editors = page.getDirtyEditors(); + for (IEditorPart editor : editors) { + IEditorInput input = editor.getEditorInput(); + FSTreeNode node = null; + if (input instanceof IURIEditorInput) { + //Get the file that is being edited. + IURIEditorInput fileInput = (IURIEditorInput) input; + URI uri = fileInput.getURI(); + try { + IFileStore store = EFS.getStore(uri); + File localFile = store.toLocalFile(0, new NullProgressMonitor()); + if (localFile != null) { + // Get the file's mapped FSTreeNode. + OpParsePath parser = new OpParsePath(localFile.getCanonicalPath()); + new NullOpExecutor().execute(parser); + node = parser.getResult(); + if (node != null) { + // If it is a modified node, add it to the dirty node list. + fDirtyNodes.add(node); + } + } + }catch(Exception e){} + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.core.commands.IExecutionListener#notHandled(java.lang.String, org.eclipse.core.commands.NotHandledException) + */ + @Override + public void notHandled(String commandId, NotHandledException exception) { + } + + /* (non-Javadoc) + * @see org.eclipse.core.commands.IExecutionListener#postExecuteFailure(java.lang.String, org.eclipse.core.commands.ExecutionException) + */ + @Override + public void postExecuteFailure(String commandId, ExecutionException exception) { + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/autosave/SaveListener.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/autosave/SaveListener.java new file mode 100644 index 000000000..670beb8fb --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/autosave/SaveListener.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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: + * William Chen (Wind River) - [345552] Edit the remote files with a proper editor + *******************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.ui.internal.autosave; + +import java.io.File; +import java.net.URI; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IExecutionListener; +import org.eclipse.core.commands.NotHandledException; +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.SafeRunner; +import org.eclipse.jface.util.SafeRunnable; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.IOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.NullOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpParsePath; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpUpload; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.operations.UiExecutor; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IURIEditorInput; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * The execution listener of command "SAVE", which synchronizes the local file + * with the one on the target server after it is saved. + */ +public class SaveListener implements IExecutionListener { + // Dirty node that should be committed or merged. + FSTreeNode dirtyNode; + + /** + * Create a SaveListener listening to command "SAVE". + */ + public SaveListener() { + } + + /* (non-Javadoc) + * @see org.eclipse.core.commands.IExecutionListener#postExecuteSuccess(java.lang.String, java.lang.Object) + */ + @Override + public void postExecuteSuccess(String commandId, Object returnValue) { + if (dirtyNode != null) { + if (UIPlugin.isAutoSaving()) { + IOpExecutor executor = new UiExecutor(); + executor.execute(new OpUpload(dirtyNode)); + } + else { + SafeRunner.run(new SafeRunnable(){ + @Override + public void handleException(Throwable e) { + // Ignore exception + } + @Override + public void run() throws Exception { + if (dirtyNode != null) dirtyNode.refresh(); + } + }); + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.core.commands.IExecutionListener#preExecute(java.lang.String, org.eclipse.core.commands.ExecutionEvent) + */ + @Override + public void preExecute(String commandId, ExecutionEvent event) { + dirtyNode = null; + IEditorInput input = HandlerUtil.getActiveEditorInput(event); + if (input instanceof IURIEditorInput) { + IURIEditorInput fileInput = (IURIEditorInput) input; + URI uri = fileInput.getURI(); + try { + IFileStore store = EFS.getStore(uri); + File localFile = store.toLocalFile(0, new NullProgressMonitor()); + if (localFile != null) { + OpParsePath parser = new OpParsePath(localFile.getCanonicalPath()); + new NullOpExecutor().execute(parser); + dirtyNode = parser.getResult(); + } + }catch(Exception e){ + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.core.commands.IExecutionListener#notHandled(java.lang.String, org.eclipse.core.commands.NotHandledException) + */ + @Override + public void notHandled(String commandId, NotHandledException exception) { + } + + /* (non-Javadoc) + * @see org.eclipse.core.commands.IExecutionListener#postExecuteFailure(java.lang.String, org.eclipse.core.commands.ExecutionException) + */ + @Override + public void postExecuteFailure(String commandId, ExecutionException exception) { + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/celleditor/FSCellListener.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/celleditor/FSCellListener.java new file mode 100644 index 000000000..0f2cac475 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/celleditor/FSCellListener.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.celleditor; + +import org.eclipse.jface.viewers.ICellEditorListener; +import org.eclipse.jface.viewers.TextCellEditor; +import org.eclipse.jface.window.DefaultToolTip; +import org.eclipse.jface.window.ToolTip; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Control; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.ImageConsts; + +/** + * FSCellListener is an <code>ICellEditorListener</code> that listens to the modification event and displays + * error messages in a tool tip when the new name entered is not valid. + */ +public class FSCellListener implements ICellEditorListener { + // The cell editor used to enter the new name for renaming. + private TextCellEditor editor; + // The tool tip used to display the error message. + private DefaultToolTip tooltip; + + /** + * Create an FSCellListener using the specified cell editor. + * + * @param editor The cell editor + */ + public FSCellListener(TextCellEditor editor) { + this.editor = editor; + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.ICellEditorListener#applyEditorValue() + */ + @Override + public void applyEditorValue() { + disposeToolTip(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.ICellEditorListener#cancelEditor() + */ + @Override + public void cancelEditor() { + disposeToolTip(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.ICellEditorListener#editorValueChanged(boolean, boolean) + */ + @Override + public void editorValueChanged(boolean oldValidState, boolean newValidState) { + if (!newValidState) { + // If it is an invalid input, then display a tool tip showing the error. + if (tooltip == null) { + tooltip = new DefaultToolTip(editor.getControl(), ToolTip.RECREATE, true); + tooltip.setImage(UIPlugin.getImage(ImageConsts.ERROR_IMAGE)); + } + tooltip.setText(editor.getErrorMessage()); + Control control = editor.getControl(); + Point pOnScr = control.getSize(); + pOnScr.x = 0; + tooltip.show(pOnScr); + } + else { + // Dispose the tool tip if it is valid. + disposeToolTip(); + } + } + + /** + * Dispose the tool tip used to display error message. + */ + private void disposeToolTip() { + if (tooltip != null) { + tooltip.hide(); + tooltip = null; + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/celleditor/FSCellModifier.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/celleditor/FSCellModifier.java new file mode 100644 index 000000000..b1da8c4ad --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/celleditor/FSCellModifier.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.celleditor; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.viewers.ICellModifier; +import org.eclipse.swt.widgets.Item; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.IOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.JobExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpRename; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.handlers.RenameCallback; + +/** + * FSCellModifier is an <code>ICellModifier</code> of the file system tree of the target explorer. + */ +public class FSCellModifier implements ICellModifier { + // The column property used to get the name of a given file system node. + public static final String PROPERTY_NAME = "name"; //$NON-NLS-1$ + + public FSCellModifier() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.ICellModifier#canModify(java.lang.Object, java.lang.String) + */ + @Override + public boolean canModify(Object element, String property) { + if (property.equals(PROPERTY_NAME)) { + if (element instanceof Item) { + element = ((Item) element).getData(); + } + if (element instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode) element; + if (!node.isRoot()) { + return node.isWindowsNode() && !node.isReadOnly() || !node.isWindowsNode() && node.isWritable(); + } + } + } + return false; + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.ICellModifier#getValue(java.lang.Object, java.lang.String) + */ + @Override + public Object getValue(Object element, String property) { + if (property.equals(PROPERTY_NAME)) { + if (element instanceof Item) { + element = ((Item) element).getData(); + } + if (element instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode) element; + return node.name; + } + } + return null; + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.ICellModifier#modify(java.lang.Object, java.lang.String, + * java.lang.Object) + */ + @Override + public void modify(Object element, String property, Object value) { + if (property.equals(PROPERTY_NAME)) { + if (element instanceof Item) { + element = ((Item) element).getData(); + } + if (element instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode) element; + Assert.isTrue(value != null && value instanceof String); + String newName = (String) value; + // Rename the node with the new name using an FSRename. + IOpExecutor executor = new JobExecutor(new RenameCallback()); + executor.execute(new OpRename(node, newName)); + } + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/celleditor/FSCellValidator.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/celleditor/FSCellValidator.java new file mode 100644 index 000000000..85b3de181 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/celleditor/FSCellValidator.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.celleditor; + +import java.util.List; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.viewers.ICellEditorValidator; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; + +/** + * FSCellValidator is an <code>ICellEditorValidator</code> that validates the name input in the file system + * tree cell editor. + */ +public class FSCellValidator implements ICellEditorValidator { + // The regular expression to define the pattern of a valid Unix file name(not '/'). + public static final String UNIX_FILENAME_REGEX = "[^/]+"; //$NON-NLS-1$ + // The regular expression to define the pattern of a valid Windows file name. + // (not '?', '\', '/','*','<','>' and '|'). + public static final String WIN_FILENAME_REGEX = "[^(\\?|\\\\|/|:|\\*|<|>|\\|)]+"; //$NON-NLS-1$ + + // The tree viewer used to display the file system. + private TreeViewer viewer; + /** + * Create an FSCellValidator for the specified file system tree. + * + * @param viewer The tree viewer for the file system. + */ + public FSCellValidator(TreeViewer viewer) { + this.viewer = viewer; + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.ICellEditorValidator#isValid(java.lang.Object) + */ + @Override + public String isValid(Object value) { + IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); + Object element = selection.getFirstElement(); + Assert.isTrue(element instanceof FSTreeNode); + FSTreeNode node = (FSTreeNode) element; + if (value == null) return Messages.FSRenamingAssistant_SpecifyNonEmptyName; + String text = value.toString().trim(); + if (text.length() == 0) return Messages.FSRenamingAssistant_SpecifyNonEmptyName; + if (hasChild(node, text)) { + return Messages.FSRenamingAssistant_NameAlreadyExists; + } + String formatRegex = node.isWindowsNode() ? WIN_FILENAME_REGEX : UNIX_FILENAME_REGEX; + if (!text.matches(formatRegex)) { + return node.isWindowsNode() ? Messages.FSRenamingAssistant_WinIllegalCharacters : Messages.FSRenamingAssistant_UnixIllegalCharacters; + } + return null; + } + /** + * To test if the folder has a child with the specified name. + * + * @param folder The folder node. + * @param name The name. + * @return true if it has a child with the name. + */ + private boolean hasChild(FSTreeNode folder, String name) { + List<FSTreeNode> nodes = folder.getParent().getChildren(); + for (FSTreeNode node : nodes) { + if (node.isWindowsNode()) { + if (node.name.equalsIgnoreCase(name)) return true; + } + else if (node.name.equals(name)) return true; + } + return false; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/celleditor/FSViewerCellEditorFactory.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/celleditor/FSViewerCellEditorFactory.java new file mode 100644 index 000000000..59788be3f --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/celleditor/FSViewerCellEditorFactory.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.celleditor; + +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.ICellModifier; +import org.eclipse.jface.viewers.TextCellEditor; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.handlers.RenameFilesHandler; +import org.eclipse.tcf.te.ui.interfaces.IViewerCellEditorFactory; + +/** + * FSViewerCellEditorFactory implements <code>IViewerCellEditorFactory</code> to add + * cell editors to Target Explorer for renaming files or folders in the file system tree viewer. + */ +public class FSViewerCellEditorFactory implements IViewerCellEditorFactory, FocusListener { + // The tree viewer to add cell editing. + private TreeViewer viewer; + // The cell editors used to rename a file/folder. + private TextCellEditor cellEditor; + // The cell modifier used to modify a file/folder's name. + private ICellModifier cellModifer; + + /** + * Create an instance. + */ + public FSViewerCellEditorFactory() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.interfaces.IViewerCellEditorFactory#init(org.eclipse.jface.viewers.TreeViewer) + */ + @Override + public void init(TreeViewer aViewer) { + viewer = aViewer; + cellEditor = new TextCellEditor(aViewer.getTree(), SWT.BORDER); + cellEditor.setValidator(new FSCellValidator(aViewer)); + cellEditor.addListener(new FSCellListener(cellEditor)); + cellModifer = new FSCellModifier(); + Tree tree = aViewer.getTree(); + tree.addFocusListener(this); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.interfaces.IViewerCellEditorFactory#getCellEditors() + */ + @Override + public CellEditor[] getCellEditors() { + return new CellEditor[] { cellEditor }; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.interfaces.IViewerCellEditorFactory#getCellModifier() + */ + @Override + public ICellModifier getCellModifier() { + return cellModifer; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.interfaces.IViewerCellEditorFactory#getColumnProperties() + */ + @Override + public String[] getColumnProperties() { + return new String[] { FSCellModifier.PROPERTY_NAME }; + } + + /* + * (non-Javadoc) + * @see org.eclipse.swt.events.FocusListener#focusGained(org.eclipse.swt.events.FocusEvent) + */ + @Override + public void focusGained(FocusEvent e) { + // Set the currently focused viewer. + RenameFilesHandler.setCurrentViewer(viewer); + } + + /* + * (non-Javadoc) + * @see org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent) + */ + @Override + public void focusLost(FocusEvent e) { + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/AccessTimeComparator.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/AccessTimeComparator.java new file mode 100644 index 000000000..29374e19c --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/AccessTimeComparator.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.columns; + +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * The comparator for the tree column "Date Accessed". + */ +public class AccessTimeComparator extends FSTreeNodeComparator { + private static final long serialVersionUID = 1L; + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.columns.FSTreeNodeComparator#doCompare(org.eclipse.tcf.te.tcf.filesystem.model.FSTreeNode, org.eclipse.tcf.te.tcf.filesystem.model.FSTreeNode) + */ + @Override + public int doCompare(FSTreeNode node1, FSTreeNode node2) { + long atime1 = node1.attr != null ? node1.attr.atime : 0; + long atime2 = node2.attr != null ? node2.attr.atime : 0; + return atime1 < atime2 ? -1 : (atime1 > atime2 ? 1 : 0); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/AccessTimeLabelProvider.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/AccessTimeLabelProvider.java new file mode 100644 index 000000000..ab84b5d73 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/AccessTimeLabelProvider.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.columns; + +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * The label provider for the tree column "Date Accessed". + */ +public class AccessTimeLabelProvider extends LabelProvider { + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object) + */ + @Override + public String getText(Object element) { + if (element instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode) element; + if (node.attr != null) { + SimpleDateFormat dateFormat = new SimpleDateFormat("M/d/yyyy h:mm aa"); //$NON-NLS-1$ + return dateFormat.format(new Date(node.attr.atime)); + } + } + return ""; //$NON-NLS-1$ + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/CacheFileImageUpdater.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/CacheFileImageUpdater.java new file mode 100644 index 000000000..24f70fb77 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/CacheFileImageUpdater.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2012 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.te.tcf.filesystem.ui.internal.columns; + +import java.io.File; + +import org.eclipse.tcf.te.tcf.filesystem.core.internal.utils.CacheManager; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * The image update adapter that updates the images of the file which + * has a local cache copy. + */ +public class CacheFileImageUpdater implements ImageUpdateAdapter { + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.columns.ImageUpdateAdapter#getImageKey(org.eclipse.tcf.te.tcf.filesystem.model.FSTreeNode) + */ + @Override + public String getImageKey(FSTreeNode node) { + return node.getLocationURL().toExternalForm(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.columns.ImageUpdateAdapter#getMirrorFile(org.eclipse.tcf.te.tcf.filesystem.model.FSTreeNode) + */ + @Override + public File getMirrorFile(FSTreeNode node) { + return CacheManager.getCacheFile(node); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.columns.ImageUpdateAdapter#getImgFile(org.eclipse.tcf.te.tcf.filesystem.model.FSTreeNode) + */ + @Override + public File getImageFile(FSTreeNode node) { + File cacheFile = CacheManager.getCacheFile(node); + File parentDir = cacheFile.getParentFile(); + if (!parentDir.exists() && !parentDir.mkdirs()) { + parentDir = CacheManager.getCacheRoot(); + } + return new File(parentDir, node.name + ".png"); //$NON-NLS-1$ + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/DefaultImageProvider.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/DefaultImageProvider.java new file mode 100644 index 000000000..2f3b78a81 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/DefaultImageProvider.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2012, 2014 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.te.tcf.filesystem.ui.internal.columns; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.graphics.Image; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.ImageConsts; +import org.eclipse.ui.IEditorRegistry; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.PlatformUI; + +/** + * The default implementation of ImageProvider, defining the images + * based on predefined images based on the node simulator. + */ +public class DefaultImageProvider implements ImageProvider { + // The editor registry used to search a file's image. + private IEditorRegistry editorRegistry = null; + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.columns.ImageProvider#getImage(org.eclipse.tcf.te.tcf.filesystem.model.FSTreeNode) + */ + @Override + public Image getImage(FSTreeNode node) { + if (node.isSystemRoot()) { + return UIPlugin.getImage(ImageConsts.ROOT); + } + else if (node.isRoot()) { + return UIPlugin.getImage(ImageConsts.ROOT_DRIVE); + } + else if (node.isDirectory()) { + return UIPlugin.getImage(ImageConsts.FOLDER); + } + else if (node.isFile()) { + return getPredefinedImage(node); + } + return null; + } + + /** + * Get a predefined image for the tree node. These images are retrieved from + * editor registry. + * + * @param node The file tree node. + * @return The editor image for this simulator. + */ + protected Image getPredefinedImage(FSTreeNode node) { + Image image; + String key = node.name; + image = UIPlugin.getImage(key); + if (image == null) { + ImageDescriptor descriptor = getEditorRegistry().getImageDescriptor(key); + if (descriptor == null) { + descriptor = getEditorRegistry().getSystemExternalEditorImageDescriptor(key); + } + if (descriptor != null) { + UIPlugin.getDefault().getImageRegistry().put(key, descriptor); + } + image = UIPlugin.getImage(key); + } + return image; + } + + /** + * Returns the workbench's editor registry. + */ + private IEditorRegistry getEditorRegistry() { + if (editorRegistry == null) { + IWorkbench workbench = PlatformUI.getWorkbench(); + if (workbench != null) editorRegistry = workbench.getEditorRegistry(); + } + return editorRegistry; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/FSTreeElementComparator.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/FSTreeElementComparator.java new file mode 100644 index 000000000..5ad79dca1 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/FSTreeElementComparator.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.columns; + +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * The comparator for the tree column "name". + */ +public class FSTreeElementComparator extends FSTreeNodeComparator { + private static final long serialVersionUID = 1L; + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.columns.FSTreeNodeComparator#doCompare(org.eclipse.tcf.te.tcf.filesystem.model.FSTreeNode, org.eclipse.tcf.te.tcf.filesystem.model.FSTreeNode) + */ + @Override + public int doCompare(FSTreeNode node1, FSTreeNode node2) { + String name1 = node1.name; + String name2 = node2.name; + if (name1 != null && name2 != null) { + if (name1.startsWith(".") && !name2.startsWith(".")) return -1; //$NON-NLS-1$ //$NON-NLS-2$ + if (!name1.startsWith(".") && name2.startsWith(".")) return 1; //$NON-NLS-1$ //$NON-NLS-2$ + return name1.compareToIgnoreCase(name2); + } + return 0; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/FSTreeElementLabelProvider.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/FSTreeElementLabelProvider.java new file mode 100644 index 000000000..3ae7d9ae4 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/FSTreeElementLabelProvider.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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.te.tcf.filesystem.ui.internal.columns; + +import org.eclipse.swt.graphics.Image; +import org.eclipse.tcf.te.runtime.model.interfaces.IModelNode; +import org.eclipse.tcf.te.runtime.utils.Host; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.ui.trees.PendingAwareLabelProvider; + +/** + * The label provider for the tree column "name". + */ +public class FSTreeElementLabelProvider extends PendingAwareLabelProvider { + // The image provider to provide platform specific images. + private ImageProvider imgProvider; + + /** + * Constructor. + */ + public FSTreeElementLabelProvider() { + if(Host.isWindowsHost()) { + imgProvider = new WindowsImageProvider(); + } + else { + imgProvider = new DefaultImageProvider(); + } + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object) + */ + @Override + public String getText(Object element) { + if (element instanceof FSTreeNode) { + return ((FSTreeNode) element).name; + } + else if (element instanceof IModelNode) { + return ((IModelNode)element).getName(); + } + + return super.getText(element); + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object) + */ + @Override + public Image getImage(Object element) { + if (element instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode) element; + return imgProvider.getImage(node); + } + else if (element instanceof IModelNode) { + return UIPlugin.getImage(((IModelNode)element).getImageId()); + } + + return super.getImage(element); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/FSTreeNodeComparator.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/FSTreeNodeComparator.java new file mode 100644 index 000000000..4aaad28d0 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/FSTreeNodeComparator.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * 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.te.tcf.filesystem.ui.internal.columns; + +import java.io.Serializable; +import java.util.Comparator; + +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * The base comparator for all the file system tree column. + */ +public abstract class FSTreeNodeComparator implements Comparator<Object>, Serializable { + private static final long serialVersionUID = 1L; + + /* + * (non-Javadoc) + * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) + */ + @Override + public final int compare(Object o1, Object o2) { + if (!(o1 instanceof FSTreeNode) || !(o2 instanceof FSTreeNode)) return 0; + + FSTreeNode node1 = (FSTreeNode)o1; + FSTreeNode node2 = (FSTreeNode)o2; + + // Get the type labels + String type1 = node1.type; + String type2 = node2.type; + + // Group directories and files always together before sorting by name + if ((node1.isRoot() || node1.isDirectory()) && !(node2.isRoot() || node2.isDirectory())) { + return -1; + } + + if ((node2.isRoot() || node2.isDirectory()) && !(node1.isRoot() || node1.isDirectory())) { + return 1; + } + + // If the nodes are of the same type and one entry starts + // with a '.', it comes before the one without a '.' + if (type1 != null && type2 != null && type1.equals(type2)) { + return doCompare(node1, node2); + } + return 0; + } + + /** + * Sort the node1 and node2 when they are both directories or files. + * + * @param node1 The first node. + * @param node2 The second node. + * @return The comparison result. + */ + public abstract int doCompare(FSTreeNode node1, FSTreeNode node2); +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/FileExtBasedImageUpdater.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/FileExtBasedImageUpdater.java new file mode 100644 index 000000000..90ca5dbe7 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/FileExtBasedImageUpdater.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2012 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.te.tcf.filesystem.ui.internal.columns; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * The image update adapter that updates the images of the file which does + * not have a local cache copy. The algorithm is based its extension. + */ +public class FileExtBasedImageUpdater implements ImageUpdateAdapter { + // The label provider update daemon + private LabelProviderUpdateDaemon updateDaemon; + + /** + * Create an instance with the specified daemon. + * + * @param daemon The label provider update daemon. + */ + public FileExtBasedImageUpdater(LabelProviderUpdateDaemon daemon) { + this.updateDaemon = daemon; + } + + /** + * Get the node's file extension or null if there is no extension. + * + * @param node The file tree node. + * @return The file's extension or null. + */ + private String getFileExt(FSTreeNode node) { + String name = node.name; + String ext = "noext"; //$NON-NLS-1$ + int index = name.lastIndexOf("."); //$NON-NLS-1$ + if (index != -1) ext = name.substring(index + 1); + return ext; + } + + /** + * Get the directory to store the temporary mirror files. + * + * @return The directory to contain the mirror files. + */ + private File getMirrorDir() { + File tmpDir = updateDaemon.getTempDir(); + File mrrDir = new File(tmpDir, ".mrr"); //$NON-NLS-1$ + if(!mrrDir.exists() && !mrrDir.mkdirs()) { + mrrDir = tmpDir; + } + return mrrDir; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.columns.ImageUpdateAdapter#getImageKey(org.eclipse.tcf.te.tcf.filesystem.model.FSTreeNode) + */ + @Override + public String getImageKey(FSTreeNode node) { + String ext = getFileExt(node); + return "EXT_IMAGE@" + ext; //$NON-NLS-1$ + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.columns.ImageUpdateAdapter#getMirrorFile(org.eclipse.tcf.te.tcf.filesystem.model.FSTreeNode) + */ + @Override + public File getMirrorFile(FSTreeNode node) { + String ext = getFileExt(node); + File mrrDir = getMirrorDir(); + File file = new File(mrrDir, "mirror" + "." + ext); //$NON-NLS-1$ //$NON-NLS-2$ + if (!file.exists()) { + try { + file.createNewFile(); + } + catch (IOException e) { + } + } + return file; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.columns.ImageUpdateAdapter#getImgFile(org.eclipse.tcf.te.tcf.filesystem.model.FSTreeNode) + */ + @Override + public File getImageFile(FSTreeNode node) { + String ext = getFileExt(node); + return updateDaemon.getTempImg(ext); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/FileTypeComparator.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/FileTypeComparator.java new file mode 100644 index 000000000..8b53a6bed --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/FileTypeComparator.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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.te.tcf.filesystem.ui.internal.columns; + +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * The comparator for the tree column "simulator". + */ +public class FileTypeComparator extends FSTreeNodeComparator { + private static final long serialVersionUID = 1L; + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.columns.FSTreeNodeComparator#doCompare(org.eclipse.tcf.te.tcf.filesystem.model.FSTreeNode, org.eclipse.tcf.te.tcf.filesystem.model.FSTreeNode) + */ + @Override + public int doCompare(FSTreeNode node1, FSTreeNode node2) { + String type1 = node1.getFileType(); + String type2 = node2.getFileType(); + return type1.compareTo(type2); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/FileTypeLabelProvider.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/FileTypeLabelProvider.java new file mode 100644 index 000000000..d97fa3d31 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/FileTypeLabelProvider.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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.te.tcf.filesystem.ui.internal.columns; + +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * The label provider for the tree column "simulator". + */ +public class FileTypeLabelProvider extends LabelProvider { + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object) + */ + @Override + public String getText(Object element) { + if (element instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode) element; + return node.getFileType(); + } + return super.getText(element); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/ImageProvider.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/ImageProvider.java new file mode 100644 index 000000000..9ec98b0c8 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/ImageProvider.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2012 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.te.tcf.filesystem.ui.internal.columns; + +import org.eclipse.swt.graphics.Image; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * An image provider provides platform specific images for each files/folders. + * It is used by FSTreeElementLabelProvider to provide the images of a file + * node. + */ +public interface ImageProvider { + /** + * Get the image display for the specified file node. + * + * @param node The file node. + * @return The image that represents the file node. + */ + Image getImage(FSTreeNode node); +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/ImageUpdateAdapter.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/ImageUpdateAdapter.java new file mode 100644 index 000000000..1457868ad --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/ImageUpdateAdapter.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2012 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.te.tcf.filesystem.ui.internal.columns; + +import java.io.File; + +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * The interface to adapt the process of providing the image for two kinds of + * files, one which has a local copy or one which does not. + */ +public interface ImageUpdateAdapter { + + /** + * Get an extension key as the image registry key for the + * specified node. + * + * @param node The node to get the key for. + * @return The key used to cache the image descriptor in the registry. + */ + public String getImageKey(FSTreeNode node); + + /** + * Return a mirror file that will be used to retrieve the image from. + * + * @param node The file system tree node. + * @return The corresponding mirror file. + */ + public File getMirrorFile(FSTreeNode node); + + /** + * Get the image file object for the specified temporary file name. + * + * @param tmpName The temporary file name. + * @return The file object. + */ + public File getImageFile(FSTreeNode node); +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/LabelProviderUpdateDaemon.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/LabelProviderUpdateDaemon.java new file mode 100644 index 000000000..5f5e04860 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/LabelProviderUpdateDaemon.java @@ -0,0 +1,289 @@ +/******************************************************************************* + * Copyright (c) 2012 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.te.tcf.filesystem.ui.internal.columns; + +import java.awt.Component; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.beans.PropertyChangeEvent; +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +import javax.imageio.ImageIO; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.filechooser.FileSystemView; + +import org.eclipse.core.runtime.ISafeRunnable; +import org.eclipse.core.runtime.SafeRunner; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.graphics.Image; +import org.eclipse.tcf.te.core.interfaces.IPropertyChangeProvider; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.utils.CacheManager; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.ImageConsts; + +/** + * The background daemon that updates the images of the file system using + * images retrieved by FileSystemView from Swing. + */ +public class LabelProviderUpdateDaemon extends Thread { + private static String[][] os_drives = { + {"windows xp", "xp_rootdrive.png"}, //$NON-NLS-1$ //$NON-NLS-2$ + {"windows 7", "win7_rootdrive.png"}, //$NON-NLS-1$//$NON-NLS-2$ + {"windows 8", "win8_rootdrive.png"} //$NON-NLS-1$//$NON-NLS-2$ + }; + private static String root_drive = createRootImage(getOSEntry()); + + private static int getOSEntry() { + String osName = System.getProperty("os.name").toLowerCase(); //$NON-NLS-1$ + for(int i = 0; i < os_drives.length;i++) { + if(os_drives[i][0].equals(osName)) return i; + } + return 0; + } + + private static String createRootImage(int i) { + UIPlugin plugin = UIPlugin.getDefault(); + URL url = plugin.getBundle().getEntry(ImageConsts.IMAGE_DIR_ROOT + ImageConsts.IMAGE_DIR_OBJ + os_drives[i][1]); + plugin.getImageRegistry().put(os_drives[i][0], ImageDescriptor.createFromURL(url)); + return os_drives[i][0]; + } + + // The dummy AWT component used to render the icon. + Component dummyComponent = new JComponent(){private static final long serialVersionUID = 5926798769323111209L;}; + //The queue that caches the current file nodes to be updated. + BlockingQueue<FSTreeNode> queueNodes; + // The image update adapter for a file which has a local cache copy. + ImageUpdateAdapter cacheAdapter; + // The image update adapter for a file which does not has a local cache copy. + ImageUpdateAdapter extAdapter; + + /** + * Constructor + */ + public LabelProviderUpdateDaemon() { + super("Image Updater Daemon"); //$NON-NLS-1$ + setDaemon(true); + this.queueNodes = new LinkedBlockingQueue<FSTreeNode>(); + this.cacheAdapter = new CacheFileImageUpdater(); + this.extAdapter = new FileExtBasedImageUpdater(this); + } + + /** + * Cache the node which is to be updated with its icon in the file tree. + * + * @param node The node to be enqueued + */ + public void enqueue(final FSTreeNode node) { + SafeRunner.run(new ISafeRunnable() { + @Override + public void handleException(Throwable exception) { + // Ignore + } + + @Override + public void run() throws Exception { + queueNodes.put(node); + } + }); + } + + /** + * Take next node to be processed. + * + * @return The next node. + */ + private FSTreeNode take() { + while (true) { + try { + return queueNodes.take(); + } + catch (InterruptedException e) { + } + } + } + + /* + * (non-Javadoc) + * @see java.lang.Thread#run() + */ + @Override + public void run() { + while (true) { + FSTreeNode node = take(); + ImageUpdateAdapter adapter = getUpdateAdapter(node); + String imgKey = adapter.getImageKey(node); + ImageDescriptor image = UIPlugin.getImageDescriptor(imgKey); + if (image == null) { + File mrrFile = adapter.getMirrorFile(node); + File imgFile = adapter.getImageFile(node); + image = createImage(imgKey, mrrFile, imgFile); + } + if (image != null) { + sendNotification(node, node.name, null, image); + } + } + } + + /** + * Select an image update adapter for the specified node. + * + * @param node The FSTreeNode. + * @return an image update adapter, either cache based or extension based. + */ + private ImageUpdateAdapter getUpdateAdapter(FSTreeNode node) { + File cacheFile = CacheManager.getCacheFile(node); + if (cacheFile.exists()) { + return cacheAdapter; + } + return extAdapter; + } + + /** + * Get the image for the specified node from its + * image update adapter. + * + * @param node The file system tree node. + * @return The image or null if there's no image yet. + */ + public Image getImage(FSTreeNode node) { + ImageUpdateAdapter adapter = getUpdateAdapter(node); + String key = adapter.getImageKey(node); + return UIPlugin.getImage(key); + } + + /** + * Create an Image Descriptor based on the mirror file and store + * it in the imgFile and store it using the specified image key. + * + * @param imgKey The image key. + * @param mrrFile The mirror file used to create the image. + * @param imgFile The image file used to store the image data. + * @return The Image Descriptor describing the image or null if it is not successful. + */ + private ImageDescriptor createImage(String imgKey, File mrrFile, File imgFile) { + ImageDescriptor image = UIPlugin.getImageDescriptor(imgKey); + if (image == null) { + if (!imgFile.exists()) { + FileSystemView view = FileSystemView.getFileSystemView(); + Icon icon = view.getSystemIcon(mrrFile); + if (icon != null) createImageFromIcon(icon, imgFile); + } + if (imgFile.exists()) { + try { + image = ImageDescriptor.createFromURL(imgFile.toURI().toURL()); + UIPlugin.getDefault().getImageRegistry().put(imgKey, image); + } + catch (MalformedURLException e) { + // Ignore + } + } + } + return image; + } + + /** + * Get the image of disk drivers on Windows platform. + * + * @return The disk driver image. + */ + public Image getDiskImage() { + return UIPlugin.getImage(root_drive); + } + + /** + * Get the folder image on Windows platform. + * + * @return The folder image. + */ + public Image getFolderImage() { + String key = "SWING_FOLDER_IMAGE"; //$NON-NLS-1$ + ImageDescriptor imgDesc = UIPlugin.getImageDescriptor(key); + if (imgDesc == null) { + String dir = System.getProperty("work.dir"); //$NON-NLS-1$ + if (dir == null) dir = System.getProperty("java.home"); //$NON-NLS-1$ + File mirror = null; + if (dir != null) mirror = new File(dir); + else mirror = new File("."); //$NON-NLS-1$ + File imgFile = getTempImg("_directory_"); //$NON-NLS-1$ + createImage(key, mirror, imgFile); + } + return UIPlugin.getImage(key); + } + + /** + * Get the temporary directory store the images and temporary mirror files. + * @return + */ + protected File getTempDir() { + File cacheRoot = CacheManager.getCacheRoot(); + File tempDir = new File(cacheRoot, ".tmp"); //$NON-NLS-1$ + if (!tempDir.exists() && !tempDir.mkdirs()) { + tempDir = cacheRoot; + } + return tempDir; + } + + /** + * Get the an image file named "imgName" in the temporary image + * directory. + * + * @param imgName The image's file name. + * @return The file object of this image file. + */ + protected File getTempImg(String imgName) { + File tempDir = getTempDir(); + File imgDir = new File(tempDir, ".img"); //$NON-NLS-1$ + if (!imgDir.exists() && !imgDir.mkdirs()) { + imgDir = tempDir; + } + return new File(imgDir, imgName + ".png"); //$NON-NLS-1$ + } + + /** + * Create an image file using "png" format + * for the specified temporary file. + * + * @param icon The icon that is used for the temporary file. + * @param tmpfile The temporary file. + */ + private void createImageFromIcon(Icon icon, File imgFile) { + BufferedImage bi = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_4BYTE_ABGR); + Graphics g = bi.createGraphics(); + icon.paintIcon(dummyComponent, g, 0, 0); + g.dispose(); + try { + ImageIO.write(bi, "png", imgFile); //$NON-NLS-1$ + } + catch (IOException e) { + } + } + + /** + * Send a notification to inform the file tree for changed images. + * + * @param node The node whose image has changed. + * @param key The key used to store the images. + * @param oldImg The old image descriptor. + * @param newImg The new image descriptor. + */ + private void sendNotification(FSTreeNode node, String key, ImageDescriptor oldImg, ImageDescriptor newImg) { + if (node.peerNode != null) { + IPropertyChangeProvider viewerInput = (IPropertyChangeProvider) node.peerNode.getAdapter(IPropertyChangeProvider.class); + viewerInput.firePropertyChange(new PropertyChangeEvent(node, key, oldImg, newImg)); + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/ModificationTimeComparator.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/ModificationTimeComparator.java new file mode 100644 index 000000000..6aad6951c --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/ModificationTimeComparator.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.columns; + +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * The comparator for the tree column "Date Modified". + */ +public class ModificationTimeComparator extends FSTreeNodeComparator { + private static final long serialVersionUID = 1L; + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.columns.FSTreeNodeComparator#doCompare(org.eclipse.tcf.te.tcf.filesystem.model.FSTreeNode, org.eclipse.tcf.te.tcf.filesystem.model.FSTreeNode) + */ + @Override + public int doCompare(FSTreeNode node1, FSTreeNode node2) { + long mtime1 = node1.attr != null ? node1.attr.mtime : 0; + long mtime2 = node2.attr != null ? node2.attr.mtime : 0; + return mtime1 < mtime2 ? -1 : (mtime1 > mtime2 ? 1 : 0); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/ModificationTimeLabelProvider.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/ModificationTimeLabelProvider.java new file mode 100644 index 000000000..0cedfb5b9 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/ModificationTimeLabelProvider.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.columns; + +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * The label provider for the tree column "Date Modified". + */ +public class ModificationTimeLabelProvider extends LabelProvider { + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object) + */ + @Override + public String getText(Object element) { + if (element instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode) element; + if (node.attr != null) { + SimpleDateFormat dateFormat = new SimpleDateFormat("M/d/yyyy h:mm aa"); //$NON-NLS-1$ + return dateFormat.format(new Date(node.attr.mtime)); + } + } + return ""; //$NON-NLS-1$ + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/SizeComparator.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/SizeComparator.java new file mode 100644 index 000000000..af9b227e6 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/SizeComparator.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.columns; + +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * The comparator for the tree column "size". + */ +public class SizeComparator extends FSTreeNodeComparator { + private static final long serialVersionUID = 1L; + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.columns.FSTreeNodeComparator#doCompare(org.eclipse.tcf.te.tcf.filesystem.model.FSTreeNode, org.eclipse.tcf.te.tcf.filesystem.model.FSTreeNode) + */ + @Override + public int doCompare(FSTreeNode node1, FSTreeNode node2) { + long size1 = node1.attr != null ? node1.attr.size : 0; + long size2 = node2.attr != null ? node2.attr.size : 0; + return size1 < size2 ? -1 : (size1 > size2 ? 1 : 0); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/SizeLabelProvider.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/SizeLabelProvider.java new file mode 100644 index 000000000..489ce7940 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/SizeLabelProvider.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.columns; + +import java.text.DecimalFormat; + +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * The label provider for the tree column "size". + */ +public class SizeLabelProvider extends LabelProvider { + // The size formatter. + private static final DecimalFormat SIZE_FORMAT = new DecimalFormat(); + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object) + */ + @Override + public String getText(Object element) { + if (element instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode) element; + // Directory nodes does not have a size + if (node.isFile() && node.attr != null) { + return SIZE_FORMAT.format(node.attr.size / 1024) + " KB"; //$NON-NLS-1$ + } + } + return ""; //$NON-NLS-1$ + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/WindowsImageProvider.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/WindowsImageProvider.java new file mode 100644 index 000000000..de0529528 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/columns/WindowsImageProvider.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2012 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.te.tcf.filesystem.ui.internal.columns; + +import org.eclipse.swt.graphics.Image; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * Windows specific image provider extending the default image provider + * to retrieve the file's images based on file extension or cached file. + */ +public class WindowsImageProvider extends DefaultImageProvider { + // The background daemons that updates the images of the file system nodes. + static LabelProviderUpdateDaemon updateDaemon; + static { + updateDaemon = new LabelProviderUpdateDaemon(); + updateDaemon.start(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.columns.DefaultImageProvider#getImage(org.eclipse.tcf.te.tcf.filesystem.model.FSTreeNode) + */ + @Override + public Image getImage(FSTreeNode node) { + if (node.isRoot()) { + return node.isWindowsNode() ? updateDaemon.getDiskImage() : super.getImage(node); + } + else if (node.isDirectory()) { + return updateDaemon.getFolderImage(); + } + else if(node.isFile()) { + Image image = updateDaemon.getImage(node); + if (image == null) { + updateDaemon.enqueue(node); + image = getPredefinedImage(node); + } + return image; + } + return super.getImage(node); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/compare/EditableSharedDocumentAdapter.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/compare/EditableSharedDocumentAdapter.java new file mode 100644 index 000000000..ae087ace0 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/compare/EditableSharedDocumentAdapter.java @@ -0,0 +1,256 @@ +/******************************************************************************* + * Copyright (c) 2005, 2014 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.ui.internal.compare; + +import org.eclipse.compare.SharedDocumentAdapter; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.text.IDocument; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.IElementStateListener; + +/** + * A shared document adapter that tracks whether the element is connected to a + * shared document and whether the contents have been flushed from a compare + * viewer. When contents are flushed, this adapter will connect to the document + * provider to ensure that the changes are not lost (see + * {@link #hasBufferedContents()}). In order to avoid a leak, the buffer must + * either be saved (see + * {@link #saveDocument(IEditorInput, boolean, IProgressMonitor)}) or released + * (see {@link #releaseBuffer()}). + * <p> + * This adapter must have a one-to-one correspondence to a typed element. + * + * @since 3.7 - Copied from + * org.eclipse.team.internal.ui.synchronize.EditableSharedDocumentAdapter + */ +public class EditableSharedDocumentAdapter extends SharedDocumentAdapter implements IElementStateListener { + + private int connectionCount; + private final ISharedDocumentAdapterListener listener; + private IEditorInput bufferedKey; + + /** + * Interface that provides this adapter with the action of the typed element + * and supports call backs to the element when the adapter action changes. + */ + public interface ISharedDocumentAdapterListener { + + /** + * Method that is invoked when the adapter connects to the document + * provider. This method is only invoked when the adapter first connects + * to the document. + */ + void handleDocumentConnected(); + + /** + * Method that is invoked when the adapter disconnects from the document + * provider. This method is only invoked when the adapter no longer has + * any connection to the document provider. + */ + void handleDocumentDisconnected(); + + /** + * Method invoked when changes in the document are flushed to the + * adapter. + */ + void handleDocumentFlushed(); + + /** + * Method invoked when the file behind the shared document is deleted. + */ + void handleDocumentDeleted(); + + /** + * Method invoked when the document dirty action changes from dirty to + * clean. + */ + void handleDocumentSaved(); + } + + /** + * Create the shared document adapter for the given element. + * + * @param listener + * access to element internals + */ + public EditableSharedDocumentAdapter(ISharedDocumentAdapterListener listener) { + super(); + this.listener = listener; + } + + /* (non-Javadoc) + * @see org.eclipse.compare.SharedDocumentAdapter#connect(org.eclipse.ui.texteditor.IDocumentProvider, org.eclipse.ui.IEditorInput) + */ + @Override + public void connect(IDocumentProvider provider, IEditorInput documentKey) + throws CoreException { + super.connect(provider, documentKey); + connectionCount++; + if (connectionCount == 1) { + provider.addElementStateListener(this); + listener.handleDocumentConnected(); + } + } + + /* (non-Javadoc) + * @see org.eclipse.compare.SharedDocumentAdapter#disconnect(org.eclipse.ui.texteditor.IDocumentProvider, org.eclipse.ui.IEditorInput) + */ + @Override + public void disconnect(IDocumentProvider provider, IEditorInput documentKey) { + try { + super.disconnect(provider, documentKey); + } finally { + if (connectionCount > 0) + connectionCount--; + if (connectionCount == 0) { + provider.removeElementStateListener(this); + listener.handleDocumentDisconnected(); + } + } + } + + /** + * Return whether the element is connected to a shared document. + * + * @return whether the element is connected to a shared document + */ + public boolean isConnected() { + return connectionCount > 0; + } + + /** + * Save the shared document of the element of this adapter. + * + * @param input + * the document key of the element. + * @param monitor + * a progress monitor + * @return whether the save succeeded or not + * @throws CoreException + */ + public boolean saveDocument(IEditorInput input, IProgressMonitor monitor) + throws CoreException { + if (isConnected()) { + IDocumentProvider provider = SharedDocumentAdapter + .getDocumentProvider(input); + try { + saveDocument(provider, input, provider.getDocument(input), + true, monitor); + } finally { + // When we write the document, remove out hold on the buffer + releaseBuffer(); + } + return true; + } + return false; + } + + /** + * Release the buffer if this adapter has buffered the contents in response + * to a + * {@link #flushDocument(IDocumentProvider, IEditorInput, IDocument, boolean)} + * . + */ + public void releaseBuffer() { + if (bufferedKey != null) { + IDocumentProvider provider = SharedDocumentAdapter + .getDocumentProvider(bufferedKey); + provider.disconnect(bufferedKey); + bufferedKey = null; + } + } + + /* (non-Javadoc) + * @see org.eclipse.compare.ISharedDocumentAdapter#flushDocument(org.eclipse.ui.texteditor.IDocumentProvider, org.eclipse.ui.IEditorInput, org.eclipse.jface.text.IDocument, boolean) + */ + @Override + public void flushDocument(IDocumentProvider provider, + IEditorInput documentKey, IDocument document, boolean overwrite) + throws CoreException { + if (!hasBufferedContents()) { + // On a flush, make an extra connection to the shared document so it + // will be kept even + // if it is no longer being viewed. + bufferedKey = documentKey; + provider.connect(bufferedKey); + } + this.listener.handleDocumentFlushed(); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.IElementStateListener#elementContentAboutToBeReplaced(java.lang.Object) + */ + @Override + public void elementContentAboutToBeReplaced(Object element) { + // Nothing to do + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.IElementStateListener#elementContentReplaced(java.lang.Object) + */ + @Override + public void elementContentReplaced(Object element) { + // Nothing to do + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.IElementStateListener#elementDeleted(java.lang.Object) + */ + @Override + public void elementDeleted(Object element) { + listener.handleDocumentDeleted(); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.IElementStateListener#elementDirtyStateChanged(java.lang.Object, boolean) + */ + @Override + public void elementDirtyStateChanged(Object element, boolean isDirty) { + if (!isDirty) { + this.listener.handleDocumentSaved(); + } + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.IElementStateListener#elementMoved(java.lang.Object, java.lang.Object) + */ + @Override + public void elementMoved(Object originalElement, Object movedElement) { + // Nothing to do + } + + /** + * Return whether the adapter has buffered contents. The adapter buffers + * contents by connecting to the document through the document provider. + * This means that the adapter must be disconnected either by saving or + * discarding the buffer. + * + * @return whether the adapter has buffered contents + */ + public boolean hasBufferedContents() { + return bufferedKey != null; + } + + /** + * Override getDocumentKey in the super class to provide an editor input + * when the element is a <code>LocalTypedElement</code>. + */ + @Override + public IEditorInput getDocumentKey(Object element) { + if (element instanceof LocalTypedElement) { + LocalTypedElement localElement = (LocalTypedElement) element; + return localElement.getEditorInput(); + } + return super.getDocumentKey(element); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/compare/LocalFileSaveable.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/compare/LocalFileSaveable.java new file mode 100644 index 000000000..db636b588 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/compare/LocalFileSaveable.java @@ -0,0 +1,481 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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 + * William Chen (Wind River)- [345552] Edit the remote files with a proper editor + *******************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.ui.internal.compare; + +import org.eclipse.compare.CompareEditorInput; +import org.eclipse.compare.ICompareContainer; +import org.eclipse.compare.IContentChangeListener; +import org.eclipse.compare.IContentChangeNotifier; +import org.eclipse.compare.ISharedDocumentAdapter; +import org.eclipse.compare.SharedDocumentAdapter; +import org.eclipse.compare.contentmergeviewer.ContentMergeViewer; +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.ListenerList; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.SafeRunner; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.util.SafeRunnable; +import org.eclipse.swt.graphics.Image; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.IOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpUpload; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.compare.EditableSharedDocumentAdapter.ISharedDocumentAdapterListener; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.operations.UiExecutor; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IPropertyListener; +import org.eclipse.ui.ISaveablesLifecycleListener; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchPartConstants; +import org.eclipse.ui.Saveable; +import org.eclipse.ui.SaveablesLifecycleEvent; +import org.eclipse.ui.texteditor.IDocumentProvider; + +/** + * A <code>LocalFileSaveable</code> is used as the saveable object that provides + * the save behavior for the merge editor input(<code>MergeEditorInput</code>). + */ +public class LocalFileSaveable extends Saveable implements + IPropertyChangeListener, ISharedDocumentAdapterListener, + IContentChangeListener { + // The property listener list. + private ListenerList listeners = new ListenerList(ListenerList.IDENTITY); + + // The merge input that provides the left and the right compared elements. + private final MergeInput input; + + // The input of the editor that provides the comparing view. + private final MergeEditorInput editorInput; + + // If the current document of the file is being saved. + private boolean saving; + + // The local file element. + private LocalTypedElement fileElement; + + // The document provided by the local file. + private IDocument document; + + // If the current document has been connected. + private boolean connected; + + /** + * Create the file-based saveable comparison. + * + * @param input + * the compare input to be save + * @param editorInput + * the editor input containing the comparison + * @param fileElement + * the file element that handles the saving and change + * notification + */ + public LocalFileSaveable(MergeInput input, MergeEditorInput editorInput, LocalTypedElement fileElement) { + Assert.isNotNull(input); + + this.input = input; + this.editorInput = editorInput; + this.fileElement = fileElement; + this.fileElement.addContentChangeListener(this); + this.fileElement.setDocumentListener(this); + } + + /** + * Dispose of the saveable. + */ + public void dispose() { + fileElement.removeContentChangeListener(this); + fileElement.discardBuffer(); + fileElement.setDocumentListener(null); + } + + /** + * Performs the save. + * + * @param monitor The progress monitor. + * + * @throws CoreException If the save operation fails. + */ + protected void performSave(IProgressMonitor monitor) throws CoreException { + try { + saving = true; + monitor.beginTask(null, 100); + // First, we need to flush the viewers so the changes get buffered + // in the input + flushViewers(monitor); + // Then we tell the input to commit its changes + // Only the left is ever saveable + if (fileElement.isDirty()) { + if (fileElement.isConnected()) { + fileElement.store2Document(monitor); + } else { + fileElement.store2Cache(monitor); + } + } + } finally { + // Make sure we fire a change for the compare input to update the + // viewers + fireInputChange(); + setDirty(false); + saving = false; + monitor.done(); + //Trigger upload action + FSTreeNode node = fileElement.getFSTreeNode(); + IOpExecutor executor = new UiExecutor(); + executor.execute(new OpUpload(node)); + } + } + + /** + * Flush the contents of any viewers into the compare input. + * + * @param monitor + * a progress monitor + * @throws CoreException + */ + protected void flushViewers(IProgressMonitor monitor) throws CoreException { + editorInput.saveChanges(monitor); + } + + /** + * Fire an input change for the compare input after it has been saved. + */ + protected void fireInputChange() { + editorInput.getCompareResult().fireInputChanged(); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.Saveable#isDirty() + */ + @Override + public boolean isDirty() { + return editorInput.isSaveNeeded(); + } + + /** + * Marks the editor input dirty. + * + * @param dirty <code>True</code> if the editor is dirty, <code>false</code> if not. + */ + protected void setDirty(boolean dirty) { + if (isDirty() != dirty) { + editorInput.setDirty(dirty); + firePropertyChange(IWorkbenchPartConstants.PROP_DIRTY); + } + } + + /* (non-Javadoc) + * @see org.eclipse.ui.Saveable#getName() + */ + @Override + public String getName() { + // Return the name of the file element as held in the compare input + if (fileElement.equals(input.getLeft())) { + return input.getLeft().getName(); + } + if (fileElement.equals(input.getRight())) { + return input.getRight().getName(); + } + + // Fallback call returning name of the main non-null element of the input + // + // see org.eclipse.team.internal.ui.mapping.AbstractCompareInput#getMainElement() + return input.getName(); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.Saveable#getToolTipText() + */ + @Override + public String getToolTipText() { + return editorInput.getToolTipText(); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.Saveable#getImageDescriptor() + */ + @Override + public ImageDescriptor getImageDescriptor() { + Image image = input.getImage(); + if (image != null) + return ImageDescriptor.createFromImage(image); + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent) + */ + @Override + public void propertyChange(PropertyChangeEvent e) { + String propertyName = e.getProperty(); + if (CompareEditorInput.DIRTY_STATE.equals(propertyName)) { + boolean changed = false; + Object newValue = e.getNewValue(); + if (newValue instanceof Boolean) + changed = ((Boolean) newValue).booleanValue(); + + ContentMergeViewer cmv = (ContentMergeViewer) e.getSource(); + + if (fileElement.equals(input.getLeft())) { + if (changed && cmv.internalIsLeftDirty()) + setDirty(changed); + else if (!changed && !cmv.internalIsLeftDirty()) { + setDirty(changed); + } + } + if (fileElement.equals(input.getRight())) { + if (changed && cmv.internalIsRightDirty()) + setDirty(changed); + else if (!changed && !cmv.internalIsRightDirty()) { + setDirty(changed); + } + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.ui.Saveable#hashCode() + */ + @Override + public int hashCode() { + if (document != null) { + return document.hashCode(); + } + return input.hashCode(); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.Saveable#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + + if (!(obj instanceof Saveable)) + return false; + + if (document != null) { + Object otherDocument = ((Saveable) obj).getAdapter(IDocument.class); + + if (otherDocument == null) + return false; + + return document.equals(otherDocument); + } + + if (obj instanceof LocalFileSaveable) { + LocalFileSaveable saveable = (LocalFileSaveable) obj; + return saveable.input.equals(input); + } + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.Saveable#getAdapter(java.lang.Class) + */ + @Override + public Object getAdapter(Class adapter) { + if (adapter == IDocument.class) { + if (document != null) + return document; + if (fileElement.isConnected()) { + ISharedDocumentAdapter sda = (ISharedDocumentAdapter) fileElement + .getAdapter(ISharedDocumentAdapter.class); + if (sda != null) { + IEditorInput input = sda.getDocumentKey(fileElement); + if (input != null) { + IDocumentProvider provider = SharedDocumentAdapter + .getDocumentProvider(input); + if (provider != null) + return provider.getDocument(input); + } + } + } + } + if (adapter == IEditorInput.class) { + return fileElement.getEditorInput(); + } + return super.getAdapter(adapter); + } + + /** + * Get an ISaveablesLifecycleListener from the specified workbench + * part. + * @param part The workbench part. + * @return The listener. + */ + private ISaveablesLifecycleListener getSaveablesLifecycleListener( + IWorkbenchPart part) { + if (part instanceof ISaveablesLifecycleListener) + return (ISaveablesLifecycleListener) part; + + Object adapted = part.getAdapter(ISaveablesLifecycleListener.class); + if (adapted instanceof ISaveablesLifecycleListener) + return (ISaveablesLifecycleListener) adapted; + + adapted = Platform.getAdapterManager().loadAdapter(part, + ISaveablesLifecycleListener.class.getName()); + if (adapted instanceof ISaveablesLifecycleListener) + return (ISaveablesLifecycleListener) adapted; + + return (ISaveablesLifecycleListener) part.getSite().getService( + ISaveablesLifecycleListener.class); + } + + /** + * When the document of the local file is connected, register this saveable. + */ + private void registerSaveable() { + ICompareContainer container = editorInput.getContainer(); + IWorkbenchPart part = container.getWorkbenchPart(); + if (part != null) { + ISaveablesLifecycleListener lifecycleListener = getSaveablesLifecycleListener(part); + // Remove this saveable from the lifecycle listener + lifecycleListener.handleLifecycleEvent(new SaveablesLifecycleEvent( + part, SaveablesLifecycleEvent.POST_CLOSE, + new Saveable[] { this }, false)); + // Now fix the hashing so it uses the fConnected fDocument + IDocument document = (IDocument) getAdapter(IDocument.class); + if (document != null) { + this.document = document; + } + // Finally, add this saveable back to the listener + lifecycleListener.handleLifecycleEvent(new SaveablesLifecycleEvent( + part, SaveablesLifecycleEvent.POST_OPEN, + new Saveable[] { this }, false)); + } + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.compare.EditableSharedDocumentAdapter.ISharedDocumentAdapterListener#handleDocumentConnected() + */ + @Override + public void handleDocumentConnected() { + if (connected) + return; + connected = true; + registerSaveable(); + fileElement.setDocumentListener(null); + } + + @Override + public void handleDocumentDeleted() { + // Ignore + } + + @Override + public void handleDocumentDisconnected() { + // Ignore + } + + @Override + public void handleDocumentFlushed() { + // Ignore + } + + @Override + public void handleDocumentSaved() { + // Ignore + } + + /* + * (non-Javadoc) + * @see org.eclipse.compare.IContentChangeListener#contentChanged(org.eclipse.compare.IContentChangeNotifier) + */ + @Override + public void contentChanged(IContentChangeNotifier source) { + if (!saving) { + try { + performSave(new NullProgressMonitor()); + } catch (CoreException e) { + e.printStackTrace(); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public void doSave(IProgressMonitor monitor) throws CoreException { + if (isDirty()) { + performSave(monitor); + setDirty(false); + } + } + + /** + * Revert any changes in the buffer back to the last saved action. + * + * @param monitor + * a progress monitor on <code>null</code> if progress feedback + * is not required + */ + public void doRevert(IProgressMonitor monitor) { + if (!isDirty()) + return; + fileElement.discardBuffer(); + setDirty(false); + } + + /** + * Add a property change listener. Adding a listener that is already + * registered has no effect. + * + * @param listener + * the listener + */ + public void addPropertyListener(IPropertyListener listener) { + listeners.add(listener); + } + + /** + * Remove a property change listener. Removing a listener that is not + * registered has no effect. + * + * @param listener + * the listener + */ + public void removePropertyListener(IPropertyListener listener) { + listeners.remove(listener); + } + + /** + * Fire a property change event for this buffer. + * + * @param property + * the property that changed + */ + protected void firePropertyChange(final int property) { + Object[] allListeners = listeners.getListeners(); + for (int i = 0; i < allListeners.length; i++) { + final Object object = allListeners[i]; + SafeRunner.run(new SafeRunnable() { + @Override + public void handleException(Throwable e) { + // Ignore exception + } + @Override + public void run() throws Exception { + ((IPropertyListener) object).propertyChanged( + LocalFileSaveable.this, property); + } + }); + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/compare/LocalTypedElement.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/compare/LocalTypedElement.java new file mode 100644 index 000000000..825a66743 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/compare/LocalTypedElement.java @@ -0,0 +1,307 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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 + * William Chen (Wind River)- [345552] Edit the remote files with a proper editor + *******************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.ui.internal.compare; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.eclipse.compare.IEditableContent; +import org.eclipse.compare.ISharedDocumentAdapter; +import org.eclipse.compare.ITypedElement; +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.osgi.util.NLS; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.utils.CacheManager; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.compare.EditableSharedDocumentAdapter.ISharedDocumentAdapterListener; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.ide.FileStoreEditorInput; + +/** + * A <code>LocalTypedElement</code> extends <code>MergeTypedElement</code> and + * wraps an <code>FSTreeNode</code> so that it can be used as the left element + * of a <code>MergeEditorInput</code>. It implements the interface + * <code>IEditableContent</code> so that it is editable. + */ +public class LocalTypedElement extends MergeTypedElement implements + IEditableContent, IAdaptable, ISharedDocumentAdapterListener { + // If the current edited file is dirty. + private boolean dirty; + // The shared document adapter + private EditableSharedDocumentAdapter documentAdapter; + // The shared document listener. + private ISharedDocumentAdapterListener documentListener; + + /** + * Creates a <code>LocalTypedElement</code> for the given resource. + * + * @param resource + * the resource + */ + public LocalTypedElement(FSTreeNode node) { + super(node); + setContent(getContent()); + dirty = false; + } + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) + */ + @Override + public Object getAdapter(Class adapter) { + if (adapter == ISharedDocumentAdapter.class) { + if (documentAdapter == null) + documentAdapter = new EditableSharedDocumentAdapter(this); + return documentAdapter; + } + return Platform.getAdapterManager().getAdapter(this, adapter); + } + + /* (non-Javadoc) + * @see org.eclipse.compare.BufferedContent#setContent(byte[]) + */ + @Override + public void setContent(byte[] contents) { + dirty = true; + super.setContent(contents); + } + + /** + * Set the document listener. + * + * @param documentListener + * the document listener. + */ + public void setDocumentListener( + ISharedDocumentAdapterListener documentListener) { + this.documentListener = documentListener; + } + + /** + * Return an input stream that opens that locally cached file to provide the + * content. + * + * @return a buffered input stream containing the contents of this file + * @exception CoreException + * if the contents of this storage could not be accessed + */ + @Override + protected InputStream createStream() throws CoreException { + try { + IPath cachePath = CacheManager.getCachePath(node); + File cacheFile = cachePath.toFile(); + return new BufferedInputStream(new FileInputStream(cacheFile)); + } catch (FileNotFoundException e) { + IStatus error = new Status(IStatus.ERROR, + UIPlugin.getUniqueIdentifier(), e.getMessage(), e); + throw new CoreException(error); + } + } + + /* (non-Javadoc) + * @see org.eclipse.compare.IEditableContent#isEditable() + */ + @Override + public boolean isEditable() { + return true; + } + + /* (non-Javadoc) + * @see org.eclipse.compare.IEditableContent#replace(org.eclipse.compare.ITypedElement, org.eclipse.compare.ITypedElement) + */ + @Override + public ITypedElement replace(ITypedElement dest, ITypedElement src) { + return dest; + } + + /** + * Save the shared document for this element. The save can only be performed + * if the element is connected to a shared document. If the element is not + * connected, <code>false</code> is returned. + * + * @param overwrite + * indicates whether overwrite should be performed while saving + * the given element if necessary + * @param monitor + * a progress monitor + * @throws CoreException + */ + public boolean store2Document(IProgressMonitor monitor) + throws CoreException { + if (isConnected()) { + IEditorInput input = documentAdapter.getDocumentKey(this); + documentAdapter.saveDocument(input, monitor); + return true; + } + return false; + } + + /** + * Judges whether the content has been changed. + * + * @return + */ + public boolean isDirty() { + return dirty + || (documentAdapter != null && documentAdapter + .hasBufferedContents()); + } + + /** + * Set the dirty action. + * + * @param dirty + * The dirty action. + */ + public void setDirty(boolean dirty) { + this.dirty = dirty; + } + + /** + * If the document adapter has been connected. + * + * @return true if it is not null and connected. + */ + public boolean isConnected() { + return documentAdapter != null && documentAdapter.isConnected(); + } + + /** + * Return the path to the local file of this node. It is used to compute its + * hash code and as the title of the comparison editor. + */ + @Override + public String toString() { + File cacheFile = CacheManager.getCacheFile(node); + return cacheFile.toString(); + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.compare.EditableSharedDocumentAdapter.ISharedDocumentAdapterListener#handleDocumentConnected() + */ + @Override + public void handleDocumentConnected() { + if (documentListener != null) + documentListener.handleDocumentConnected(); + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.compare.EditableSharedDocumentAdapter.ISharedDocumentAdapterListener#handleDocumentDeleted() + */ + @Override + public void handleDocumentDeleted() { + if (documentListener != null) + documentListener.handleDocumentDeleted(); + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.compare.EditableSharedDocumentAdapter.ISharedDocumentAdapterListener#handleDocumentDisconnected() + */ + @Override + public void handleDocumentDisconnected() { + if (documentListener != null) + documentListener.handleDocumentDisconnected(); + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.compare.EditableSharedDocumentAdapter.ISharedDocumentAdapterListener#handleDocumentFlushed() + */ + @Override + public void handleDocumentFlushed() { + fireContentChanged(); + if (documentListener != null) + documentListener.handleDocumentFlushed(); + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.compare.EditableSharedDocumentAdapter.ISharedDocumentAdapterListener#handleDocumentSaved() + */ + @Override + public void handleDocumentSaved() { + if (documentListener != null) + documentListener.handleDocumentSaved(); + } + + /** + * Get an editor input for this file. + * + * @return The editor input. + */ + public IEditorInput getEditorInput() { + IPath path = CacheManager.getCachePath(node); + IFileStore fileStore = EFS.getLocalFileSystem().getStore(path); + return new FileStoreEditorInput(fileStore); + } + + /** + * Save to its local file when the document has not been connected yet. + * + * @param monitor + * The monitor that reports the progress. + */ + public void store2Cache(IProgressMonitor monitor) throws CoreException { + File cacheFile = CacheManager.getCacheFile(node); + monitor.beginTask(NLS.bind(Messages.LocalTypedElement_SavingFile, cacheFile.getName()), 100); + InputStream is = getContents(); + BufferedOutputStream bos = null; + try { + long total = cacheFile.length(); + bos = new BufferedOutputStream(new FileOutputStream(cacheFile)); + byte[] data = new byte[10 * 1024]; + int length; + long current = 0; + int currProgress = 0; + while ((length = is.read(data)) > 0) { + bos.write(data, 0, length); + bos.flush(); + current += length; + int progress = (int) (current * 100 / total); + if (currProgress != progress) { + monitor.worked(progress - currProgress); + currProgress = progress; + } + } + setDirty(false); + } catch (IOException e) { + throw new CoreException(new Status(IStatus.ERROR, + UIPlugin.getUniqueIdentifier(), e.getMessage(), e)); + } finally { + if (is != null) + try { + is.close(); + } catch (IOException ex) { + } + if (bos != null) { + try { + bos.close(); + } catch (Exception e) { + } + } + // Notify the local file element that the document has changed. + fireContentChanged(); + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/compare/MergeEditorInput.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/compare/MergeEditorInput.java new file mode 100644 index 000000000..65f8c5846 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/compare/MergeEditorInput.java @@ -0,0 +1,419 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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 + * William Chen (Wind River)- [345552] Edit the remote files with a proper editor + *******************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.ui.internal.compare; + +import java.lang.reflect.InvocationTargetException; + +import org.eclipse.compare.CompareConfiguration; +import org.eclipse.compare.CompareEditorInput; +import org.eclipse.compare.IPropertyChangeNotifier; +import org.eclipse.compare.structuremergeviewer.Differencer; +import org.eclipse.compare.structuremergeviewer.ICompareInput; +import org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener; +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.ListenerList; +import org.eclipse.core.runtime.SafeRunner; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.util.SafeRunnable; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.osgi.util.NLS; +import org.eclipse.osgi.util.TextProcessor; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.ImageConsts; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IPropertyListener; +import org.eclipse.ui.ISaveablesSource; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPartConstants; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.Saveable; +/** + * A <code>MergeEditorInput</code> is the input of a compare editor used to + * compare the local file and the remote file in a Target Explorer file system. + */ +public class MergeEditorInput extends CompareEditorInput implements + ISaveablesSource, IPropertyListener, ICompareInputChangeListener { + + // The left element is a local file which can be editable. + private LocalTypedElement left; + // The right element is the remote file which is read only. + private RemoteTypedElement right; + + // The active page of the current workbench. + private final IWorkbenchPage page; + + // The current input change listener list. + private final ListenerList inputChangeListeners = new ListenerList(ListenerList.IDENTITY); + // The current saveable for the left element, i.e., the local file. + private LocalFileSaveable saveable; + + /** + * Creates a new MergeEditorInput. + * + * @param left + * @param right + * @param page + */ + public MergeEditorInput(LocalTypedElement left, RemoteTypedElement right, IWorkbenchPage page) { + super(new CompareConfiguration()); + this.page = page; + this.left = left; + this.right = right; + configureCompare(); + } + + /** + * Configure the compare configuration using the left + * and right elements. Set the left and right label. + * Set the editable status. + */ + protected void configureCompare() { + CompareConfiguration cc = getCompareConfiguration(); + cc.setLeftEditable(true); + cc.setRightEditable(false); + + String name = TextProcessor.process(left.getName()); + String label = NLS.bind(Messages.MergeEditorInput_LocalFile, name); + cc.setLeftLabel(label); + + name = TextProcessor.process(right.toString()); + label = NLS.bind(Messages.MergeEditorInput_RemoteFile, name); + cc.setRightLabel(label); + } + + /** + * Returns <code>true</code> if the other object is of simulator + * <code>MergeEditorInput</code> and both of their corresponding fLeft and + * fRight objects are identical. The content is not considered. + */ + @Override + public boolean equals(Object obj) { + if (obj == this) + return true; + if (obj instanceof MergeEditorInput) { + MergeEditorInput other = (MergeEditorInput) obj; + return other.left.equals(left) && other.right.equals(right); + } + return false; + } + + /** + * Override hashCode to provide identical value when + * two MergeEditorInputs are equal to each other. + */ + @Override + public int hashCode() { + return left.hashCode() + right.hashCode(); + } + + /** + * Prepare the compare input of this editor input. This method is not + * intended to be overridden of extended by subclasses (but is not final for + * backwards compatibility reasons). The implementation of this method in + * this class delegates the creation of the compare input to the + * {@link #prepareCompareInput(IProgressMonitor)} method which subclasses + * must implement. + * + * @see org.eclipse.compare.CompareEditorInput#prepareInput(org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + protected Object prepareInput(IProgressMonitor monitor) + throws InvocationTargetException, InterruptedException { + right.cacheContents(monitor); + MergeInput input = new MergeInput(left, right); + setTitle(input.getName()); + return input; + } + + /* (non-Javadoc) + * @see org.eclipse.compare.CompareEditorInput#getToolTipText() + */ + @Override + public String getToolTipText() { + return NLS.bind(Messages.MergeEditorInput_CompareLeftAndRight, left, right); + } + + /* (non-Javadoc) + * @see org.eclipse.compare.CompareEditorInput#getTitle() + */ + @Override + public String getTitle() { + return NLS.bind(Messages.MergeEditorInput_CompareWithLocalCache, left.getName()); + } + + /** + * Override the super method to provide clear typed input. + */ + @Override + public MergeInput getCompareResult() { + return (MergeInput) super.getCompareResult(); + } + + /* (non-Javadoc) + * @see org.eclipse.compare.CompareEditorInput#handleDispose() + */ + @Override + protected void handleDispose() { + super.handleDispose(); + ICompareInput compareInput = getCompareResult(); + if (compareInput != null) + compareInput.removeCompareInputChangeListener(this); + if(getCompareResult()!=null){ + getSaveable().removePropertyListener(this); + getSaveable().dispose(); + } + left.discardBuffer(); + } + + /* (non-Javadoc) + * @see org.eclipse.compare.CompareEditorInput#contentsCreated() + */ + @Override + protected void contentsCreated() { + super.contentsCreated(); + if (getCompareResult() != null) { + getCompareResult().addCompareInputChangeListener(this); + getSaveable().addPropertyListener(this); + setDirty(getSaveable().isDirty()); + } + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IPropertyListener#propertyChanged(java.lang.Object, int) + */ + @Override + public void propertyChanged(Object source, int propId) { + if (propId == IWorkbenchPartConstants.PROP_DIRTY && getCompareResult()!=null) { + setDirty(getSaveable().isDirty()); + } + } + + /** + * Close the editor if it is not dirty. If it is still dirty, let the + * content merge viewer handle the compare input change. + * + * @param checkForUnsavedChanges + * whether to check for unsaved changes + * @return <code>true</code> if the editor was closed (note that the close + * may be asynchronous) + */ + protected boolean closeEditor(boolean checkForUnsavedChanges) { + if (isSaveNeeded() && checkForUnsavedChanges) { + return false; + } + final IWorkbenchPage page = getPage(); + if (page == null) + return false; + + Runnable runnable = new Runnable() { + @Override + public void run() { + Shell shell = page.getWorkbenchWindow().getShell(); + if (shell == null) + return; + + IEditorPart part = page.findEditor(MergeEditorInput.this); + getPage().closeEditor(part, false); + } + }; + if (Display.getCurrent() != null) { + runnable.run(); + } else { + Shell shell = page.getWorkbenchWindow().getShell(); + if (shell == null) + return false; + Display display = shell.getDisplay(); + display.asyncExec(runnable); + } + return true; + } + + /** + * Get the current active page. + * @return the workbench page. + */ + IWorkbenchPage getPage() { + if (page == null) + return PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + return page; + } + + /** + * Propagate the input change event to the compare input change listener list. + */ + /* default */void propogateInputChange() { + if (!inputChangeListeners.isEmpty()) { + Object[] allListeners = inputChangeListeners.getListeners(); + for (int i = 0; i < allListeners.length; i++) { + final ICompareInputChangeListener listener = (ICompareInputChangeListener) allListeners[i]; + SafeRunner.run(new SafeRunnable() { + @Override + public void handleException(Throwable e) { + // Ignore exception + } + @Override + public void run() throws Exception { + listener.compareInputChanged(getCompareResult()); + } + }); + } + } + } + + /** + * Get the fSaveable that provides the save behavior for this compare editor + * input. The {@link #createSaveable()} is called to create the fSaveable if + * it does not yet exist. This method cannot be called until after the input + * is prepared (i.e. until after the {@link #run(IProgressMonitor)} method + * is called which will in turn will invoke + * {@link #prepareCompareInput(IProgressMonitor)}. + * + * @return fSaveable that provides the save behavior for this compare editor + * input. + */ + public LocalFileSaveable getSaveable() { + if (saveable == null) { + Assert.isNotNull(getCompareResult()); + saveable = new LocalFileSaveable(getCompareResult(), this, left); + } + return saveable; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.ISaveablesSource#getActiveSaveables() + */ + @Override + public Saveable[] getActiveSaveables() { + if (getCompareResult() == null) + return new Saveable[0]; + return new Saveable[] { getSaveable() }; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.ISaveablesSource#getSaveables() + */ + @Override + public Saveable[] getSaveables() { + return getActiveSaveables(); + } + + /* (non-Javadoc) + * @see org.eclipse.compare.CompareEditorInput#addCompareInputChangeListener(org.eclipse.compare.structuremergeviewer.ICompareInput, org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener) + */ + @Override + public void addCompareInputChangeListener(ICompareInput input, + ICompareInputChangeListener listener) { + if (input == getCompareResult()) { + inputChangeListeners.add(listener); + } else { + super.addCompareInputChangeListener(input, listener); + } + } + + /* (non-Javadoc) + * @see org.eclipse.compare.CompareEditorInput#removeCompareInputChangeListener(org.eclipse.compare.structuremergeviewer.ICompareInput, org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener) + */ + @Override + public void removeCompareInputChangeListener(ICompareInput input, + ICompareInputChangeListener listener) { + if (input == getCompareResult()) { + inputChangeListeners.remove(listener); + } else { + super.removeCompareInputChangeListener(input, listener); + } + } + + /* (non-Javadoc) + * @see org.eclipse.compare.CompareEditorInput#getTitleImage() + */ + @Override + public Image getTitleImage() { + return UIPlugin.getImage(ImageConsts.COMPARE_EDITOR); + } + + /* (non-Javadoc) + * @see org.eclipse.compare.CompareEditorInput#getImageDescriptor() + */ + @Override + public ImageDescriptor getImageDescriptor() { + return UIPlugin.getImageDescriptor(ImageConsts.COMPARE_EDITOR); + } + + /* (non-Javadoc) + * @see org.eclipse.compare.CompareEditorInput#findContentViewer(org.eclipse.jface.viewers.Viewer, org.eclipse.compare.structuremergeviewer.ICompareInput, org.eclipse.swt.widgets.Composite) + */ + @Override + public Viewer findContentViewer(Viewer oldViewer, ICompareInput input, + Composite parent) { + Viewer newViewer = super.findContentViewer(oldViewer, input, parent); + boolean isNewViewer = newViewer != oldViewer; + if (isNewViewer && newViewer instanceof IPropertyChangeNotifier && getCompareResult()!=null) { + // Register the model for change events if appropriate + final IPropertyChangeNotifier dsp = (IPropertyChangeNotifier) newViewer; + dsp.addPropertyChangeListener(getSaveable()); + Control c = newViewer.getControl(); + c.addDisposeListener(new DisposeListener() { + @Override + public void widgetDisposed(DisposeEvent e) { + dsp.removePropertyChangeListener(getSaveable()); + } + }); + } + return newViewer; + } + + /* (non-Javadoc) + * @see org.eclipse.compare.CompareEditorInput#canRunAsJob() + */ + @Override + public boolean canRunAsJob() { + return true; + } + + /* (non-Javadoc) + * @see org.eclipse.compare.CompareEditorInput#isDirty() + */ + @Override + public boolean isDirty() { + if (saveable != null) + return saveable.isDirty(); + return super.isDirty(); + } + + /* (non-Javadoc) + * @see org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener#compareInputChanged(org.eclipse.compare.structuremergeviewer.ICompareInput) + */ + @Override + public void compareInputChanged(ICompareInput source) { + if (source == getCompareResult()) { + boolean closed = false; + if (source.getKind() == Differencer.NO_CHANGE) { + closed = closeEditor(true); + } + if (!closed) { + // The editor was closed either because the compare + // input still has changes or because the editor input + // is dirty. In either case, fire the changes + // to the registered listeners + propogateInputChange(); + } + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/compare/MergeInput.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/compare/MergeInput.java new file mode 100644 index 000000000..912b777ee --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/compare/MergeInput.java @@ -0,0 +1,158 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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 + * William Chen (Wind River)- [345552] Edit the remote files with a proper editor + *******************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.ui.internal.compare; + +import org.eclipse.compare.ITypedElement; +import org.eclipse.compare.structuremergeviewer.Differencer; +import org.eclipse.compare.structuremergeviewer.ICompareInput; +import org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener; +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.ListenerList; +import org.eclipse.core.runtime.SafeRunner; +import org.eclipse.jface.util.SafeRunnable; +import org.eclipse.swt.graphics.Image; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; + +/** + * An abstract compare input whose purpose is to support change notification + * through a {@link CompareInputChangeNotifier}. + */ +public class MergeInput implements ICompareInput { + + // The left element. + private ITypedElement left; + // The right element. + private ITypedElement right; + // The compare input change listener list. + private final ListenerList listeners = new ListenerList(ListenerList.IDENTITY); + + /** + * Create a <code>MergeInput</code>. + * @param left the left element. + * @param right the right element. + */ + public MergeInput(ITypedElement left, ITypedElement right) { + this.left = left; + this.right = right; + } + + /* (non-Javadoc) + * @see org.eclipse.compare.structuremergeviewer.ICompareInput#addCompareInputChangeListener(org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener) + */ + @Override + public void addCompareInputChangeListener(ICompareInputChangeListener listener) { + listeners.add(listener); + } + + /* (non-Javadoc) + * @see org.eclipse.compare.structuremergeviewer.ICompareInput#removeCompareInputChangeListener(org.eclipse.compare.structuremergeviewer.ICompareInputChangeListener) + */ + @Override + public void removeCompareInputChangeListener(ICompareInputChangeListener listener) { + listeners.remove(listener); + } + + /** + * Fire a compare input change event. This method must be called from the UI + * thread. + */ + void fireInputChanged() { + if (!listeners.isEmpty()) { + Object[] _listeners = listeners.getListeners(); + for (int i = 0; i < _listeners.length; i++) { + final ICompareInputChangeListener listener = (ICompareInputChangeListener) _listeners[i]; + SafeRunner.run(new SafeRunnable() { + @Override + public void handleException(Throwable e) { + // Ignore exception + } + @Override + public void run() throws Exception { + listener.compareInputChanged(MergeInput.this); + } + }); + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.compare.structuremergeviewer.ICompareInput#copy(boolean) + */ + @Override + public void copy(boolean leftToRight) { + Assert.isTrue(false, Messages.MergeInput_CopyNotSupported); + } + + /* (non-Javadoc) + * @see org.eclipse.compare.structuremergeviewer.ICompareInput#getAncestor() + */ + @Override + public ITypedElement getAncestor() { + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.compare.structuremergeviewer.ICompareInput#getImage() + */ + @Override + public Image getImage() { + ITypedElement element = getMainElement(); + return element == null ? null : element.getImage(); + } + + /** + * Return the main non-null element that identifies this input. By default, + * the fLeft is returned if non-null. If the fLeft is null, the fRight is + * returned. If both the fLeft and fRight are null the ancestor is returned. + * + * @return the main non-null element that identifies this input + */ + private ITypedElement getMainElement() { + if (left != null) + return left; + if (right != null) + return right; + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.compare.structuremergeviewer.ICompareInput#getKind() + */ + @Override + public int getKind() { + return Differencer.CHANGE; + } + + /* (non-Javadoc) + * @see org.eclipse.compare.structuremergeviewer.ICompareInput#getLeft() + */ + @Override + public ITypedElement getLeft() { + return left; + } + + /* (non-Javadoc) + * @see org.eclipse.compare.structuremergeviewer.ICompareInput#getName() + */ + @Override + public String getName() { + ITypedElement element = getMainElement(); + return element == null ? null : element.getName(); + } + + /* (non-Javadoc) + * @see org.eclipse.compare.structuremergeviewer.ICompareInput#getRight() + */ + @Override + public ITypedElement getRight() { + return right; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/compare/MergeTypedElement.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/compare/MergeTypedElement.java new file mode 100644 index 000000000..37e96269d --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/compare/MergeTypedElement.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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 + * William Chen (Wind River)- [345552] Edit the remote files with a proper editor + *******************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.ui.internal.compare; + +import org.eclipse.compare.BufferedContent; +import org.eclipse.compare.CompareUI; +import org.eclipse.compare.ITypedElement; +import org.eclipse.swt.graphics.Image; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * A <code>MergeTypedElement</code> wraps an <code>FSTreeNode</code> so that it + * can be used as input for the differencing engine (<code>ITypedElement</code>). + */ +public abstract class MergeTypedElement extends BufferedContent implements ITypedElement { + // The File System tree node to be wrapped. + protected FSTreeNode node; + + /** + * Create a MergeTypedElement for the given node. + * + * @param node + * The node. + */ + public MergeTypedElement(FSTreeNode node) { + this.node = node; + } + + /* (non-Javadoc) + * @see org.eclipse.compare.ITypedElement#getImage() + */ + @Override + public Image getImage() { + return CompareUI.getImage(getType()); + } + + /** + * Return the tree node wrapped. + * + * @return The tree node of the file + */ + public FSTreeNode getFSTreeNode() { + return node; + } + + /* (non-Javadoc) + * @see org.eclipse.compare.ITypedElement#getType() + */ + @Override + public String getType() { + if (node != null) { + if (node.isDirectory()) { + return ITypedElement.FOLDER_TYPE; + } + String s = node.name; + int dot = s.lastIndexOf('.'); + if (dot != -1) s = s.substring(dot + 1); + return s; + } + return ITypedElement.UNKNOWN_TYPE; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object other) { + if (other instanceof ITypedElement) { + return toString().equals(other.toString()); + } + return super.equals(other); + } + + /* (non-Javadoc) + * @see org.eclipse.compare.ITypedElement#getName() + */ + @Override + public String getName() { + return node.name; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + * + * Returns the hash code of the name. + */ + @Override + public int hashCode() { + return toString().hashCode(); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/compare/RemoteTypedElement.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/compare/RemoteTypedElement.java new file mode 100644 index 000000000..b7e82c474 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/compare/RemoteTypedElement.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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 + * William Chen (Wind River)- [345552] Edit the remote files with a proper editor + *******************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.ui.internal.compare; + +import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.InvocationTargetException; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.osgi.util.NLS; +import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IOperation; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpOutStreamOp; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; + +/** + * A <code>RemoteTypedElement</code> wraps an <code>FSTreeNode</code> so that it + * can be used as input for the differencing engine (<code>ITypedElement</code>) + * as the right element of the comparison editor. + * + * @since 3.7 + */ +public class RemoteTypedElement extends MergeTypedElement { + /** + * Creates a <code>RemoteTypedElement</code> for the given node. + * + * @param node + * the tree node. + */ + public RemoteTypedElement(FSTreeNode node) { + super(node); + } + + /** + * Return an input stream that opens that remote file to provide the stream + * content. + * + * @return a buffered input stream containing the contents of this file + * @exception CoreException + * if the contents of this storage could not be accessed + */ + @Override + protected InputStream createStream() throws CoreException { + try { + return node.getLocationURL().openStream(); + } catch (IOException e) { + Status error = new Status(IStatus.ERROR, + UIPlugin.getUniqueIdentifier(), e.getMessage(), e); + throw new CoreException(error); + } + } + + /** + * Download the remote file and save the content so that it is cached for + * getContents call. + * + * @param monitor + * The monitor used to display downloading progress. + * @throws InvocationTargetException + * throws when an exception occurs during downloading. + * InterruptedException + * throws when the loading process is canceled. + */ + public void cacheContents(IProgressMonitor monitor) + throws InvocationTargetException, InterruptedException { + monitor.beginTask(NLS.bind(Messages.RemoteTypedElement_DowloadingFile, node.name), 100); + OutputStream output = null; + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + output = new BufferedOutputStream(baos); + monitor.beginTask(Messages.RemoteTypedElement_GettingRemoteContent + node.name, 100); + IOperation operation = new OpOutStreamOp(node, output); + operation.run(monitor); + if (!monitor.isCanceled()) { + setContent(baos.toByteArray()); + } + } + + /** + * Return the external form of the URL to the remote file of this node. It + * is used to compute its hash code and as the title of the comparison + * editor. + */ + @Override + public String toString() { + return node.getLocationURI().toString(); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/decorators/PhantomDecorator.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/decorators/PhantomDecorator.java new file mode 100644 index 000000000..8247ef500 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/decorators/PhantomDecorator.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.decorators; + +import org.eclipse.jface.viewers.ILabelDecorator; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Image; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.ui.jface.images.AbstractImageDescriptor; +/** + * The label decorator to decorate the FSTreeNodes that are cut or hidden. + */ +public class PhantomDecorator extends LabelProvider implements ILabelDecorator { + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.ILabelDecorator#decorateImage(org.eclipse.swt.graphics.Image, java.lang.Object) + */ + @Override + public Image decorateImage(Image image, Object element) { + if (element instanceof FSTreeNode && image != null) { + // Create the cut image for the image to be decorated. + AbstractImageDescriptor descriptor = new PhantomImageDescriptor(image); + return UIPlugin.getSharedImage(descriptor); + } + return null; + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.ILabelDecorator#decorateText(java.lang.String, java.lang.Object) + */ + @Override + public String decorateText(String text, Object element) { + // Do not decorate its label. + return null; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/decorators/PhantomImageDescriptor.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/decorators/PhantomImageDescriptor.java new file mode 100644 index 000000000..1200daf7b --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/decorators/PhantomImageDescriptor.java @@ -0,0 +1,224 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.decorators; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.PaletteData; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.ui.jface.images.AbstractImageDescriptor; + +/** + * The descriptor for a phantom-like image. + */ +public class PhantomImageDescriptor extends AbstractImageDescriptor { + // The alpha data when highlight the base image. + private static final int HIGHLIGHT_ALPHA = 127; + // The key to store the cut mask image. + private static final String ID_FS_NODE_CUT_MASK = "FS_NODE_CUT_MASK@"; //$NON-NLS-1$ + // The key to store the cut decoration image. + private static final String ID_FS_NODE_CUT = "FS_NODE_CUT@"; //$NON-NLS-1$ + // the base image to decorate with overlays + private Image baseImage; + + /** + * Constructor. + */ + public PhantomImageDescriptor(final Image baseImage) { + super(UIPlugin.getDefault().getImageRegistry()); + this.baseImage = baseImage; + // build up the key for the image registry + String key = ID_FS_NODE_CUT + baseImage.hashCode(); + setDecriptorKey(key); + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.resource.CompositeImageDescriptor#drawCompositeImage(int, int) + */ + @Override + protected void drawCompositeImage(int width, int height) { + drawCentered(baseImage, width, height); + drawCentered(getMaskImage(), width, height); + } + + /** + * Get the mask image of the base image. The mask image is an image which + * has the data of the decorator image and the transparent mask of the + * base image. The decorator image (the key of which is CUT_DECORATOR_IMAGE) + * is a translucent white board, which will be drawn over the base image and + * make the base image sightly lighter. Try to the cut a file in a file explorer + * on Windows host, you'll see its icon is changed to a lighter version. The + * mask image created by this method will be drawn over the base image and + * generate the similar effect. + * + * @return The mask image used to decorate the base image. + */ + private Image getMaskImage() { + String maskKey = ID_FS_NODE_CUT_MASK + baseImage.hashCode(); + Image maskImage = UIPlugin.getImage(maskKey); + if (maskImage == null) { + ImageData baseData = baseImage.getImageData(); + PaletteData palette = new PaletteData(new RGB[]{new RGB(255, 255, 255), new RGB(0,0,0)}); + ImageData imageData = new ImageData(baseData.width, baseData.height, 1, palette); + // Get the base image's transparency mask. + imageData.alphaData = createAlphaData(); + maskImage = new Image(baseImage.getDevice(), imageData); + UIPlugin.getDefault().getImageRegistry().put(maskKey, maskImage); + } + return maskImage; + } + + /** + * Create the alpha data that will be used in the mask image data. + * + * @return The alpha data. + */ + private byte[] createAlphaData() { + ImageData imageData = baseImage.getImageData(); + if (imageData.maskData != null) { + if (imageData.depth == 32) { + return maskAlpha32(); + } + return maskAlpha(); + } + return nonMaskAlpha(); + } + + /** + * Create the alpha data for the base image that has no mask data. + * + * @return The alpha data. + */ + private byte[] nonMaskAlpha() { + ImageData imageData = baseImage.getImageData(); + Assert.isTrue(imageData.maskData == null); + + byte[] alphaData = new byte[imageData.width * imageData.height]; + int i = 0; + for (int y = 0; y < imageData.height; y++) { + for (int x = 0; x < imageData.width; x++) { + int pixel = imageData.getPixel(x, y); + int alpha = 255; + if (imageData.transparentPixel != -1 && imageData.transparentPixel == pixel) { + // If it has a transparent pixel and the current pixel is the transparent. + alpha = 0; + } + else if (imageData.alpha != -1) { + // If it has a global alpha value. + alpha = imageData.alpha; + } + else if (imageData.alphaData != null) { + // If it has alpha data. + alpha = imageData.getAlpha(x, y); + } + alphaData[i++] = (byte) (alpha * HIGHLIGHT_ALPHA / 255); + } + } + return alphaData; + } + + /** + * Create the alpha data for the base image that has mask data, and the color depth is not of + * 32-bit. + * + * @return The alpha data + */ + private byte[] maskAlpha() { + ImageData imageData = baseImage.getImageData(); + Assert.isTrue(imageData.maskData != null && imageData.depth != 32); + + ImageData mask = imageData.getTransparencyMask(); + // Get the black index. + int blackIndex = getBlackIndex(mask); + byte[] alphaData = new byte[imageData.width * imageData.height]; + int i = 0; + for (int y = 0; y < imageData.height; y++) { + for (int x = 0; x < imageData.width; x++) { + int alpha = mask.getPixel(x, y) == blackIndex ? 0 : 255; + alphaData[i++] = (byte) (alpha * HIGHLIGHT_ALPHA / 255); + } + } + return alphaData; + } + + /** + * Create the alpha data for the base image that has mask data and the color depth is of 32-bit. + * + * @return The alpha data. + */ + private byte[] maskAlpha32() { + ImageData imageData = baseImage.getImageData(); + Assert.isTrue(imageData.maskData != null && imageData.depth == 32); + + ImageData mask = imageData.getTransparencyMask(); + // Get the black index. + int blackIndex = getBlackIndex(mask); + // Calculate the alpha mask and the alpha shift. + int alphaMask = ~(imageData.palette.redMask | imageData.palette.greenMask | imageData.palette.blueMask); + int alphaShift = 0; + while (alphaMask != 0 && ((alphaMask >>> alphaShift) & 1) == 0) + alphaShift++; + byte[] alphaData = new byte[imageData.width * imageData.height]; + int i = 0; + for (int y = 0; y < imageData.height; y++) { + for (int x = 0; x < imageData.width; x++) { + int pixel = imageData.getPixel(x, y); + int alpha = (pixel & alphaMask) >>> alphaShift; + if (alpha <= 0 || alpha > 255) { + // If the alpha value is illegal, try to get it from the mask data. + alpha = mask.getPixel(x, y) == blackIndex ? 0 : 255; + } + alphaData[i++] = (byte) (alpha * HIGHLIGHT_ALPHA / 255); + } + } + return alphaData; + } + + /** + * Get the black index from the palette of the mask data. + * + * @param mask + * @return + */ + private int getBlackIndex(ImageData mask) { + RGB[] rgbs = mask.getRGBs(); + if (rgbs != null) { + for (int i = 0; i < rgbs.length; i++) { + RGB rgb = rgbs[i]; + if (rgb.red == 0 && rgb.green == 0 && rgb.blue == 0) { + return i; + } + } + } + return 0; + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.resource.CompositeImageDescriptor#getSize() + */ + @Override + protected Point getSize() { + return new Point(baseImage.getImageData().width, baseImage.getImageData().height); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.ide.util.ui.AbstractImageDescriptor#getBaseImage() + */ + @Override + protected Image getBaseImage() { + return baseImage; + } +}
\ No newline at end of file diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/dnd/CommonDnD.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/dnd/CommonDnD.java new file mode 100644 index 000000000..2a3d832de --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/dnd/CommonDnD.java @@ -0,0 +1,409 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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.te.tcf.filesystem.ui.internal.dnd; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.util.LocalSelectionTransfer; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.DragSourceEvent; +import org.eclipse.swt.dnd.FileTransfer; +import org.eclipse.swt.dnd.TransferData; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tcf.te.runtime.callback.Callback; +import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback; +import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IConfirmCallback; +import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IOperation; +import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.runtime.IRuntimeModel; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.IOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.JobExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpCopy; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpMove; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpRefresh; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpUpload; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.utils.CacheManager; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.core.model.ModelManager; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.ImageConsts; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.handlers.MoveCopyCallback; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.operations.UiExecutor; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.ui.PlatformUI; +/** + * Common DnD operations shared by File Explorer and Target Explorer. + */ +public class CommonDnD implements IConfirmCallback { + + /** + * If the current selection is draggable. + * + * @param selection The currently selected nodes. + * @return true if it is draggable. + */ + public boolean isDraggable(IStructuredSelection selection) { + if (selection.isEmpty()) { + return false; + } + Object[] objects = selection.toArray(); + for (Object object : objects) { + if (!isDraggableObject(object)) { + return false; + } + } + return true; + } + + /** + * If the specified object is a draggable element. + * + * @param object The object to be dragged. + * @return true if it is draggable. + */ + private boolean isDraggableObject(Object object) { + if (object instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode) object; + return !node.isRoot() && (node.isWindowsNode() && !node.isReadOnly() || !node.isWindowsNode() && node.isWritable()); + } + return false; + } + + /** + * Perform the drop operation over dragged files to the specified target folder. + * + * @param viewer the tree viewer to be refreshed after dragging. + * @param files The files being dropped. + * @param operations the current dnd operations. + * @param target the target folder the files to be dropped to. + * @return true if the dropping is successful. + */ + public boolean dropFiles(TreeViewer viewer, String[] files, int operations, FSTreeNode target) { + IOpExecutor executor = null; + if ((operations & DND.DROP_MOVE) != 0) { + String question; + if (files.length == 1) { + question = NLS.bind(Messages.FSDropTargetListener_MovingWarningSingle, files[0]); + } + else { + question = NLS.bind(Messages.FSDropTargetListener_MovingWarningMultiple, Integer.valueOf(files.length)); + } + Shell parent = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + if (MessageDialog.openQuestion(parent, Messages.FSDropTargetListener_ConfirmMoveTitle, question)) { + ICallback callback = getMoveCallback(viewer, files, target); + executor = new UiExecutor(callback); + } + } + else if ((operations & DND.DROP_COPY) != 0) { + ICallback callback = getCopyCallback(viewer, files, target); + executor = new UiExecutor(callback); + } + if (executor != null) { + IStatus status = executor.execute(new OpUpload(files, target, this)); + return status != null && status.isOK(); + } + return false; + } + + /** + * Get the callback that refresh and select the files being dragged when the dragging gesture is + * copying. + * + * @param viewer the tree viewer to be refreshed after dragging. + * @param files The files being dragged. + * @param target The target folder to drag the files to. + * @return callback that handles refreshing and selection. + */ + private ICallback getCopyCallback(final TreeViewer viewer, final String[] files, final FSTreeNode target) { + return new Callback() { + @Override + protected void internalDone(Object caller, IStatus status) { + if (status.isOK()) { + IOpExecutor executor = new JobExecutor(getSelectionCallback(viewer, files, target)); + executor.execute(new OpRefresh(target)); + } + } + }; + } + + /** + * Get the callback that delete the dragged source files, refresh and select the files being + * dragged when the dragging gesture is moving. + * + * @param viewer the tree viewer to be refreshed after dragging. + * @param files The files being dragged. + * @param target The target folder to drag the files to. + * @return callback that handles deletion, refreshing and selection. + */ + private ICallback getMoveCallback(final TreeViewer viewer, final String[] files, final FSTreeNode target) { + return new Callback() { + @Override + protected void internalDone(Object caller, IStatus status) { + if (status.isOK()) { + boolean successful = true; + for (String path : files) { + File file = new File(path); + successful &= file.delete(); + } + if (successful) { + IRuntimeModel model = ModelManager.getRuntimeModel(target.peerNode); + IOpExecutor executor = new JobExecutor(getSelectionCallback(viewer, files, target)); + executor.execute(new OpRefresh(model.getRoot())); + } + } + } + }; + } + + /** + * Get the callback that refresh the files being dragged after moving or copying. + * + * @param viewer the tree viewer to be refreshed after dragging. + * @param paths The paths of the files being dragged. + * @param target The target folder to drag the files to. + * @return callback that handles refreshing and selection. + */ + ICallback getSelectionCallback(final TreeViewer viewer, final String[] paths, final FSTreeNode target) { + return new Callback() { + @Override + protected void internalDone(Object caller, IStatus status) { + if(status.isOK()) { + List<FSTreeNode> nodes = new ArrayList<FSTreeNode>(); + List<FSTreeNode> children = target.getChildren(); + for (String path : paths) { + File file = new File(path); + String name = file.getName(); + for (FSTreeNode child : children) { + if (name.equals(child.name)) { + nodes.add(child); + break; + } + } + } + if (viewer != null) { + updateViewer(viewer, target, nodes); + } + } + } + }; + } + + /** + * Update the tree viewer after DnD and select the nodes that being dropped. + * + * @param viewer The tree viewer in which the DnD takes place. + * @param target The target node that the drop operation happens. + * @param nodes The nodes that are being dropped. + */ + protected void updateViewer(final TreeViewer viewer, final FSTreeNode target, final List<FSTreeNode> nodes) { + if (Display.getCurrent() != null) { + viewer.refresh(target); + IStructuredSelection selection = new StructuredSelection(nodes.toArray()); + viewer.setSelection(selection, true); + } + else { + PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable(){ + @Override + public void run() { + updateViewer(viewer, target, nodes); + }}); + } + } + + /** + * Perform the drop operation over dragged selection. + * + * @param aTarget the target Object to be moved to. + * @param operations the current dnd operations. + * @param selection The local selection being dropped. + * @return true if the dropping is successful. + */ + public boolean dropLocalSelection(FSTreeNode target, int operations, IStructuredSelection selection) { + List<FSTreeNode> nodes = selection.toList(); + IOpExecutor executor = null; + IOperation operation = null; + if ((operations & DND.DROP_MOVE) != 0) { + operation = new OpMove(nodes, target, new MoveCopyCallback()); + executor = new UiExecutor(new Callback(){ + @Override + protected void internalDone(Object caller, IStatus status) { + UIPlugin.getClipboard().clear(); + } + }); + } + else if ((operations & DND.DROP_COPY) != 0) { + FSTreeNode dest = getCopyDestination(target, nodes); + boolean cpPerm = UIPlugin.isCopyPermission(); + boolean cpOwn = UIPlugin.isCopyOwnership(); + operation = new OpCopy(nodes, dest, cpPerm, cpOwn, new MoveCopyCallback()); + executor = new UiExecutor(); + } + if (operation != null && executor != null) { + IStatus status = executor.execute(operation); + return status != null && status.isOK(); + } + return false; + } + + /** + * Return an appropriate destination directory for copying according to the specified hovered + * node. If the hovered node is a file, then return its parent directory. If the hovered node is + * a directory, then return its self if it is not a node being copied. Return its parent + * directory if it is a node being copied. + * + * @param hovered + * @param nodes + * @return + */ + private FSTreeNode getCopyDestination(FSTreeNode hovered, List<FSTreeNode> nodes) { + if (hovered.isFile()) { + return hovered.getParent(); + } + else if (hovered.isDirectory()) { + for (FSTreeNode node : nodes) { + if (node == hovered) { + return hovered.getParent(); + } + } + } + return hovered; + } + + /** + * Validate dropping when the elements being dragged are files. + * + * @param target The target object. + * @param operation The DnD operation. + * @param transferType The transfered data simulator. + * @return true if it is valid for dropping. + */ + public boolean validateFilesDrop(Object target, int operation, TransferData transferType) { + FileTransfer transfer = FileTransfer.getInstance(); + String[] elements = (String[]) transfer.nativeToJava(transferType); + if (elements.length > 0) { + boolean moving = (operation & DND.DROP_MOVE) != 0; + boolean copying = (operation & DND.DROP_COPY) != 0; + FSTreeNode hovered = (FSTreeNode) target; + if (hovered.isFile() && copying) { + hovered = hovered.getParent(); + } + return hovered.isDirectory() && hovered.isWritable() && (moving || copying); + } + return false; + } + + /** + * Validate dropping when the elements being dragged are local selection. + * + * @param target The target object. + * @param operation The DnD operation. + * @param transferType The transfered data simulator. + * @return true if it is valid for dropping. + */ + public boolean validateLocalSelectionDrop(Object target, int operation, TransferData transferType) { + FSTreeNode hovered = (FSTreeNode) target; + LocalSelectionTransfer transfer = LocalSelectionTransfer.getTransfer(); + IStructuredSelection selection = (IStructuredSelection) transfer.getSelection(); + List<FSTreeNode> nodes = selection.toList(); + boolean moving = (operation & DND.DROP_MOVE) != 0; + boolean copying = (operation & DND.DROP_COPY) != 0; + if (hovered.isDirectory() && hovered.isWritable() && (moving || copying)) { + FSTreeNode head = nodes.get(0); + String hid = head.peerNode.getPeerId(); + String tid = hovered.peerNode.getPeerId(); + if (hid.equals(tid)) { + for (FSTreeNode node : nodes) { + if (moving && node == hovered || node.isAncestorOf(hovered)) { + return false; + } + } + return true; + } + } + else if (hovered.isFile() && copying) { + hovered = hovered.getParent(); + return validateLocalSelectionDrop(hovered, operation, transferType); + } + return false; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.interfaces.IConfirmCallback#requires(java.lang.Object) + */ + @Override + public boolean requires(Object object) { + return true; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.interfaces.IConfirmCallback#confirms(java.lang.Object) + */ + @Override + public int confirms(Object object) { + final int[] results = new int[1]; + final File file = (File) object; + Display display = PlatformUI.getWorkbench().getDisplay(); + display.syncExec(new Runnable() { + @Override + public void run() { + Shell parent = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + String title = Messages.FSUpload_OverwriteTitle; + String message = NLS.bind(Messages.FSUpload_OverwriteConfirmation, file.getName()); + final Image titleImage = UIPlugin.getImage(ImageConsts.DELETE_READONLY_CONFIRM); + MessageDialog qDialog = new MessageDialog(parent, title, null, message, + MessageDialog.QUESTION, new String[] {Messages.FSUpload_Yes, + Messages.FSUpload_YesToAll, Messages.FSUpload_No, Messages.FSUpload_Cancel}, 0) { + @Override + public Image getQuestionImage() { + return titleImage; + } + }; + results[0] = qDialog.open(); + } + }); + return results[0]; + } + + /* + * (non-Javadoc) + * @see org.eclipse.swt.dnd.DragSourceListener#dragSetData(org.eclipse.swt.dnd.DragSourceEvent) + */ + public boolean setDragData(DragSourceEvent anEvent) { + if (LocalSelectionTransfer.getTransfer().isSupportedType(anEvent.dataType)) { + anEvent.data = LocalSelectionTransfer.getTransfer().getSelection(); + return true; + } + else if (FileTransfer.getInstance().isSupportedType(anEvent.dataType)) { + IStructuredSelection selection = (IStructuredSelection) LocalSelectionTransfer.getTransfer().getSelection(); + List<FSTreeNode> nodes = selection.toList(); + List<String> paths = new ArrayList<String>(); + for(FSTreeNode node : nodes) { + File file = CacheManager.getCacheFile(node); + if(file.exists()) { + paths.add(file.getAbsolutePath()); + } + } + if (!paths.isEmpty()) anEvent.data = paths.toArray(new String[paths.size()]); + return !paths.isEmpty(); + } + return false; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/dnd/FSDragAdapterAssistant.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/dnd/FSDragAdapterAssistant.java new file mode 100644 index 000000000..aaffe7f23 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/dnd/FSDragAdapterAssistant.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.dnd; + +import org.eclipse.jface.util.LocalSelectionTransfer; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.dnd.DragSourceEvent; +import org.eclipse.swt.dnd.FileTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.ui.navigator.CommonDragAdapterAssistant; + +/** + * The drag assistant used by Target Explorer to extend its DnD support to FSTreeNode elements. + */ +public class FSDragAdapterAssistant extends CommonDragAdapterAssistant { + // The common dnd operation + CommonDnD dnd; + + /** + * Create an instance. + */ + public FSDragAdapterAssistant() { + dnd = new CommonDnD(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.navigator.CommonDragAdapterAssistant#dragStart(org.eclipse.swt.dnd.DragSourceEvent, org.eclipse.jface.viewers.IStructuredSelection) + */ + @Override + public void dragStart(DragSourceEvent anEvent, IStructuredSelection aSelection) { + anEvent.doit = dnd.isDraggable(aSelection); + LocalSelectionTransfer.getTransfer().setSelection(aSelection); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.navigator.CommonDragAdapterAssistant#getSupportedTransferTypes() + */ + @Override + public Transfer[] getSupportedTransferTypes() { + return new Transfer[] {FileTransfer.getInstance()}; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.navigator.CommonDragAdapterAssistant#setDragData(org.eclipse.swt.dnd.DragSourceEvent, org.eclipse.jface.viewers.IStructuredSelection) + */ + @Override + public boolean setDragData(DragSourceEvent anEvent, IStructuredSelection aSelection) { + return dnd.setDragData(anEvent); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/dnd/FSDragSourceListener.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/dnd/FSDragSourceListener.java new file mode 100644 index 000000000..e3854474b --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/dnd/FSDragSourceListener.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.dnd; + +import org.eclipse.jface.util.LocalSelectionTransfer; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.dnd.DragSourceEvent; +import org.eclipse.swt.dnd.DragSourceListener; + +/** + * The drag source listener for the file tree of Target Explorer. + */ +public class FSDragSourceListener implements DragSourceListener { + // The tree viewer in which the DnD gesture happens. + private TreeViewer viewer; + // The common dnd operation + CommonDnD dnd; + + /** + * Create an FSDragSourceListener using the specified tree viewer. + * + * @param viewer The file system tree viewer. + */ + public FSDragSourceListener(TreeViewer viewer) { + this.viewer = viewer; + dnd = new CommonDnD(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.swt.dnd.DragSourceListener#dragStart(org.eclipse.swt.dnd.DragSourceEvent) + */ + @Override + public void dragStart(DragSourceEvent event) { + IStructuredSelection aSelection = (IStructuredSelection) viewer.getSelection(); + event.doit = dnd.isDraggable(aSelection); + LocalSelectionTransfer.getTransfer().setSelection(aSelection); + } + + /* + * (non-Javadoc) + * @see org.eclipse.swt.dnd.DragSourceListener#dragSetData(org.eclipse.swt.dnd.DragSourceEvent) + */ + @Override + public void dragSetData(DragSourceEvent event) { + event.doit = dnd.setDragData(event); + } + + /* + * (non-Javadoc) + * @see org.eclipse.swt.dnd.DragSourceListener#dragFinished(org.eclipse.swt.dnd.DragSourceEvent) + */ + @Override + public void dragFinished(DragSourceEvent event) { + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/dnd/FSDropAdapterAssistant.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/dnd/FSDropAdapterAssistant.java new file mode 100644 index 000000000..d3ab481cb --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/dnd/FSDropAdapterAssistant.java @@ -0,0 +1,115 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.dnd; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.util.LocalSelectionTransfer; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.dnd.DropTargetEvent; +import org.eclipse.swt.dnd.FileTransfer; +import org.eclipse.swt.dnd.TransferData; +import org.eclipse.swt.widgets.Display; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.ui.views.interfaces.IUIConstants; +import org.eclipse.ui.IViewReference; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.navigator.CommonDropAdapter; +import org.eclipse.ui.navigator.CommonDropAdapterAssistant; +import org.eclipse.ui.navigator.CommonNavigator; + +/** + * The drop assistant used by Target Explorer to extend its DnD support to FSTreeNode elements. + */ +public class FSDropAdapterAssistant extends CommonDropAdapterAssistant { + // The common dnd operation + CommonDnD dnd; + + /** + * Create an instance. + */ + public FSDropAdapterAssistant() { + dnd = new CommonDnD(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.navigator.CommonDropAdapterAssistant#validateDrop(java.lang.Object, int, org.eclipse.swt.dnd.TransferData) + */ + @Override + public IStatus validateDrop(Object target, int operation, TransferData transferType) { + boolean valid = false; + if (target instanceof FSTreeNode) { + if (LocalSelectionTransfer.getTransfer().isSupportedType(transferType)) { + valid = dnd.validateLocalSelectionDrop(target, operation, transferType); + } + else if(FileTransfer.getInstance().isSupportedType(transferType)) { + valid = dnd.validateFilesDrop(target, operation, transferType); + } + } + return valid ? Status.OK_STATUS : Status.CANCEL_STATUS; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.navigator.CommonDropAdapterAssistant#isSupportedType(org.eclipse.swt.dnd.TransferData) + */ + @Override + public boolean isSupportedType(TransferData aTransferType) { + if(FileTransfer.getInstance().isSupportedType(aTransferType)) + return true; + return super.isSupportedType(aTransferType); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.navigator.CommonDropAdapterAssistant#handleDrop(org.eclipse.ui.navigator.CommonDropAdapter, org.eclipse.swt.dnd.DropTargetEvent, java.lang.Object) + */ + @Override + public IStatus handleDrop(CommonDropAdapter aDropAdapter, DropTargetEvent aDropTargetEvent, Object aTarget) { + boolean sucess = false; + TransferData transferType = aDropTargetEvent.currentDataType; + if (LocalSelectionTransfer.getTransfer().isSupportedType(transferType)) { + IStructuredSelection selection = (IStructuredSelection) aDropTargetEvent.data; + int operations = aDropAdapter.getCurrentOperation(); + FSTreeNode target = (FSTreeNode) aTarget; + sucess = dnd.dropLocalSelection(target, operations, selection); + } + else if(FileTransfer.getInstance().isSupportedType(transferType)) { + String[] files = (String[]) aDropTargetEvent.data; + int operations = aDropAdapter.getCurrentOperation(); + FSTreeNode target = (FSTreeNode) aTarget; + sucess = dnd.dropFiles(getCommonViewer(), files, operations, target); + } + return sucess ? Status.OK_STATUS : Status.CANCEL_STATUS; + } + + /** + * Get the tree viewer of Target Explorer view. + * + * @return The tree viewer of Target Explorer view or null if the view is not found. + */ + private TreeViewer getCommonViewer() { + Assert.isNotNull(Display.getCurrent()); + IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + Assert.isNotNull(window); + IViewReference[] references = window.getActivePage().getViewReferences(); + for(IViewReference reference : references) { + if(reference.getId().equals(IUIConstants.ID_EXPLORER)) { + CommonNavigator navigator = (CommonNavigator) reference.getPart(true); + return navigator.getCommonViewer(); + } + } + return null; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/dnd/FSDropTargetListener.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/dnd/FSDropTargetListener.java new file mode 100644 index 000000000..be8185fd0 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/dnd/FSDropTargetListener.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.dnd; + +import org.eclipse.jface.util.LocalSelectionTransfer; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.ViewerDropAdapter; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.DropTargetEvent; +import org.eclipse.swt.dnd.FileTransfer; +import org.eclipse.swt.dnd.TransferData; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * The drop target listener for the file tree of Target Explorer. + */ +public class FSDropTargetListener extends ViewerDropAdapter { + // The tree viewer that the drop listener attached to. + TreeViewer viewer; + // The common dnd operation + CommonDnD dnd; + /** + * Create FSDropTargetListener using the viewer. + * + * @param viewer The file system tree viewer. + */ + public FSDropTargetListener(TreeViewer viewer) { + super(viewer); + this.viewer = viewer; + dnd = new CommonDnD(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.ViewerDropAdapter#dragEnter(org.eclipse.swt.dnd.DropTargetEvent) + */ + @Override + public void dragEnter(DropTargetEvent event) { + if (FileTransfer.getInstance().isSupportedType(event.currentDataType)) { + // Force the operation of file transfer from external application to DROP_COPY + event.detail = DND.DROP_COPY; + } + super.dragEnter(event); + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.ViewerDropAdapter#validateDrop(java.lang.Object, int, org.eclipse.swt.dnd.TransferData) + */ + @Override + public boolean validateDrop(Object target, int operation, TransferData transferType) { + if (target instanceof FSTreeNode) { + if (LocalSelectionTransfer.getTransfer().isSupportedType(transferType)) { + return dnd.validateLocalSelectionDrop(target, operation, transferType); + } + else if (FileTransfer.getInstance().isSupportedType(transferType)) { + return dnd.validateFilesDrop(target, operation, transferType); + } + } + return false; + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.ViewerDropAdapter#performDrop(java.lang.Object) + */ + @Override + public boolean performDrop(Object data) { + boolean success = false; + TransferData transferType = getCurrentEvent().currentDataType; + if (LocalSelectionTransfer.getTransfer().isSupportedType(transferType)) { + IStructuredSelection selection = (IStructuredSelection) data; + int operations = getCurrentOperation(); + FSTreeNode target = (FSTreeNode) getCurrentTarget(); + success = dnd.dropLocalSelection(target, operations, selection); + } + else if(FileTransfer.getInstance().isSupportedType(transferType)) { + String[] files = (String[]) data; + int operations = getCurrentOperation(); + FSTreeNode target = (FSTreeNode) getCurrentTarget(); + success = dnd.dropFiles(viewer, files, operations, target); + } + return success; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/CommitHandler.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/CommitHandler.java new file mode 100644 index 000000000..924ba72f0 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/CommitHandler.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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 + * William Chen (Wind River)- [345552] Edit the remote files with a proper editor + *******************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.ui.internal.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.IOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpUpload; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.operations.UiExecutor; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * The handler that commits the content of a modified file to the target file system. + */ +public class CommitHandler extends AbstractHandler { + + /* (non-Javadoc) + * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent) + */ + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + IStructuredSelection selection = (IStructuredSelection) HandlerUtil.getCurrentSelectionChecked(event); + FSTreeNode node = (FSTreeNode) selection.getFirstElement(); + IOpExecutor executor = new UiExecutor(); + executor.execute(new OpUpload(node)); + return null; + } + +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/CopyFilesHandler.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/CopyFilesHandler.java new file mode 100644 index 000000000..663cf903d --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/CopyFilesHandler.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.handlers; + +import java.util.List; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpClipboard; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * The handler that copies the selected files or folders to the clip board. + */ +public class CopyFilesHandler extends AbstractHandler { + + /* + * (non-Javadoc) + * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent) + */ + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + OpClipboard cb = UIPlugin.getClipboard(); + IStructuredSelection selection = (IStructuredSelection) HandlerUtil.getCurrentSelection(event); + if (!selection.isEmpty()) { + List<FSTreeNode> nodes = selection.toList(); + // Copy these files to the clip board. + cb.copyFiles(nodes); + } + return null; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/CutFilesHandler.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/CutFilesHandler.java new file mode 100644 index 000000000..cbca9c47e --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/CutFilesHandler.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.handlers; + +import java.util.List; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpClipboard; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * The handler that cuts the selected files or folders to the clip board. + */ +public class CutFilesHandler extends AbstractHandler { + + /* + * (non-Javadoc) + * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent) + */ + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + OpClipboard cb = UIPlugin.getClipboard(); + IStructuredSelection selection = (IStructuredSelection) HandlerUtil.getCurrentSelection(event); + if (!selection.isEmpty()) { + List<FSTreeNode> nodes = selection.toList(); + // Cut these files to the clip board. + cb.cutFiles(nodes); + } + return null; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/DeleteHandler.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/DeleteHandler.java new file mode 100644 index 000000000..2cf79b44c --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/DeleteHandler.java @@ -0,0 +1,128 @@ +/******************************************************************************* + * Copyright (c) 2012 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.te.tcf.filesystem.ui.internal.handlers; + +import java.util.List; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IConfirmCallback; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.IOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpDelete; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.ImageConsts; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.operations.UiExecutor; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * Delete handler implementation. + */ +public class DeleteHandler extends AbstractHandler { + // The confirmation call for read only files. + private IConfirmCallback readonlyCallback = new ReadOnlyConfirmCallback(); + + /* (non-Javadoc) + * @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent) + */ + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + // Get the current selection + ISelection selection = HandlerUtil.getCurrentSelection(event); + if (selection instanceof IStructuredSelection && !selection.isEmpty()) { + List<FSTreeNode> nodes = ((IStructuredSelection)selection).toList(); + if(confirmDeletion(nodes)) { + IOpExecutor executor = new UiExecutor(); + executor.execute(new OpDelete(nodes, readonlyCallback)); + } + } + + return null; + } + + /** + * Confirm the deletion of the specified nodes. + * + * @param nodes The nodes to be deleted. + * @return true if the user agrees to delete. + */ + private boolean confirmDeletion(List<FSTreeNode> nodes) { + String question; + if (nodes.size() == 1) { + FSTreeNode node = nodes.get(0); + question = NLS.bind(Messages.DeleteFilesHandler_DeleteOneFileConfirmation, node.name); + } + else { + question = NLS.bind(Messages.DeleteFilesHandler_DeleteMultipleFilesConfirmation, Integer.valueOf(nodes.size())); + } + Shell parent = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + if (MessageDialog.openQuestion(parent, Messages.DeleteFilesHandler_ConfirmDialogTitle, question)) { + return true; + } + return false; + } + + /** + * The callback implementation for the user to confirm the deletion of + * a read-only file/folder. + */ + static class ReadOnlyConfirmCallback implements IConfirmCallback { + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IConfirmCallback#requires(java.lang.Object) + */ + @Override + public boolean requires(Object object) { + if(object instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode) object; + return node.isWindowsNode() && node.isReadOnly() || !node.isWindowsNode() && !node.isWritable(); + } + return false; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IConfirmCallback#confirms(java.lang.Object) + */ + @Override + public int confirms(Object object) { + final FSTreeNode node = (FSTreeNode) object; + final int[] results = new int[1]; + Display display = PlatformUI.getWorkbench().getDisplay(); + display.syncExec(new Runnable() { + @Override + public void run() { + Shell parent = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + String title = Messages.FSDelete_ConfirmDelete; + String message = NLS.bind(Messages.FSDelete_ConfirmMessage, node.name); + final Image titleImage = UIPlugin.getImage(ImageConsts.DELETE_READONLY_CONFIRM); + MessageDialog qDialog = new MessageDialog(parent, title, null, message, MessageDialog.QUESTION, new String[] { Messages.FSDelete_ButtonYes, Messages.FSDelete_ButtonYes2All, Messages.FSDelete_ButtonNo, Messages.FSDelete_ButtonCancel }, 0) { + @Override + public Image getQuestionImage() { + return titleImage; + } + }; + results[0] = qDialog.open(); + } + }); + return results[0]; + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/MergeHandler.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/MergeHandler.java new file mode 100644 index 000000000..47287db7e --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/MergeHandler.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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 + * William Chen (Wind River)- [345552] Edit the remote files with a proper editor + *******************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.ui.internal.handlers; + +import org.eclipse.compare.CompareUI; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.compare.LocalTypedElement; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.compare.MergeEditorInput; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.compare.RemoteTypedElement; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * The handler used to merge a file which is conflicting with its remote file. + */ +public class MergeHandler extends AbstractHandler { + + /* (non-Javadoc) + * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent) + */ + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + IStructuredSelection selection = (IStructuredSelection) HandlerUtil.getCurrentSelectionChecked(event); + FSTreeNode node = (FSTreeNode) selection.getFirstElement(); + LocalTypedElement local = new LocalTypedElement(node); + RemoteTypedElement remote = new RemoteTypedElement(node); + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + MergeEditorInput input = new MergeEditorInput(local, remote, page); + CompareUI.openCompareDialog(input); + return null; + } + +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/MoveCopyCallback.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/MoveCopyCallback.java new file mode 100644 index 000000000..004628fbb --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/MoveCopyCallback.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2012 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.te.tcf.filesystem.ui.internal.handlers; + +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IConfirmCallback; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.ImageConsts; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.ui.PlatformUI; + +/** + * The confirmation callback implementation for operation "Move" and "Copy". + */ +public class MoveCopyCallback implements IConfirmCallback { + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IConfirmCallback#requires(java.lang.Object) + */ + @Override + public boolean requires(Object object) { + return true; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IConfirmCallback#confirms(java.lang.Object) + */ + @Override + public int confirms(Object object) { + final FSTreeNode node = (FSTreeNode) object; + final int[] results = new int[1]; + Display display = PlatformUI.getWorkbench().getDisplay(); + display.syncExec(new Runnable() { + @Override + public void run() { + Shell parent = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + String title = node.isDirectory() ? Messages.FSOperation_ConfirmFolderReplaceTitle : Messages.FSOperation_ConfirmFileReplace; + String message = NLS.bind(node.isDirectory() ? Messages.FSOperation_ConfirmFolderReplaceMessage : Messages.FSOperation_ConfirmFileReplaceMessage, node.name); + final Image titleImage = UIPlugin.getImage(ImageConsts.REPLACE_FOLDER_CONFIRM); + MessageDialog qDialog = new MessageDialog(parent, title, null, message, MessageDialog.QUESTION, new String[] { Messages.FSOperation_ConfirmDialogYes, Messages.FSOperation_ConfirmDialogYesToAll, Messages.FSOperation_ConfirmDialogNo, Messages.FSOperation_ConfirmDialogCancel }, 0) { + @Override + public Image getQuestionImage() { + return titleImage; + } + }; + results[0] = qDialog.open(); + } + }); + return results[0]; + } + +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/MoveFilesHandler.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/MoveFilesHandler.java new file mode 100644 index 000000000..d62a1d6b1 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/MoveFilesHandler.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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.te.tcf.filesystem.ui.internal.handlers; + +import java.util.List; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.IOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpMove; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.dialogs.FSFolderSelectionDialog; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.operations.UiExecutor; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNode; +import org.eclipse.ui.handlers.HandlerUtil; +/** + * The handler that moves the selected files or folders to a destination folder. + */ +public class MoveFilesHandler extends AbstractHandler { + + /* + * (non-Javadoc) + * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent) + */ + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + Shell shell = HandlerUtil.getActiveShellChecked(event); + FSFolderSelectionDialog dialog = new FSFolderSelectionDialog(shell); + IStructuredSelection selection = (IStructuredSelection) HandlerUtil.getCurrentSelection(event); + List<FSTreeNode> nodes = selection.toList(); + IPeerNode peer = nodes.get(0).peerNode; + dialog.setInput(peer); + dialog.setMovedNodes(nodes); + if (dialog.open() == Window.OK) { + Object obj = dialog.getFirstResult(); + Assert.isTrue(obj instanceof FSTreeNode); + FSTreeNode dest = (FSTreeNode) obj; + IOpExecutor executor = new UiExecutor(); + executor.execute(new OpMove(nodes, dest, new MoveCopyCallback())); + } + return null; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/NewFileHandler.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/NewFileHandler.java new file mode 100644 index 000000000..5a02014a1 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/NewFileHandler.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.handlers; + +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.wizards.NewFileWizard; +import org.eclipse.ui.IWorkbenchWizard; + +/** + * The handler to create a new file node in the file system of Target Explorer. + */ +public class NewFileHandler extends NewNodeHandler { + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.handlers.NewNodeHandler#createWizard() + */ + @Override + protected IWorkbenchWizard createWizard() { + return new NewFileWizard(); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/NewFolderHandler.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/NewFolderHandler.java new file mode 100644 index 000000000..d8302f5f9 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/NewFolderHandler.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.handlers; + +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.wizards.NewFolderWizard; +import org.eclipse.ui.IWorkbenchWizard; + +/** + * The handler to create a new folder node in the file system of Target Explorer. + */ +public class NewFolderHandler extends NewNodeHandler { + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.handlers.NewNodeHandler#createWizard() + */ + @Override + protected IWorkbenchWizard createWizard() { + return new NewFolderWizard(); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/NewNodeHandler.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/NewNodeHandler.java new file mode 100644 index 000000000..332f6dbbf --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/NewNodeHandler.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * 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.te.tcf.filesystem.ui.internal.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWizard; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * The base handler to create a new file/folder node in the file system of Target Explorer. + */ +public abstract class NewNodeHandler extends AbstractHandler { + + /* + * (non-Javadoc) + * @see + * org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent) + */ + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + // In Eclipse 4.x, the HandlerUtil.getActiveWorkbenchWindow(event) may return null + IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindow(event); + if (window == null) window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); + IWorkbenchWizard wizard; + wizard = createWizard(); + ISelection selection = HandlerUtil.getCurrentSelectionChecked(event); + if (selection instanceof IStructuredSelection) { + wizard.init(PlatformUI.getWorkbench(), (IStructuredSelection) selection); + } + else { + wizard.init(PlatformUI.getWorkbench(), StructuredSelection.EMPTY); + } + Shell parent = window != null ? window.getShell() : null; + WizardDialog dialog = new WizardDialog(parent, wizard); + dialog.create(); + dialog.open(); + return null; + } + + /** + * Create a "New" wizard to for creating a file/folder. + * + * @return the wizard to be used for creating a file/folder. + */ + protected abstract IWorkbenchWizard createWizard(); +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/OpenFileHandler.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/OpenFileHandler.java new file mode 100644 index 000000000..cb046f899 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/OpenFileHandler.java @@ -0,0 +1,141 @@ +/******************************************************************************* + * 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: + * William Chen (Wind River)- [345387]Open the remote files with a proper editor + *******************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.ui.internal.handlers; + +import java.io.File; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tcf.te.runtime.callback.Callback; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.IOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpCacheUpdate; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.utils.CacheManager; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.utils.ContentTypeHelper; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.utils.PersistenceManager; +import org.eclipse.tcf.te.tcf.filesystem.core.model.CacheState; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.operations.UiExecutor; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.tcf.te.ui.swt.DisplayUtil; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.handlers.HandlerUtil; +import org.eclipse.ui.ide.FileStoreEditorInput; +import org.eclipse.ui.ide.IDE; + +/** + * The action handler to open a file on the remote file system. + */ +public class OpenFileHandler extends AbstractHandler { + + /* (non-Javadoc) + * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent) + */ + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + IStructuredSelection selection = (IStructuredSelection) HandlerUtil.getCurrentSelectionChecked(event); + final FSTreeNode node = (FSTreeNode) selection.getFirstElement(); + final IWorkbenchPage page = HandlerUtil.getActiveSite(event).getPage(); + if (ContentTypeHelper.isBinaryFile(node)) { + // If the file is a binary file. + Shell parent = HandlerUtil.getActiveShell(event); + MessageDialog.openWarning(parent, Messages.OpenFileHandler_Warning, + Messages.OpenFileHandler_OpeningBinaryNotSupported); + } else { + if (UIPlugin.isAutoSaving()) { + // Refresh the node to determine the cache state correctly + node.refresh(new Callback() { + @Override + protected void internalDone(Object caller, IStatus status) { + File file = CacheManager.getCacheFile(node); + if (node.getCacheState() == CacheState.outdated) { + file.delete(); + } + + DisplayUtil.safeAsyncExec(new Runnable() { + @Override + public void run() { + // Open the file node. + openFile(node, page); + } + }); + } + }); + } else { + // Open the file node. + openFile(node, page); + } + + } + return null; + } + + /** + * Open the file node in an editor of the specified workbench page. If the + * local cache file of the node is stale, then download it. Then open its + * local cache file. + * + * @param node + * The file node to be opened. + * @param page + * The workbench page in which the editor is opened. + */ + /* default */ void openFile(FSTreeNode node, IWorkbenchPage page) { + File file = CacheManager.getCacheFile(node); + if (!file.exists()) { + // If the file node's local cache does not exist yet, download it. + IOpExecutor executor = new UiExecutor(); + IStatus status = executor.execute(new OpCacheUpdate(node)); + if (!status.isOK()) { + return; + } + } + openEditor(page, node); + } + + /** + * Open the editor to display the file node in the UI thread. + * + * @param page + * The workbench page in which the editor is opened. + * @param node + * The file node whose local cache file is opened. + */ + private void openEditor(final IWorkbenchPage page, final FSTreeNode node) { + Display display = page.getWorkbenchWindow().getWorkbench().getDisplay(); + display.asyncExec(new Runnable() { + @Override + public void run() { + IPath path = CacheManager.getCachePath(node); + IFileStore fileStore = EFS.getLocalFileSystem().getStore(path); + String editorID = PersistenceManager.getInstance().getPersistentProperties(node).get(IDE.EDITOR_KEY); + try { + if(editorID!=null){ + FileStoreEditorInput input = new FileStoreEditorInput(fileStore); + page.openEditor(input, editorID, true, IWorkbenchPage.MATCH_INPUT|IWorkbenchPage.MATCH_ID); + }else{ + IDE.openEditorOnFileStore(page, fileStore); + } + } catch (PartInitException e) { + } + } + }); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/OpenWithContribution.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/OpenWithContribution.java new file mode 100644 index 000000000..aea1a5b3c --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/OpenWithContribution.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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: + * William Chen (Wind River) [360494]Provide an "Open With" action in the pop + * up menu of file system nodes of Target Explorer. + *******************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.ui.internal.handlers; + +import org.eclipse.core.expressions.IEvaluationContext; +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.action.IContributionItem; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.ui.ISources; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.actions.CompoundContributionItem; +import org.eclipse.ui.handlers.IHandlerService; +import org.eclipse.ui.menus.IWorkbenchContribution; +import org.eclipse.ui.services.IServiceLocator; + +/** + * The dynamic contribution of "Open With" submenu items. + */ +public class OpenWithContribution extends CompoundContributionItem implements IWorkbenchContribution { + // Service locator to located the handler service. + private IServiceLocator serviceLocator; + + /** + * Create the contribution instance. + */ + public OpenWithContribution() { + } + + /** + * Create the contribution instance with the specified id. + */ + public OpenWithContribution(String id) { + super(id); + } + + /* + * (non-Javadoc) + * @see + * org.eclipse.ui.menus.IWorkbenchContribution#initialize(org.eclipse.ui.services.IServiceLocator + * ) + */ + @Override + public void initialize(IServiceLocator serviceLocator) { + this.serviceLocator = serviceLocator; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.actions.CompoundContributionItem#getContributionItems() + */ + @Override + protected IContributionItem[] getContributionItems() { + // Get the selected node. + IHandlerService service = (IHandlerService) this.serviceLocator + .getService(IHandlerService.class); + IEvaluationContext state = service.getCurrentState(); + ISelection selection = (ISelection) state + .getVariable(ISources.ACTIVE_CURRENT_SELECTION_NAME); + IStructuredSelection iss = (IStructuredSelection) selection; + Object obj = iss.getFirstElement(); + Assert.isTrue(obj instanceof FSTreeNode); + FSTreeNode node = (FSTreeNode) obj; + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + return new IContributionItem[] { new OpenWithMenu(page, node) }; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/OpenWithMenu.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/OpenWithMenu.java new file mode 100644 index 000000000..14c6679e1 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/OpenWithMenu.java @@ -0,0 +1,419 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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: + * William Chen (Wind River) [360494]Provide an "Open With" action in the pop + * up menu of file system nodes of Target Explorer. + *******************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.ui.internal.handlers; + +import java.io.File; +import java.text.Collator; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.Map; + +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.QualifiedName; +import org.eclipse.core.runtime.content.IContentType; +import org.eclipse.jface.action.ContributionItem; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.window.Window; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.IOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpCacheUpdate; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.utils.CacheManager; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.utils.ContentTypeHelper; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.utils.PersistenceManager; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.operations.UiExecutor; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.ui.IEditorDescriptor; +import org.eclipse.ui.IEditorRegistry; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.dialogs.EditorSelectionDialog; +import org.eclipse.ui.ide.FileStoreEditorInput; +import org.eclipse.ui.ide.IDE; + +/** + * A menu for opening files in the target explorer. + * <p> + * An <code>OpenWithMenu</code> is used to populate a menu with "Open With" actions. One action is + * added for each editor which is applicable to the selected file. If the user selects one of these + * items, the corresponding editor is opened on the file. + * </p> + * + * @since 3.7 - Copied and modified based on org.eclipse.ui.actions.OpenWithMenu to avoid + * introducing org.eclipse.core.resources + */ +public class OpenWithMenu extends ContributionItem { + private static final String DEFAULT_TEXT_EDITOR = "org.eclipse.ui.DefaultTextEditor"; //$NON-NLS-1$ + + /** + * The id of this action. + */ + public static final String ID = UIPlugin.getUniqueIdentifier() + ".OpenWithMenu";//$NON-NLS-1$ + + /* + * Compares the labels from two IEditorDescriptor objects + */ + private static final Comparator<IEditorDescriptor> comparer = new Comparator<IEditorDescriptor>() { + private Collator collator = Collator.getInstance(); + + @Override + public int compare(IEditorDescriptor arg0, IEditorDescriptor arg1) { + String s1 = arg0.getLabel(); + String s2 = arg1.getLabel(); + return collator.compare(s1, s2); + } + }; + // The selected tree node. + FSTreeNode node; + // The current workbench page. + IWorkbenchPage page; + // The editor registry. + IEditorRegistry registry; + + /** + * Create an instance using the specified page and the specified FSTreeNode. + * + * @param page The page to open the editor. + * @param node The FSTreeNode to be opened. + */ + public OpenWithMenu(IWorkbenchPage page, FSTreeNode node) { + super(ID); + this.node = node; + this.page = page; + this.registry = PlatformUI.getWorkbench().getEditorRegistry(); + } + + /** + * Returns an image to show for the corresponding editor descriptor. + * + * @param editorDesc the editor descriptor, or null for the system editor + * @return the image or null + */ + private Image getImage(IEditorDescriptor editorDesc) { + ImageDescriptor imageDesc = getImageDescriptor(editorDesc); + if (imageDesc == null) { + return null; + } + return imageDesc.createImage(); + } + + /** + * Returns the image descriptor for the given editor descriptor, or null if it has no image. + */ + private ImageDescriptor getImageDescriptor(IEditorDescriptor editorDesc) { + ImageDescriptor imageDesc = null; + if (editorDesc == null) { + imageDesc = registry.getImageDescriptor(node.name); + // TODO: is this case valid, and if so, what are the implications for content-simulator + // editor bindings? + } + else { + imageDesc = editorDesc.getImageDescriptor(); + } + if (imageDesc == null) { + if (editorDesc != null && editorDesc.getId().equals(IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID)) { + imageDesc = registry.getSystemExternalEditorImageDescriptor(node.name); + } + } + return imageDesc; + } + + /** + * Creates the menu item for the editor descriptor. + * + * @param menu the menu to add the item to + * @param descriptor the editor descriptor, or null for the system editor + * @param preferredEditor the descriptor of the preferred editor, or <code>null</code> + */ + private void createMenuItem(Menu menu, final IEditorDescriptor descriptor, final IEditorDescriptor preferredEditor) { + final MenuItem menuItem = new MenuItem(menu, SWT.RADIO); + boolean isPreferred = preferredEditor != null && descriptor.getId() + .equals(preferredEditor.getId()); + menuItem.setSelection(isPreferred); + menuItem.setText(descriptor.getLabel()); + Image image = getImage(descriptor); + if (image != null) { + menuItem.setImage(image); + } + Listener listener = new Listener() { + @Override + public void handleEvent(Event event) { + switch (event.type) { + case SWT.Selection: + if (menuItem.getSelection()) { + syncOpen(descriptor, false); + } + break; + default: + break; + } + } + }; + menuItem.addListener(SWT.Selection, listener); + } + + /** + * Creates the Other... menu item + * + * @param menu the menu to add the item to + */ + @SuppressWarnings("unused") + private void createOtherMenuItem(final Menu menu) { + new MenuItem(menu, SWT.SEPARATOR); + final MenuItem menuItem = new MenuItem(menu, SWT.PUSH); + menuItem.setText(Messages.OpenWithMenu_OpenWith); + Listener listener = new Listener() { + @Override + public void handleEvent(Event event) { + switch (event.type) { + case SWT.Selection: + EditorSelectionDialog dialog = new EditorSelectionDialog(menu.getShell()); + dialog.setMessage(NLS + .bind(Messages.OpenWithMenu_ChooseEditorForOpening, node.name)); + if (dialog.open() == Window.OK) { + IEditorDescriptor editor = dialog.getSelectedEditor(); + if (editor != null) { + syncOpen(editor, editor.isOpenExternal()); + } + } + break; + default: + break; + } + } + }; + menuItem.addListener(SWT.Selection, listener); + } + + /** + * Get the default editor for this FSTreeNode. + * + * @return The descriptor of the default editor. + */ + private IEditorDescriptor getDefaultEditor() { + // Try file specific editor. + try { + String editorID = PersistenceManager.getInstance().getPersistentProperties(node) + .get(IDE.EDITOR_KEY); + if (editorID != null) { + IEditorDescriptor desc = registry.findEditor(editorID); + if (desc != null) { + return desc; + } + } + } + catch (Exception e) { + // do nothing + } + + IContentType contentType = null; + contentType = ContentTypeHelper.getContentType(node); + // Try lookup with filename + return registry.getDefaultEditor(node.name, contentType); + } + + /* + * (non-Javadoc) Fills the menu with perspective items. + */ + @SuppressWarnings("unused") + @Override + public void fill(Menu menu, int index) { + + IEditorDescriptor defaultEditor = registry.findEditor(DEFAULT_TEXT_EDITOR); + IEditorDescriptor preferredEditor = getDefaultEditor(); + + IEditorDescriptor[] editors = registry.getEditors(node.name, ContentTypeHelper.getContentType(node)); + Collections.sort(Arrays.asList(editors), comparer); + + boolean defaultFound = false; + + // Check that we don't add it twice. This is possible + // if the same editor goes to two mappings. + ArrayList<IEditorDescriptor> alreadyMapped = new ArrayList<IEditorDescriptor>(); + + for (int i = 0; i < editors.length; i++) { + IEditorDescriptor editor = editors[i]; + if (!alreadyMapped.contains(editor)) { + createMenuItem(menu, editor, preferredEditor); + if (defaultEditor != null && editor.getId().equals(defaultEditor.getId())) { + defaultFound = true; + } + alreadyMapped.add(editor); + } + } + + // Only add a separator if there is something to separate + if (editors.length > 0) { + new MenuItem(menu, SWT.SEPARATOR); + } + + // Add default editor. Check it if it is saved as the preference. + if (!defaultFound && defaultEditor != null) { + createMenuItem(menu, defaultEditor, preferredEditor); + } + + // Add system editor (should never be null) + IEditorDescriptor descriptor = registry + .findEditor(IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID); + createMenuItem(menu, descriptor, preferredEditor); + + createDefaultMenuItem(menu); + + // add Other... menu item + createOtherMenuItem(menu); + } + + /* + * (non-Javadoc) Returns whether this menu is dynamic. + */ + @Override + public boolean isDynamic() { + return true; + } + + /** + * Creates the menu item for clearing the current selection. + * + * @param menu the menu to add the item to + * @param file the file being edited + */ + private void createDefaultMenuItem(Menu menu) { + final MenuItem menuItem = new MenuItem(menu, SWT.RADIO); + menuItem.setSelection(getDefaultEditor() == null); + menuItem.setText(Messages.OpenWithMenu_DefaultEditor); + + Listener listener = new Listener() { + @Override + public void handleEvent(Event event) { + switch (event.type) { + case SWT.Selection: + if (menuItem.getSelection()) { + PersistenceManager.getInstance().getPersistentProperties(node) + .put(IDE.EDITOR_KEY, null); + try { + syncOpen(getEditorDescriptor(), false); + } + catch (PartInitException e) { + e.printStackTrace(); + } + } + break; + default: + break; + } + } + }; + + menuItem.addListener(SWT.Selection, listener); + } + + /** + * Get an appropriate editor for the FSTreeNode. If the default editor is not found, it will + * search the in-place editor, the external editor and finally the default text editor. + * + * @return An appropriate editor to open the node using "Default Editor". + * @throws PartInitException + */ + protected IEditorDescriptor getEditorDescriptor() throws PartInitException { + IEditorDescriptor defaultDescriptor = getDefaultEditor(); + if (defaultDescriptor != null) { + return defaultDescriptor; + } + + IEditorDescriptor editorDesc = null; + + // next check the OS for in-place editor (OLE on Win32) + if (registry.isSystemInPlaceEditorAvailable(node.name)) { + editorDesc = registry.findEditor(IEditorRegistry.SYSTEM_INPLACE_EDITOR_ID); + } + + // next check with the OS for an external editor + if (editorDesc == null && registry.isSystemExternalEditorAvailable(node.name)) { + editorDesc = registry.findEditor(IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID); + } + + // next lookup the default text editor + if (editorDesc == null) { + editorDesc = registry.findEditor(DEFAULT_TEXT_EDITOR); + } + + // if no valid editor found, bail out + if (editorDesc == null) { + throw new PartInitException(Messages.OpenWithMenu_NoEditorFound); + } + + return editorDesc; + } + + /** + * Synchronize and open the file using the specified editor descriptor. If openUsingDescriptor + * is true, it will try to use an external editor to open it if an eclipse editor is not + * available. + * + * @param editorDescriptor The editor descriptor used to open the node. + * @param openUsingDescriptor If an external editor should be used to open the node. + */ + protected void syncOpen(IEditorDescriptor editorDescriptor, boolean openUsingDescriptor) { + File file = CacheManager.getCacheFile(node); + if (!file.exists()) { + // If the file node's local cache does not exist yet, download it. + IOpExecutor executor = new UiExecutor(); + IStatus status = executor.execute(new OpCacheUpdate(node)); + if (!status.isOK()) { + return; + } + } + openInEditor(editorDescriptor, openUsingDescriptor); + } + + /** + * Open the editor using the specified editor descriptor. If openUsingDescriptor is true, it + * will try to use an external editor to open it if an eclipse editor is not available. + * + * @param editorDescriptor The editor descriptor used to open the node. + * @param openUsingDescriptor If an external editor should be used to open the node. + */ + private void openInEditor(IEditorDescriptor editorDescriptor, boolean openUsingDescriptor) { + try { + IPath path = CacheManager.getCachePath(node); + IFileStore fileStore = EFS.getLocalFileSystem().getStore(path); + FileStoreEditorInput input = new FileStoreEditorInput(fileStore); + if (openUsingDescriptor) { + String editorId = editorDescriptor.getId(); + page.openEditor(input, editorId, true, IWorkbenchPage.MATCH_INPUT | IWorkbenchPage.MATCH_ID); + } + else { + String editorId = IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID; + if (editorDescriptor != null) editorId = editorDescriptor.getId(); + page.openEditor(input, editorId, true, IWorkbenchPage.MATCH_INPUT | IWorkbenchPage.MATCH_ID); + Map<QualifiedName, String> properties = PersistenceManager.getInstance() + .getPersistentProperties(node); + properties.put(IDE.EDITOR_KEY, editorId); + } + } + catch (PartInitException e) { + e.printStackTrace(); + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/PasteFilesHandler.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/PasteFilesHandler.java new file mode 100644 index 000000000..b7f62ac59 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/PasteFilesHandler.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.handlers; + +import java.util.List; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.FileTransfer; +import org.eclipse.tcf.te.runtime.callback.Callback; +import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IOperation; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.IOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpCopy; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpMove; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.dnd.CommonDnD; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.operations.FsClipboard; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.operations.UiExecutor; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * The handler that pastes the files or folders in the clip board. + */ +public class PasteFilesHandler extends AbstractHandler { + + /* + * (non-Javadoc) + * @see + * org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent) + */ + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + FsClipboard cb = UIPlugin.getClipboard(); + if (!cb.isEmpty()) { + // Get the files/folders from the clip board. + IStructuredSelection selection = (IStructuredSelection) HandlerUtil.getCurrentSelectionChecked(event); + List<FSTreeNode> nodes = cb.getFiles(); + IOpExecutor executor = null; + IOperation operation = null; + if (cb.isCutOp()) { + FSTreeNode dest = (FSTreeNode) selection.getFirstElement(); + operation = new OpMove(nodes, dest, new MoveCopyCallback()); + executor = new UiExecutor(new Callback(){ + @Override + protected void internalDone(Object caller, IStatus status) { + UIPlugin.getClipboard().clear(); + } + }); + } + else if (cb.isCopyOp()) { + FSTreeNode hovered = (FSTreeNode) selection.getFirstElement(); + FSTreeNode dest = getCopyDestination(hovered, nodes); + boolean cpPerm = UIPlugin.isCopyPermission(); + boolean cpOwn = UIPlugin.isCopyOwnership(); + operation = new OpCopy(nodes, dest, cpPerm, cpOwn, new MoveCopyCallback()); + executor = new UiExecutor(); + } + if (executor != null && operation != null) { + executor.execute(operation); + } + } + else { + Clipboard clipboard = cb.getSystemClipboard(); + Object contents = clipboard.getContents(FileTransfer.getInstance()); + if (contents != null) { + String[] files = (String[]) contents; + // Get the files/folders from the clip board. + IStructuredSelection selection = (IStructuredSelection) HandlerUtil + .getCurrentSelectionChecked(event); + FSTreeNode hovered = (FSTreeNode) selection.getFirstElement(); + CommonDnD dnd = new CommonDnD(); + dnd.dropFiles(null, files, DND.DROP_COPY, hovered); + } + } + return null; + } + + /** + * Return an appropriate destination directory for copying according to + * the specified hovered node. If the hovered node is a file, then return + * its parent directory. If the hovered node is a directory, then return its + * self if it is not a node being copied. Return its parent directory if it is + * a node being copied. + * @param hovered + * @param nodes + * @return + */ + private FSTreeNode getCopyDestination(FSTreeNode hovered, List<FSTreeNode> nodes) { + if (hovered.isFile()) { + return hovered.getParent(); + } + else if (hovered.isDirectory()) { + for (FSTreeNode node : nodes) { + if (node == hovered) { + return hovered.getParent(); + } + } + } + return hovered; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/RefreshHandler.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/RefreshHandler.java new file mode 100644 index 000000000..1bedafff1 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/RefreshHandler.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2012 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.te.tcf.filesystem.ui.internal.handlers; + +import java.util.List; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.IOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.JobExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpRefresh; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * Refresh handler implementation. + */ +public class RefreshHandler extends AbstractHandler { + + /* + * (non-Javadoc) + * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent) + */ + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + ISelection selection = HandlerUtil.getCurrentSelection(event); + if (selection instanceof IStructuredSelection && !selection.isEmpty()) { + List<FSTreeNode> nodes = ((IStructuredSelection) selection).toList(); + IOpExecutor executor = new JobExecutor(); + executor.execute(new OpRefresh(nodes)); + } + return null; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/RefreshViewerHandler.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/RefreshViewerHandler.java new file mode 100644 index 000000000..5cd226d37 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/RefreshViewerHandler.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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.te.tcf.filesystem.ui.internal.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.IOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.JobExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpRefresh; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.core.model.ModelManager; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNode; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * The action handler to refresh the whole file system tree. + */ +public class RefreshViewerHandler extends AbstractHandler { + + /* + * (non-Javadoc) + * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent) + */ + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + IEditorInput editorInput = HandlerUtil.getActiveEditorInputChecked(event); + IPeerNode peer = (IPeerNode) editorInput.getAdapter(IPeerNode.class); + if (peer != null) { + FSTreeNode root = ModelManager.getRuntimeModel(peer).getRoot(); + if (root != null) { + IOpExecutor executor = new JobExecutor(); + executor.execute(new OpRefresh(root)); + } + } + return null; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/RenameCallback.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/RenameCallback.java new file mode 100644 index 000000000..274442df0 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/RenameCallback.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2012 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.te.tcf.filesystem.ui.internal.handlers; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tcf.te.runtime.callback.Callback; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.ui.PlatformUI; +/** + * The callback implementation for Renaming. + */ +public class RenameCallback extends Callback implements Runnable { + // The message to be displayed. + private String message; + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.callback.Callback#internalDone(java.lang.Object, org.eclipse.core.runtime.IStatus) + */ + @Override + protected void internalDone(Object caller, IStatus status) { + if (!status.isOK()) { + message = status.getMessage(); + PlatformUI.getWorkbench().getDisplay().asyncExec(this); + } + } + + /* + * (non-Javadoc) + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + Shell parent = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + MessageDialog.openError(parent, Messages.FSRename_RenameFileFolderTitle, message); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/RenameFilesHandler.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/RenameFilesHandler.java new file mode 100644 index 000000000..69b7c52e5 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/RenameFilesHandler.java @@ -0,0 +1,138 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.handlers; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.window.Window; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.IOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.JobExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpRename; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.celleditor.FSCellValidator; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.tcf.te.ui.dialogs.RenameDialog; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * The handler that renames the selected file or folder. + */ +public class RenameFilesHandler extends AbstractHandler { + // The currently focused viewer. + private static TreeViewer currentViewer; + + /* + * (non-Javadoc) + * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent) + */ + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + IStructuredSelection sel = (IStructuredSelection) HandlerUtil.getCurrentSelectionChecked(event); + if (!sel.isEmpty()) { + FSTreeNode node = (FSTreeNode) sel.getFirstElement(); + boolean inPlaceEditor = UIPlugin.isInPlaceEditor(); + if (inPlaceEditor) { + // If it is configured to use in-place editor, then invoke the editor. + if (currentViewer != null) { + Control control = currentViewer.getControl(); + if (!control.isDisposed()) { + currentViewer.editElement(node, 0); + } + } + } + else { + Shell shell = HandlerUtil.getActiveShellChecked(event); + RenameDialog dialog = createRenameDialog(shell, node); + int ok = dialog.open(); + if (ok == Window.OK) { + // Do the renaming. + String newName = dialog.getNewName(); + // Rename the node with the new name using an FSRename. + IOpExecutor executor = new JobExecutor(new RenameCallback()); + executor.execute(new OpRename(node, newName)); + } + } + } + return null; + } + + /** + * Create a renaming dialog for the specified file/folder node. + * + * @param shell The parent shell. + * @param node The file/folder node. + * @return The renaming dialog. + */ + private RenameDialog createRenameDialog(Shell shell, FSTreeNode node) { + String[] names = getUsedNames(node); + String title; + if (node.isFile()) { + title = Messages.RenameFilesHandler_TitleRenameFile; + } + else if (node.isDirectory()) { + title = Messages.RenameFilesHandler_TitleRenameFolder; + } + else { + title = Messages.RenameFilesHandler_TitleRename; + } + String formatRegex; + if (node.isWindowsNode()) { + formatRegex = FSCellValidator.WIN_FILENAME_REGEX; + } + else { + formatRegex = FSCellValidator.UNIX_FILENAME_REGEX; + } + String error; + if (node.isWindowsNode()) { + error = Messages.FSRenamingAssistant_WinIllegalCharacters; + } + else { + error = Messages.FSRenamingAssistant_UnixIllegalCharacters; + } + String prompt = Messages.RenameFilesHandler_RenamePromptMessage; + String usedError = Messages.FSRenamingAssistant_NameAlreadyExists; + String label = Messages.RenameFilesHandler_PromptNewName; + return new RenameDialog(shell, title, null, prompt, usedError, error, label, node.name, formatRegex, names, null); + } + + /** + * Get the used names in the specified folder. + * + * @param folder The folder. + * @return Used names. + */ + private String[] getUsedNames(FSTreeNode folder) { + List<String> usedNames = new ArrayList<String>(); + List<FSTreeNode> nodes = folder.getParent().getChildren(); + for (FSTreeNode node : nodes) { + usedNames.add(node.name); + } + return usedNames.toArray(new String[usedNames.size()]); + } + + /** + * Set the currently focused tree viewer. Called by Target Explorer and FSTreeControl to set the + * current viewer. + * + * @param viewer The currently focused tree viewer. + */ + public static void setCurrentViewer(TreeViewer viewer) { + currentViewer = viewer; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/UpdateHandler.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/UpdateHandler.java new file mode 100644 index 000000000..0fc8b1b0d --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/handlers/UpdateHandler.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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 + * William Chen (Wind River)- [345552] Edit the remote files with a proper editor + *******************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.ui.internal.handlers; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.IOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpCacheUpdate; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.operations.UiExecutor; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * The handler to update the local file's content with the latest of its remote file. + * + */ +public class UpdateHandler extends AbstractHandler { + + /* + * (non-Javadoc) + * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent) + */ + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + IStructuredSelection selection = (IStructuredSelection) HandlerUtil.getCurrentSelectionChecked(event); + FSTreeNode node = (FSTreeNode) selection.getFirstElement(); + IOpExecutor executor = new UiExecutor(); + executor.execute(new OpCacheUpdate(node)); + return null; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/operations/FsClipboard.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/operations/FsClipboard.java new file mode 100644 index 000000000..3b04debe1 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/operations/FsClipboard.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.operations; + +import java.util.List; + +import org.eclipse.swt.SWTException; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.widgets.Display; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpClipboard; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.ui.PlatformUI; + +/** + * The clip board to which copy or cut files/folders. + */ +public class FsClipboard extends OpClipboard { + // The system clipboard. + private Clipboard clipboard; + + /** + * Create a clip board instance. + */ + public FsClipboard() { + super(); + clipboard = new Clipboard(PlatformUI.getWorkbench().getDisplay()); + } + + /** + * Cut the specified files/folders to the clip board. + * + * @param files The file/folder nodes. + */ + @Override + public void cutFiles(List<FSTreeNode> files) { + super.cutFiles(files); + clearSystemClipboard(); + } + + /** + * Copy the specified files/folders to the clip board. + * + * @param files The file/folder nodes. + */ + @Override + public void copyFiles(List<FSTreeNode> files) { + super.copyFiles(files); + clearSystemClipboard(); + } + + /** + * Clear the clip board. + */ + @Override + public void clear() { + super.clear(); + clearSystemClipboard(); + } + + /** + * Make sure the system clip board is cleared in a UI thread. + */ + void clearSystemClipboard() { + if (Display.getCurrent() != null) { + clipboard.clearContents(); + } + else { + PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable(){ + @Override + public void run() { + clearSystemClipboard(); + }}); + } + } + + /** + * Dispose the clipboard. + */ + @Override + public void dispose() { + if(Display.getCurrent() != null) { + if (!clipboard.isDisposed()) { + try { + clipboard.dispose(); + } + catch (SWTException e) { + } + } + } + else { + PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable(){ + @Override + public void run() { + dispose(); + }}); + } + } + + /** + * Get the system clipboard. + * + * @return The system clipboard. + */ + public Clipboard getSystemClipboard() { + return clipboard; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/operations/UiExecutor.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/operations/UiExecutor.java new file mode 100644 index 000000000..e93449524 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/operations/UiExecutor.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.operations; + +import java.lang.reflect.InvocationTargetException; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback; +import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IOperation; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.exceptions.TCFException; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.IOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.dialogs.TimeTriggeredProgressMonitorDialog; +import org.eclipse.ui.PlatformUI; + +/** + * The operation that is executed in an interactive progress dialog. + */ +public class UiExecutor implements IOpExecutor { + // The callback + protected ICallback callback; + + /** + * Create a UI executor with no callback. + */ + public UiExecutor() { + this(null); + } + + /** + * Create a UI executor with a callback that will be + * invoked after execution. + * + * @param callback The callback to be invoked after execution. + */ + public UiExecutor(ICallback callback) { + this.callback = callback; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.ui.internal.operations.IOpExecutor#execute(org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IOperation) + */ + @Override + public IStatus execute(final IOperation operation) { + Assert.isNotNull(Display.getCurrent()); + Shell parent = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + TimeTriggeredProgressMonitorDialog dialog = new TimeTriggeredProgressMonitorDialog(parent, 250); + final IRunnableWithProgress runnable = new IRunnableWithProgress() { + @Override + public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { + try { + monitor.setTaskName(operation.getName()); + monitor.beginTask(operation.getName(), operation.getTotalWork()); + operation.run(monitor); + } + finally { + monitor.done(); + } + }}; + dialog.setCancelable(true); + IStatus status = null; + try { + dialog.run(true, true, runnable); + status = Status.OK_STATUS; + } + catch (InvocationTargetException e) { + // Display the error during copy. + Throwable throwable = e.getTargetException(); + if(throwable instanceof TCFException) { + int severity = ((TCFException)throwable).getSeverity(); + status = new Status(severity, UIPlugin.getUniqueIdentifier(), throwable.getMessage(), throwable); + } + else { + status = new Status(IStatus.ERROR, UIPlugin.getUniqueIdentifier(), throwable.getMessage(), throwable); + } + MessageDialog.openError(parent, operation.getName(), throwable.getMessage()); + } + catch (InterruptedException e) { + // It is canceled. + status = Status.OK_STATUS; + } + if (callback != null) callback.done(operation, status); + return status; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/pages/FSExplorerEditorPage.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/pages/FSExplorerEditorPage.java new file mode 100644 index 000000000..60f12d207 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/pages/FSExplorerEditorPage.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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.te.tcf.filesystem.ui.internal.pages; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.tcf.te.runtime.events.ChangeEvent; +import org.eclipse.tcf.te.runtime.events.EventManager; +import org.eclipse.tcf.te.tcf.filesystem.core.model.ModelManager; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNode; +import org.eclipse.tcf.te.tcf.ui.editor.AbstractTreeViewerExplorerEditorPage; +import org.eclipse.tcf.te.ui.trees.TreeControl; +/** + * The editor page for the file system explorer. + */ +public class FSExplorerEditorPage extends AbstractTreeViewerExplorerEditorPage { + + // The event listener instance + private FSExplorerEventListener listener = null; + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.editor.pages.AbstractTreeViewerExplorerEditorPage#dispose() + */ + @Override + public void dispose() { + if (listener != null) { + EventManager.getInstance().removeEventListener(listener); + listener = null; + } + super.dispose(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.editor.pages.AbstractTreeViewerExplorerEditorPage#getDoubleClickCommandId() + */ + @Override + protected String getDoubleClickCommandId() { + return "org.eclipse.ui.navigator.Open"; //$NON-NLS-1$ + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.editor.pages.AbstractTreeViewerExplorerEditorPage#getViewerId() + */ + @Override + protected String getViewerId() { + return "org.eclipse.tcf.te.ui.controls.viewer.fs"; //$NON-NLS-1$ + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.editor.pages.AbstractCustomFormToolkitEditorPage#getFormTitle() + */ + @Override + protected String getFormTitle() { + return Messages.FSExplorerEditorPage_PageTitle; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.editor.pages.AbstractCustomFormToolkitEditorPage#getContextHelpId() + */ + @Override + protected String getContextHelpId() { + return "org.eclipse.tcf.te.tcf.filesystem.FSExplorerEditorPage"; //$NON-NLS-1$ + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.editor.pages.AbstractTreeViewerExplorerEditorPage#getViewerInput() + */ + @Override + protected Object getViewerInput() { + Object element = getEditorInputNode(); + IPeerNode peerNode = element instanceof IPeerNode ? (IPeerNode)element : null; + if (peerNode == null && element instanceof IAdaptable) { + peerNode = (IPeerNode)((IAdaptable)element).getAdapter(IPeerNode.class); + } + return peerNode != null ? ModelManager.getRuntimeModel(peerNode).getRoot() : null; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.editor.pages.AbstractTreeViewerExplorerEditorPage#doCreateTreeControl() + */ + @Override + protected TreeControl doCreateTreeControl() { + TreeControl treeControl = super.doCreateTreeControl(); + Assert.isNotNull(treeControl); + + if (listener == null) { + listener = new FSExplorerEventListener(treeControl); + EventManager.getInstance().addEventListener(listener, ChangeEvent.class); + } + + return treeControl; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/pages/FSExplorerEventListener.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/pages/FSExplorerEventListener.java new file mode 100644 index 000000000..909eb167e --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/pages/FSExplorerEventListener.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2014 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.te.tcf.filesystem.ui.internal.pages; + +import java.util.EventObject; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.tcf.te.core.interfaces.IConnectable; +import org.eclipse.tcf.te.runtime.events.ChangeEvent; +import org.eclipse.tcf.te.runtime.events.EventManager; +import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.runtime.IRuntimeModel; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.core.model.ModelManager; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNode; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNodeProperties; +import org.eclipse.tcf.te.ui.events.AbstractEventListener; +import org.eclipse.tcf.te.ui.trees.TreeControl; + +/** + * Filesystem page event listener implementation. + */ +public class FSExplorerEventListener extends AbstractEventListener { + // Reference to the parent tree control + /* default */ final TreeControl treeControl; + + /** + * Constructor. + * + * @param treeControl The parent tree control. Must not be <code>null</code>. + */ + public FSExplorerEventListener(TreeControl treeControl) { + Assert.isNotNull(treeControl); + this.treeControl = treeControl; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.runtime.interfaces.events.IEventListener#eventFired(java.util.EventObject) + */ + @Override + public void eventFired(EventObject event) { + if (event instanceof ChangeEvent) { + final ChangeEvent changeEvent = (ChangeEvent)event; + final Object source = changeEvent.getSource(); + + if (treeControl.getViewer() != null) { + if (treeControl.getViewer().getControl() == null || treeControl.getViewer().getControl().isDisposed()) { + EventManager.getInstance().removeEventListener(this); + return; + } + // Property changes for the runtime model refreshes the whole tree. + if (source instanceof IRuntimeModel) { + treeControl.getViewer().refresh(); + } + + // Property changes for individual context nodes refreshes the node only + else if (source instanceof FSTreeNode) { + if ("expanded".equals(changeEvent.getEventId())) { //$NON-NLS-1$ + // Expansion state of the node changed. + boolean expanded = ((Boolean)changeEvent.getNewValue()).booleanValue(); + // Update the nodes expansion state + ((TreeViewer)treeControl.getViewer()).setExpandedState(source, expanded); + } else { + ((TreeViewer)treeControl.getViewer()).refresh(source, true); + } + } + + else if (source instanceof IPeerNode && source == getPeerNode()) { + if (IPeerNodeProperties.PROPERTY_CONNECT_STATE.equals(changeEvent.getEventId())) { + // Peer node connect state changed to connected + if (changeEvent.getNewValue().equals(Integer.valueOf(IConnectable.STATE_CONNECTED))) { + // Get the new runtime model + final IRuntimeModel model = ModelManager.getRuntimeModel(getPeerNode()); + // Update the tree viewer input element + treeControl.getViewer().setInput(model.getRoot()); + } + // Trigger a refresh on the whole viewer to show the "Please connect ..." text + treeControl.getViewer().refresh(); + } + } + } + } + } + + protected IPeerNode getPeerNode() { + Object element = treeControl.getViewer().getInput(); + IPeerNode peerNode = element instanceof IPeerNode ? (IPeerNode)element : null; + if (peerNode == null && element instanceof IAdaptable) { + peerNode = (IPeerNode)((IAdaptable)element).getAdapter(IPeerNode.class); + } + return peerNode; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/preferences/PreferencePage.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/preferences/PreferencePage.java new file mode 100644 index 000000000..e3a22ad7d --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/preferences/PreferencePage.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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 + * William Chen (Wind River)- [345552] Edit the remote files with a proper editor + *******************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.ui.internal.preferences; + +import org.eclipse.jface.preference.BooleanFieldEditor; +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.interfaces.preferences.IPreferenceKeys; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + +/** + * The preference page for configuring the preference options for + * the TCF File System Explorer. + * + */ +public class PreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage, IPreferenceKeys { + + /*** + * Create a preference page for Target Explorer File System Explorer. + */ + public PreferencePage() { + super(GRID); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.preference.FieldEditorPreferencePage#createFieldEditors() + */ + @Override + protected void createFieldEditors() { + UIPlugin plugin = UIPlugin.getDefault(); + IPreferenceStore preferenceStore = plugin.getPreferenceStore(); + setPreferenceStore(preferenceStore); + BooleanFieldEditor autoSaving = new BooleanFieldEditor(PREF_AUTOSAVING, Messages.PreferencePage_AutoSavingText, getFieldEditorParent()); + addField(autoSaving); + BooleanFieldEditor renamingOption = new BooleanFieldEditor(PREF_RENAMING_IN_PLACE_EDITOR, Messages.PreferencePage_RenamingOptionText, getFieldEditorParent()); + addField(renamingOption); + BooleanFieldEditor copyPermission = new BooleanFieldEditor(PREF_COPY_PERMISSION, Messages.PreferencePage_CopyPermissionText, getFieldEditorParent()); + addField(copyPermission); + BooleanFieldEditor copyOwnership = new BooleanFieldEditor(PREF_COPY_OWNERSHIP, Messages.PreferencePage_CopyOwnershipText, getFieldEditorParent()); + addField(copyOwnership); + BooleanFieldEditor persistExpanded = new BooleanFieldEditor(PREF_EXPANDED_PERSISTED, Messages.PreferencePage_PersistExpanded, getFieldEditorParent()); + addField(persistExpanded); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench) + */ + @Override + public void init(IWorkbench workbench) { + // do nothing + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/preferences/PreferencesInitializer.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/preferences/PreferencesInitializer.java new file mode 100644 index 000000000..228af3ced --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/preferences/PreferencesInitializer.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.preferences; + +import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; +import org.eclipse.core.runtime.preferences.DefaultScope; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.interfaces.preferences.IPreferenceKeys; + + +/** + * The bundle's preference initializer implementation. + */ +public class PreferencesInitializer extends AbstractPreferenceInitializer implements IPreferenceKeys { + + /** + * Constructor. + */ + public PreferencesInitializer() { + super(); + } + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences() + */ + @Override + public void initializeDefaultPreferences() { + // Get the bundles preferences manager + IEclipsePreferences prefs = DefaultScope.INSTANCE.getNode(UIPlugin.getUniqueIdentifier()); + if (prefs != null) { + // [Hidden] Editor content contribution: default on + prefs.putBoolean(PREF_FEATURE_ENABLE_EDITOR_CONTENT_CONTRIBUTION, DEFAULT_FEATURE_ENABLE_EDITOR_CONTENT_CONTRIBUTION); + } + IPreferenceStore preferenceStore = UIPlugin.getDefault().getPreferenceStore(); + preferenceStore.setDefault(PREF_AUTOSAVING, DEFAULT_AUTOSAVING); + preferenceStore.setDefault(PREF_RENAMING_IN_PLACE_EDITOR, DEFAULT_RENAMING_IN_PLACE_EDITOR); + preferenceStore.setDefault(PREF_COPY_PERMISSION, DEFAULT_COPY_PERMISSION); + preferenceStore.setDefault(PREF_COPY_OWNERSHIP, DEFAULT_COPY_OWNERSHIP); + preferenceStore.setDefault(PREF_EXPANDED_PERSISTED, DEFAULT_EXPANDED_PERSISTED); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/properties/AdvancedAttributesDialog.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/properties/AdvancedAttributesDialog.java new file mode 100644 index 000000000..4731034d0 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/properties/AdvancedAttributesDialog.java @@ -0,0 +1,214 @@ +/********************************************************************************************* + * Copyright (c) 2011, 2012 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: + * William Chen (Wind River) - [345384]Provide property pages for remote file system nodes + *********************************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.ui.internal.properties; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +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.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IWindowsFileAttributes; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.ImageConsts; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; + +/** + * The dialog used to display the advanced attributes of a Windows file or + * folder. + */ +public class AdvancedAttributesDialog extends Dialog { + + // The file or folder node whose advanced attributes are to be displayed. + FSTreeNode node; + + /** + * Create the advanced attributes dialog with the specified node and a + * parent shell. + * + * @param parentShell + * The parent shell. + * @param node + * The file or folder node to be displayed. + */ + public AdvancedAttributesDialog(Shell parentShell, FSTreeNode node) { + super(parentShell); + this.node = node; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite) + */ + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + Composite banner = new Composite(composite, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + banner.setLayout(layout); + Label label = new Label(banner, SWT.NONE); + Image bImg = getBannerImage(); + label.setImage(bImg); + label.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false)); + label = new Label(banner, SWT.NONE); + if (node.isFile()) { + label.setText(Messages.AdvancedAttributesDialog_FileBanner); + } else if (node.isDirectory()) { + label.setText(Messages.AdvancedAttributesDialog_FolderBanner); + } + createArchiveAndIndexGroup(composite); + createCompressAndEncryptGroup(composite); + return composite; + } + + /** + * Get the image in the banner area. + * + * @return The image in the banner area. + */ + private Image getBannerImage() { + return UIPlugin.getImage(ImageConsts.BANNER_IMAGE); + } + + /** + * Create the compress and encrypt options group. + * + * @param parent + * The parent composite where they are created. + */ + private void createCompressAndEncryptGroup(Composite parent) { + Group group = new Group(parent, SWT.SHADOW_ETCHED_IN); + group.setText(Messages.AdvancedAttributesDialog_CompressEncrypt); + group.setLayout(new GridLayout()); + group.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); + createCompress(group); + createEncrypt(group); + } + + /** + * Create the archive and indexing options group. + * + * @param parent + * The parent composite where they are created. + */ + private void createArchiveAndIndexGroup(Composite parent) { + Group group = new Group(parent, SWT.SHADOW_ETCHED_IN); + group.setText(Messages.AdvancedAttributesDialog_ArchiveIndex); + group.setLayout(new GridLayout()); + group.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); + createArchive(group); + createIndexField(group); + } + + /** + * Create the indexing option field. + * + * @param group + * The group widget where the field is created. + */ + private void createIndexField(Group group) { + String label = node.isFile() ? Messages.AdvancedAttributesDialog_IndexFile + : (node.isDirectory() ? Messages.AdvancedAttributesDialog_IndexFolder + : null); + boolean on = !node.isWin32AttrOn(IWindowsFileAttributes.FILE_ATTRIBUTE_NOT_CONTENT_INDEXED); + createOptionField(group, label, IWindowsFileAttributes.FILE_ATTRIBUTE_NOT_CONTENT_INDEXED, on); + } + + /** + * Create the archive option field. + * + * @param group + * The group widget where the field is created. + */ + private void createArchive(Group group) { + String label = node.isFile() ? Messages.AdvancedAttributesDialog_FileArchive + : (node.isDirectory() ? Messages.AdvancedAttributesDialog_FolderArchive + : null); + boolean on = node.isWin32AttrOn(IWindowsFileAttributes.FILE_ATTRIBUTE_ARCHIVE); + createOptionField(group, label, IWindowsFileAttributes.FILE_ATTRIBUTE_ARCHIVE, on); + } + + /** + * Create the encrypt option field. + * + * @param group + * The group widget where the field is created. + */ + private void createEncrypt(Group group) { + String label = Messages.AdvancedAttributesDialog_Encrypt; + boolean on = node.isWin32AttrOn(IWindowsFileAttributes.FILE_ATTRIBUTE_ENCRYPTED); + createOptionField(group, label, IWindowsFileAttributes.FILE_ATTRIBUTE_ENCRYPTED, on); + } + + /** + * Create the compress option field. + * + * @param group + * The group widget where the field is created. + */ + private void createCompress(Group group) { + String label = Messages.AdvancedAttributesDialog_Compress; + boolean on = node.isWin32AttrOn(IWindowsFileAttributes.FILE_ATTRIBUTE_COMPRESSED); + createOptionField(group, label, IWindowsFileAttributes.FILE_ATTRIBUTE_COMPRESSED, on); + } + + /** + * Create an option field in the specified group, using the specified label, + * and with the specified boolean value. + * + * @param group + * The group widget where the field is created. + * @param label + * The label used by the field. + * @param bit + * The bit mask to be changed once the value is changed. + * @param on + * The boolean value to be set. + */ + private void createOptionField(Group group, String label, final int bit, final boolean on) { + final Button button = new Button(group, SWT.CHECK); + button.setText(label); + button.setSelection(on); + // Only the owner can edit the properties + button.setEnabled(node.isAgentOwner()); + button.addSelectionListener(new SelectionAdapter(){ + @Override + public void widgetSelected(SelectionEvent e) { + if (button.getSelection() != on) { + node.setWin32Attr(bit, on); + } + } + }); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell) + */ + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + newShell.setText(Messages.AdvancedAttributesDialog_ShellTitle); + } + + /** + * Get the result. + * @return The result. + */ + public FSTreeNode getResult() { + return node; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/properties/GeneralInformationPage.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/properties/GeneralInformationPage.java new file mode 100644 index 000000000..94624e244 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/properties/GeneralInformationPage.java @@ -0,0 +1,405 @@ +/********************************************************************************************* + * Copyright (c) 2011, 2014 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: + * William Chen (Wind River) - [345384]Provide property pages for remote file system nodes + * [361322]Minor improvements to the properties dialog of a file. + *********************************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.ui.internal.properties; + +import java.text.DateFormat; +import java.text.DecimalFormat; +import java.util.Date; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.window.Window; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +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.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.IOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.JobExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.NullOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpCommitAttr; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpRefresh; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.ui.dialogs.PropertyPage; + +/** + * The general information page of a file's properties dialog. + */ +public class GeneralInformationPage extends PropertyPage { + // The times of retrying before failure. + private static final int RETRY_TIMES = 3; + // The formatter for the size of a file. + private static final DecimalFormat SIZE_FORMAT = new DecimalFormat(); + // The original node. + FSTreeNode node; + // Cloned node for modification. + FSTreeNode clone; + // The button of "Read-Only" + Button btnReadOnly; + // The button of "Hidden" + Button btnHidden; + // The button of "Permissions" + Button[] btnPermissions; + + /** + * Create a horizontal separator between field sections. + * + * @param parent + * The parent composite of the separator. + */ + protected void createSeparator(Composite parent) { + Label label = new Label(parent, SWT.SEPARATOR | SWT.SHADOW_ETCHED_IN | SWT.HORIZONTAL); + GridData data = new GridData(SWT.FILL, SWT.BEGINNING, true, false); + data.horizontalSpan = 2; + label.setLayoutData(data); + } + + /** + * Create a field displaying the a specific value with a specific label. + * + * @param text + * The label text for the field. + * @param value + * The value to be displayed. + * @param parent + * The parent composite of the field. + */ + protected void createField(String text, String value, Composite parent) { + Label label = new Label(parent, SWT.NONE); + label.setText(text); + GridData data = new GridData(); + data.horizontalAlignment = SWT.LEFT; + data.verticalAlignment = SWT.TOP; + label.setLayoutData(data); + Text txt = new Text(parent, SWT.WRAP | SWT.READ_ONLY); + data = new GridData(); + data.verticalAlignment = SWT.TOP; + data.widthHint = 300; + data.grabExcessHorizontalSpace = true; + data.horizontalAlignment = GridData.FILL; + txt.setLayoutData(data); + txt.setBackground(txt.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); + txt.setText(value); + } + + /** + * Get the string of the file size using using the formatter, SIZE_FORMAT. + * + * @param size + * The size of the file to be formatted. + * @return The string in the format of SIZE_FORMAT. + */ + protected String getSizeText(long size) { + return NLS.bind(Messages.GeneralInformationPage_FileSizeInfo, SIZE_FORMAT.format(size / 1024), SIZE_FORMAT.format(size)); + } + + /** + * Get the string of the specific time using the formatter, DATE_FORMAT. + * + * @param time + * The time to be formatted. + * @return The string in the format of DATE_FORMAT. + */ + protected String getDateText(long time) { + DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT); + return dateFormat.format(new Date(time)); + } + + /** + * Create the attributes section for a Windows file/folder. + * + * @param parent + * The parent composite on which it is created. + */ + protected void createAttributesSection(Composite parent) { + // Attributes + Label label = new Label(parent, SWT.NONE); + label.setText(Messages.GeneralInformationPage_Attributes); + GridData data = new GridData(); + data.horizontalAlignment = SWT.LEFT; + label.setLayoutData(data); + + Composite attr = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(3, true); + layout.marginHeight = 0; + attr.setLayout(layout); + // Read-only + btnReadOnly = new Button(attr, SWT.CHECK); + btnReadOnly.setText(Messages.GeneralInformationPage_ReadOnly); + // Only the owner can edit this property + btnReadOnly.setEnabled(node.isAgentOwner()); + btnReadOnly.addSelectionListener(new SelectionAdapter(){ + @Override + public void widgetSelected(SelectionEvent e) { + if(btnReadOnly.getSelection()!=clone.isReadOnly()){ + clone.setReadOnly(btnReadOnly.getSelection()); + } + } + }); + // Hidden + btnHidden = new Button(attr, SWT.CHECK); + btnHidden.setText(Messages.GeneralInformationPage_Hidden); + // Only the owner can edit this property + btnHidden.setEnabled(node.isAgentOwner()); + btnHidden.addSelectionListener(new SelectionAdapter(){ + @Override + public void widgetSelected(SelectionEvent e) { + Button btnHidden = (Button) e.getSource(); + if(btnHidden.getSelection()!=clone.isHidden()){ + clone.setHidden(btnHidden.getSelection()); + } + } + }); + // Advanced Attributes + Button btnAdvanced = new Button(attr, SWT.PUSH); + btnAdvanced.setText(Messages.GeneralInformationPage_Advanced); + btnAdvanced.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + showAdvancedAttributes(); + } + }); + // Update the attribute values. + updateAttributes(); + } + + /** + * Update the value of attributes section. + */ + private void updateAttributes() { + btnReadOnly.setSelection(clone.isReadOnly()); + btnHidden.setSelection(clone.isHidden()); + } + + /** + * Show the advanced attributes dialog for the specified file/folder. + */ + void showAdvancedAttributes() { + AdvancedAttributesDialog dialog = new AdvancedAttributesDialog(this.getShell(), (FSTreeNode)(clone.clone())); + if (dialog.open() == Window.OK) { + FSTreeNode result = dialog.getResult(); + clone.attr = result.attr; + } + } + + /** + * Create the permissions section for a Unix/Linux file/folder. + * + * @param parent + * The parent composite on which it is created. + */ + protected void createPermissionsSection(Composite parent) { + GridLayout gridLayout; + Label label = new Label(parent, SWT.NONE); + label.setText(Messages.GeneralInformationPage_PermissionText); + GridData data = new GridData(); + data.horizontalAlignment = SWT.LEFT; + data.verticalAlignment = SWT.TOP; + label.setLayoutData(data); + Composite perms = new Composite(parent, SWT.NONE); + gridLayout = new GridLayout(2, false); + gridLayout.marginHeight = 0; + perms.setLayout(gridLayout); + btnPermissions = new Button[9]; + createPermissionGroup(perms, 0, + Messages.PermissionsGroup_UserPermissions); + createPermissionGroup(perms, 3, + Messages.PermissionsGroup_GroupPermissions); + createPermissionGroup(perms, 6, + Messages.PermissionsGroup_OtherPermissions); + // Update the permission values. + updatePermissions(); + } + + /** + * Create a permission group for a role, such as a user, a group or others. + * + * @param parent + * The parent composite. + * @param bit + * The permission bit index. + * @param header + * The group's header label. + */ + protected void createPermissionGroup(Composite parent, int bit, String header) { + Label label = new Label(parent, SWT.NONE); + label.setText(header); + GridData data = new GridData(); + data.horizontalAlignment = SWT.LEFT; + label.setLayoutData(data); + Composite group = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(3, true); + layout.marginHeight = 0; + group.setLayout(layout); + createPermissionButton(Messages.PermissionsGroup_Readable, bit, group); + createPermissionButton(Messages.PermissionsGroup_Writable, bit + 1, group); + createPermissionButton(Messages.PermissionsGroup_Executable, bit + 2, group); + } + + /** + * Create a check-box field for a single permission item. + * + * @param label + * The label of the permission. + * @param index + * The index of current permission bit mask index. + * @param parent + * The parent to hold the check-box field. + */ + private void createPermissionButton(String label, final int index, Composite parent) { + btnPermissions[index] = new Button(parent, SWT.CHECK); + btnPermissions[index].setText(label); + // Only the owner can edit its permission. + btnPermissions[index].setEnabled(node.isAgentOwner()); + btnPermissions[index].addSelectionListener(new SelectionAdapter(){ + @Override + public void widgetSelected(SelectionEvent e) { + int bit = 1 << (8 - index); + boolean on = clone.attr != null && (clone.attr.permissions & bit) != 0; + boolean newOn = btnPermissions[index].getSelection(); + if (newOn != on) { + int permissions = clone.attr != null ? clone.attr.permissions : 0; + permissions = newOn ? (permissions | bit) : (permissions & ~bit); + clone.setPermissions(permissions); + } + } + }); + } + + /** + * Update the value of permissions section. + */ + private void updatePermissions(){ + for (int i = 0; i < 9; i++) { + final int bit = 1 << (8 - i); + final boolean on = clone.attr != null && (clone.attr.permissions & bit) != 0; + btnPermissions[i].setSelection(on); + } + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.preference.PreferencePage#performDefaults() + */ + @Override + protected void performDefaults() { + clone = (FSTreeNode) node.clone(); + if (node.isWindowsNode()) { + updateAttributes(); + } + else { + updatePermissions(); + } + super.performDefaults(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.preference.PreferencePage#performOk() + */ + @Override + public boolean performOk() { + if (hasAttrsChanged()) { + IStatus status = commitAttr(); + if(!status.isOK()) { + setErrorMessage(status.getMessage()); + return false; + } + } + return true; + } + + /** + * Commit the new attributes of the file and + * return a status. This operation will try + * several times before reporting failure. + * + * @return The committing status. + */ + private IStatus commitAttr() { + OpCommitAttr op = new OpCommitAttr(node, clone.attr); + IOpExecutor executor = new NullOpExecutor(); + IStatus status = null; + for (int i = 0; i < RETRY_TIMES; i++) { + status = executor.execute(op); + if (status.isOK()) { + if (!node.isRoot()) { + // Refresh the parent so that the filters work! + executor = new JobExecutor(); + executor.execute(new OpRefresh(node.getParent())); + } + return status; + } + } + return status; + } + + /** + * If the attributes has been changed. + * @return If the attributes has been changed. + */ + private boolean hasAttrsChanged(){ + if(node.isWindowsNode()){ + // If it is a Windows file, only check its attributes. + return node.getWin32Attrs() != clone.getWin32Attrs(); + } + // If it is not a Windows file, only check its permissions. + return node.attr != null && clone.attr != null && node.attr.permissions != clone.attr.permissions; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite) + */ + @Override + protected Control createContents(Composite parent) { + IAdaptable element = getElement(); + Assert.isTrue(element instanceof FSTreeNode); + + node = (FSTreeNode) element; + clone = (FSTreeNode) node.clone(); + Composite page = new Composite(parent, SWT.NONE); + GridLayout gridLayout = new GridLayout(2, false); + page.setLayout(gridLayout); + // Field "Name" + createField(Messages.GeneralInformationPage_Name, clone.name, page); + // Field "Type" + createField(Messages.GeneralInformationPage_Type, clone.getFileType(), page); + // Field "Location" + String location = clone.isSystemRoot() || clone.isRoot() ? + Messages.GeneralInformationPage_Computer : clone.getLocation(); + createField(Messages.GeneralInformationPage_Location, location, page); + // Field "Size" + if (clone.isFile()) { + createField(Messages.GeneralInformationPage_Size, clone.attr != null ? getSizeText(clone.attr.size) : "", page); //$NON-NLS-1$ + } + // Field "Modified" + createField(Messages.GeneralInformationPage_Modified, clone.attr != null ? getDateText(clone.attr.mtime) : "", page); //$NON-NLS-1$ + // Field "Accessed" + if (clone.isFile()) { + createField(Messages.GeneralInformationPage_Accessed, clone.attr != null ? getDateText(clone.attr.atime) : "", page); //$NON-NLS-1$ + } + createSeparator(page); + if (clone.isWindowsNode()) { + createAttributesSection(page); + } else { + createPermissionsSection(page); + } + return page; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/DateValidator.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/DateValidator.java new file mode 100644 index 000000000..0ada406c5 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/DateValidator.java @@ -0,0 +1,108 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.search; + +import java.util.Calendar; +import java.util.StringTokenizer; + +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.tcf.te.ui.controls.validator.RegexValidator; + +/** + * The validator used to validate the date entered in the search dialog. + */ +public class DateValidator extends RegexValidator { + // The regex that defines the format of the date, i.e., MM/DD/YYYY + private static final String DATE_REGEX = "\\d{1,2}/\\d{1,2}/\\d{4}"; //$NON-NLS-1$ + + /** + * Constructor + */ + public DateValidator() { + super(ATTR_MANDATORY, DATE_REGEX); + setMessageText(INFO_MISSING_VALUE, Messages.DateValidator_InfoPrompt); + setMessageText(ERROR_INVALID_VALUE, Messages.DateValidator_InfoFormat); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.controls.validator.RegexValidator#isValid(java.lang.String) + */ + @Override + public boolean isValid(String newText) { + boolean valid = super.isValid(newText); + if(valid) { + try { + parseTimeInMillis(newText); + return true; + } + catch(IllegalArgumentException e) { + String error = e.getMessage(); + setMessage(error, ERROR); + } + } + return false; + } + + /** + * Parse a text string to a date expressed in milliseconds since 1/1/1970. + * If the format is not right, then throw an illegal argument exception containing + * the error message. + * + * @param newText The text string to be parsed. + * @return a number in milliseconds since 1/1/1970 + * @throws IllegalArgumentException when the format is not right. + */ + public static long parseTimeInMillis(String newText) throws IllegalArgumentException{ + StringTokenizer tokenizer = new StringTokenizer(newText, "/"); //$NON-NLS-1$ + String month_str = tokenizer.nextToken(); + int month = 0; + try{ + month = Integer.parseInt(month_str); + } + catch(NumberFormatException e){ + throw new IllegalArgumentException(Messages.DateValidator_MonthInvalidNumber); + } + if(month <= 0 || month > 12) { + throw new IllegalArgumentException(Messages.DateValidator_MonthOutofRange); + } + String date_str = tokenizer.nextToken(); + int date = 0; + try { + date = Integer.parseInt(date_str); + } + catch(NumberFormatException e) { + throw new IllegalArgumentException(Messages.DateValidator_DateInvalidNumber); + } + if(date <= 0 || date > 31) { + throw new IllegalArgumentException(Messages.DateValidator_DateOutofRange); + } + String year_str = tokenizer.nextToken(); + int year = 0; + try { + year = Integer.parseInt(year_str); + } + catch(NumberFormatException e) { + throw new IllegalArgumentException(Messages.DateValidator_YearInvalidNumber); + } + if(year <= 0) { + throw new IllegalArgumentException(Messages.DateValidator_YearOutofRange); + } + Calendar calendar = Calendar.getInstance(); + calendar.setLenient(false); + calendar.set(year, month-1, date); + try { + return calendar.getTimeInMillis(); + } + catch(IllegalArgumentException e) { + throw new IllegalArgumentException(Messages.DateValidator_InvalidDate); + } + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/FSBaseSearchable.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/FSBaseSearchable.java new file mode 100644 index 000000000..c6576dcbf --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/FSBaseSearchable.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.search; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tcf.te.ui.forms.FormLayoutFactory; +import org.eclipse.tcf.te.ui.interfaces.ISearchMatcher; +import org.eclipse.tcf.te.ui.utils.AbstractSearchable; +import org.eclipse.ui.forms.events.ExpansionEvent; +import org.eclipse.ui.forms.events.IExpansionListener; +import org.eclipse.ui.forms.widgets.ExpandableComposite; +import org.eclipse.ui.forms.widgets.Section; + +/** + * The base searchable that provides common methods for its subclasses. + * + * @see FSModifiedSearchable + * @see FSSizeSearchable + */ +public abstract class FSBaseSearchable extends AbstractSearchable implements ISearchMatcher { + + /** + * Create a collapseable section with the specified title and return the + * content composite. + * + * @param parent The parent where the section is to be created. + * @param title The title of the section. + * @return The content composite. + */ + protected Composite createSection(Composite parent, String title) { + Section section = new Section(parent, ExpandableComposite.TWISTIE | ExpandableComposite.CLIENT_INDENT); + section.setText(title); + section.setLayout(FormLayoutFactory.createSectionClientGridLayout(false, 2)); + GridData layoutData = new GridData(GridData.FILL_HORIZONTAL); + section.setLayoutData(layoutData); + + final Composite client = new Composite(section, SWT.NONE); + client.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + client.setBackground(section.getBackground()); + section.setClient(client); + + section.addExpansionListener(new IExpansionListener(){ + @Override + public void expansionStateChanging(ExpansionEvent e) { + } + @Override + public void expansionStateChanged(ExpansionEvent e) { + Shell shell = client.getShell(); + boolean state = e.getState(); + int client_height = client.getSize().y; + Point p = shell.getSize(); + p.y = state ? p.y + client_height : p.y - client_height; + shell.setSize(p.x, p.y); + }}); + return client; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.interfaces.ISearchable#getMatcher() + */ + @Override + public ISearchMatcher getMatcher() { + return this; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/FSGeneralSearchable.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/FSGeneralSearchable.java new file mode 100644 index 000000000..e8c3976ce --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/FSGeneralSearchable.java @@ -0,0 +1,302 @@ +/******************************************************************************* + * 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.te.tcf.filesystem.ui.internal.search; + +import org.eclipse.jface.dialogs.IDialogSettings; +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.events.SelectionListener; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.tcf.te.ui.controls.BaseEditBrowseTextControl; +import org.eclipse.tcf.te.ui.interfaces.ISearchMatcher; +import org.eclipse.tcf.te.ui.search.TreeViewerSearchDialog; +import org.eclipse.tcf.te.ui.utils.AbstractSearchable; + +/** + * The searchable that provides a UI to collect and test + * the general operations of a file search. + */ +public class FSGeneralSearchable extends AbstractSearchable { + // The keys to access the options stored in the dialog settings. + private static final String INCLUDE_HIDDEN = "FS.IncludeHidden"; //$NON-NLS-1$ + private static final String INCLUDE_SYSTEM = "FS.IncludeSystem"; //$NON-NLS-1$ + private static final String TARGET_NAME = "FS.TargetName"; //$NON-NLS-1$ + private static final String TARGET_TYPE = "FS.TargetType"; //$NON-NLS-1$ + private static final String MATCH_PRECISE = "FS.MatchPrecise"; //$NON-NLS-1$ + private static final String CASE_SENSITIVE = "FS.CaseSensitive"; //$NON-NLS-1$ + // The check option to define if system files should be searched. + private Button fBtnSystem; + // The check option to define if hidden files should be searched. + private Button fBtnHidden; + // The case sensitive check box. + private Button fBtnCase; + // The matching rule check box. + private Button fBtnMatch; + // The input field for searching conditions. + private BaseEditBrowseTextControl fSearchField; + // The current target names. + private String fTargetName; + // Whether it is case sensitive + private boolean fCaseSensitive; + // Whether it is precise matching. + private boolean fMatchPrecise; + // The flag if system files should be searched, default to true. + private boolean fIncludeSystem = true; + // The flag if hidden files should be searched, default to true. + private boolean fIncludeHidden = true; + // The types of target files. + private Combo fCmbTypes; + // The current selected target type index. + private int fTargetType; + // The root directory node. + private FSTreeNode rootNode; + + /** + * Constructor + * + * @param node the node whose sub tree will be searched. + */ + public FSGeneralSearchable(FSTreeNode node) { + rootNode = node; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.ui.utils.AbstractSearchable#createCommonPart(org.eclipse.tcf.te.ui.search.TreeViewerSearchDialog, org.eclipse.swt.widgets.Composite) + */ + @Override + public void createCommonPart(TreeViewerSearchDialog dialog, Composite parent) { + Composite composite = new Composite(parent, SWT.NONE); + GridLayout glayout = new GridLayout(3, false); + glayout.marginHeight = 0; + glayout.marginWidth = 0; + composite.setLayout(glayout); + composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + // Searching field. + Label label = new Label(composite, SWT.NONE); + label.setText(Messages.FSGeneralSearchable_Find); + + fSearchField = new BaseEditBrowseTextControl(null); + fSearchField.setIsGroup(false); + fSearchField.setHasHistory(false); + fSearchField.setHideBrowseButton(true); + fSearchField.setParentControlIsInnerPanel(true); + fSearchField.setupPanel(composite); + fSearchField.setEditFieldValidator(new NameValidator()); + //fSearchField.setEditFieldValidator(new FolderValidator(this)); + Text text = (Text) fSearchField.getEditFieldControl(); + text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + text.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + searchTextModified(); + } + }); + + SelectionListener l = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + optionChecked(e); + } + }; + + Group group = new Group(parent, SWT.NONE); + group.setText(Messages.FSGeneralSearchable_GeneralOptionText); + group.setLayout(new GridLayout()); + group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + Composite cmpType = new Composite(group, SWT.NONE); + GridData data = new GridData(GridData.FILL_HORIZONTAL); + cmpType.setLayoutData(data); + cmpType.setLayout(new GridLayout(2, false)); + + label = new Label(cmpType, SWT.NONE); + label.setText(Messages.FSGeneralSearchable_FileType); + + // Search files only + fCmbTypes = new Combo(cmpType, SWT.BORDER | SWT.READ_ONLY); + fCmbTypes.setItems(new String[]{Messages.FSTreeNodeSearchable_FilesAndFolders, Messages.FSTreeNodeSearchable_FilesOnly, Messages.FSTreeNodeSearchable_FoldersOnly}); + fCmbTypes.setLayoutData(new GridData()); + fCmbTypes.addSelectionListener(l); + + Composite compOptions = new Composite(group, SWT.NONE); + data = new GridData(GridData.FILL_HORIZONTAL); + compOptions.setLayoutData(data); + compOptions.setLayout(new GridLayout(3, true)); + + // Case sensitive + fBtnCase = new Button(compOptions, SWT.CHECK); + fBtnCase.setText(Messages.TreeViewerSearchDialog_BtnCaseText); + data = new GridData(GridData.FILL_HORIZONTAL); + fBtnCase.setLayoutData(data); + fBtnCase.addSelectionListener(l); + + // Matching precisely + fBtnMatch = new Button(compOptions, SWT.CHECK); + fBtnMatch.setText(Messages.TreeViewerSearchDialog_BtnPreciseText); + data = new GridData(GridData.FILL_HORIZONTAL); + fBtnMatch.setLayoutData(data); + fBtnMatch.addSelectionListener(l); + + dialog.createSearchDirectionOptions(compOptions); + + // If the target is Windows platform, then add system/hidden options. + if(rootNode.isWindowsNode()) { + fBtnSystem = new Button(compOptions, SWT.CHECK); + fBtnSystem.setText(Messages.FSGeneralSearchable_SearchSystemFiles); + data = new GridData(GridData.FILL_HORIZONTAL); + fBtnSystem.setLayoutData(data); + fBtnSystem.addSelectionListener(l); + + fBtnHidden = new Button(compOptions, SWT.CHECK); + fBtnHidden.setText(Messages.FSGeneralSearchable_SearchHiddenFiles); + data = new GridData(GridData.FILL_HORIZONTAL); + fBtnHidden.setLayoutData(data); + fBtnHidden.addSelectionListener(l); + } + } + + /** + * The text for searching is modified. + */ + protected void searchTextModified() { + fireOptionChanged(); + fTargetName = fSearchField.getEditFieldControlText().trim(); + } + + /** + * Handling the event that a button is selected and checked. + * + * @param e The selection event. + */ + protected void optionChecked(SelectionEvent e) { + Object src = e.getSource(); + if (src == fBtnCase) { + fCaseSensitive = fBtnCase.getSelection(); + } + else if (src == fBtnMatch) { + fMatchPrecise = fBtnMatch.getSelection(); + } + else if (src == fCmbTypes) { + fTargetType = fCmbTypes.getSelectionIndex(); + } + else if (src == fBtnSystem) { + fIncludeSystem = fBtnSystem.getSelection(); + } + else if (src == fBtnHidden) { + fIncludeHidden = fBtnHidden.getSelection(); + } + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.utils.AbstractSearchable#restoreValues(org.eclipse.jface.dialogs.IDialogSettings) + */ + @Override + public void restoreValues(IDialogSettings settings) { + if(settings != null) { + fCaseSensitive = settings.getBoolean(CASE_SENSITIVE); + fBtnCase.setSelection(fCaseSensitive); + fMatchPrecise = settings.getBoolean(MATCH_PRECISE); + fBtnMatch.setSelection(fMatchPrecise); + try { + fTargetType = settings.getInt(TARGET_TYPE); + fCmbTypes.select(fTargetType); + }catch(NumberFormatException e) { + fTargetType = 0; + } + fTargetName = settings.get(TARGET_NAME); + if (fTargetName != null) { + fSearchField.setEditFieldControlText(fTargetName); + } + if (rootNode.isWindowsNode()) { + fIncludeSystem = settings.get(INCLUDE_SYSTEM) == null ? true : settings.getBoolean(INCLUDE_SYSTEM); + fIncludeHidden = settings.get(INCLUDE_HIDDEN) == null ? true : settings.getBoolean(INCLUDE_HIDDEN); + } + } + else { + fCaseSensitive = false; + fMatchPrecise = false; + fTargetType = 0; + fTargetName = null; + if(rootNode.isWindowsNode()) { + fIncludeHidden = true; + fIncludeSystem = true; + } + } + fBtnCase.setSelection(fCaseSensitive); + fBtnMatch.setSelection(fMatchPrecise); + fCmbTypes.select(fTargetType); + if (fTargetName != null) { + fSearchField.setEditFieldControlText(fTargetName); + } + if (rootNode.isWindowsNode()) { + fBtnSystem.setSelection(fIncludeSystem); + fBtnHidden.setSelection(fIncludeHidden); + } + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.utils.AbstractSearchable#persistValues(org.eclipse.jface.dialogs.IDialogSettings) + */ + @Override + public void persistValues(IDialogSettings settings) { + if(settings != null) { + settings.put(CASE_SENSITIVE, fCaseSensitive); + settings.put(MATCH_PRECISE, fMatchPrecise); + settings.put(TARGET_TYPE, fTargetType); + settings.put(TARGET_NAME, fTargetName); + if(rootNode.isWindowsNode()) { + settings.put(INCLUDE_SYSTEM, fIncludeSystem); + settings.put(INCLUDE_HIDDEN, fIncludeHidden); + } + } + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.interfaces.ISearchable#getMatcher() + */ + @Override + public ISearchMatcher getMatcher() { + return new FSTreeNodeMatcher(fCaseSensitive, fMatchPrecise, fTargetType, fTargetName, fIncludeSystem, fIncludeHidden); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.utils.AbstractSearchable#isInputValid() + */ + @Override + public boolean isInputValid() { + return fSearchField.isValid(); + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.ui.utils.AbstractSearchable#getPreferredSize() + */ + @Override + public Point getPreferredSize() { + return new Point(400, rootNode.isWindowsNode() ? 200 : 180); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/FSModifiedSearchable.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/FSModifiedSearchable.java new file mode 100644 index 000000000..df7113707 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/FSModifiedSearchable.java @@ -0,0 +1,253 @@ +/******************************************************************************* + * 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.te.tcf.filesystem.ui.internal.search; + +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.events.SelectionListener; +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.Text; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.tcf.te.ui.controls.BaseEditBrowseTextControl; +import org.eclipse.tcf.te.ui.search.TreeViewerSearchDialog; + +/** + * The searchable that provides a UI to collect and test + * the last modified time of a file during searching. + */ +public class FSModifiedSearchable extends FSBaseSearchable { + // Constant values of last modified options + private static final int OPTION_NOT_REMEMBER = 0; + private static final int OPTION_LAST_WEEK = 1; + private static final int OPTION_LAST_MONTH = 2; + private static final int OPTION_LAST_YEAR = 3; + private static final int OPTION_SPECIFIED = 4; + + // Constant values of different time unit, used for matching purpose. + private static final long SECOND = 1000L; + private static final long MINUTE = 60 * SECOND; + private static final long HOUR = 60 * MINUTE; + private static final long DAY = 24 * HOUR; + private static final long WEEK = 7 * DAY; + private static final long MONTH = 30 * DAY; + private static final long YEAR = 365 * DAY; + + // The choice selected + private int choice; + // The specified "from" date + private long fromTime; + // The specified "to" date + private long toTime; + + // UI elements for input + private Button fBtnLmNotRem; + private Button fBtnLmLastWeek; + private Button fBtnLmPastMonth; + private Button fBtnLmPastYear; + private Button fBtnLmSpecified; + private BaseEditBrowseTextControl txtLmFrom; + private BaseEditBrowseTextControl txtLmTo; + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.ui.utils.AbstractSearchable#createAdvancedPart(org.eclipse.tcf.te.ui.search.TreeViewerSearchDialog, org.eclipse.swt.widgets.Composite) + */ + @Override + public void createAdvancedPart(TreeViewerSearchDialog dialog, Composite parent) { + SelectionListener l = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + optionChecked(e); + } + }; + Composite modifiedComp = createSection(parent, Messages.FSModifiedSearchable_WhenModified); + modifiedComp.setLayout(new GridLayout(4, false)); + + fBtnLmNotRem = new Button(modifiedComp, SWT.RADIO); + fBtnLmNotRem.setText(Messages.FSModifiedSearchable_DontRemember); + fBtnLmNotRem.setSelection(true); + GridData data = new GridData(); + data.horizontalSpan = 4; + fBtnLmNotRem.setLayoutData(data); + fBtnLmNotRem.addSelectionListener(l); + + fBtnLmLastWeek = new Button(modifiedComp, SWT.RADIO); + fBtnLmLastWeek.setText(Messages.FSModifiedSearchable_LastWeek); + data = new GridData(); + data.horizontalSpan = 4; + fBtnLmLastWeek.setLayoutData(data); + fBtnLmLastWeek.addSelectionListener(l); + + fBtnLmPastMonth = new Button(modifiedComp, SWT.RADIO); + fBtnLmPastMonth.setText(Messages.FSModifiedSearchable_PastMonth); + data = new GridData(); + data.horizontalSpan = 4; + fBtnLmPastMonth.setLayoutData(data); + fBtnLmPastMonth.addSelectionListener(l); + + fBtnLmPastYear = new Button(modifiedComp, SWT.RADIO); + fBtnLmPastYear.setText(Messages.FSModifiedSearchable_PastYear); + data = new GridData(); + data.horizontalSpan = 4; + fBtnLmPastYear.setLayoutData(data); + fBtnLmPastYear.addSelectionListener(l); + + fBtnLmSpecified = new Button(modifiedComp, SWT.RADIO); + fBtnLmSpecified.setText(Messages.FSModifiedSearchable_SpecifyDates); + data = new GridData(); + fBtnLmSpecified.setLayoutData(data); + fBtnLmSpecified.addSelectionListener(l); + + Composite cmpFrom = new Composite(modifiedComp, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + layout.marginWidth = 0; + layout.marginHeight = 0; + layout.horizontalSpacing = 0; + layout.verticalSpacing = 0; + cmpFrom.setLayout(layout); + data = new GridData(); + cmpFrom.setLayoutData(data); + + txtLmFrom = new BaseEditBrowseTextControl(null); + txtLmFrom.setIsGroup(false); + txtLmFrom.setHasHistory(false); + txtLmFrom.setHideBrowseButton(true); + txtLmFrom.setParentControlIsInnerPanel(true); + txtLmFrom.setupPanel(cmpFrom); + txtLmFrom.setEnabled(false); + txtLmFrom.setEditFieldValidator(new DateValidator()); + Text text = (Text) txtLmFrom.getEditFieldControl(); + text.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + datesModified(); + } + }); + + Label label = new Label(modifiedComp, SWT.NONE); + label.setText(Messages.FSModifiedSearchable_ToDate); + + Composite cmpTo = new Composite(modifiedComp, SWT.NONE); + layout = new GridLayout(2, false); + layout.marginWidth = 0; + layout.marginHeight = 0; + layout.horizontalSpacing = 0; + layout.verticalSpacing = 0; + cmpTo.setLayout(layout); + data = new GridData(); + cmpTo.setLayoutData(data); + + txtLmTo = new BaseEditBrowseTextControl(null); + txtLmTo.setIsGroup(false); + txtLmTo.setHasHistory(false); + txtLmTo.setHideBrowseButton(true); + txtLmTo.setParentControlIsInnerPanel(true); + txtLmTo.setupPanel(cmpTo); + txtLmTo.setEnabled(false); + txtLmTo.setEditFieldValidator(new DateValidator()); + text = (Text) txtLmTo.getEditFieldControl(); + text.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + datesModified(); + } + }); + } + + /** + * The modified event of the date fields. + */ + protected void datesModified() { + fireOptionChanged(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.utils.AbstractSearchable#isInputValid() + */ + @Override + public boolean isInputValid() { + if(choice == OPTION_SPECIFIED && txtLmFrom != null && txtLmTo != null) { + boolean vFrom = txtLmFrom.isValid(); + boolean vTo = txtLmTo.isValid(); + if(vFrom) { + String fromText = txtLmFrom.getEditFieldControlText().trim(); + this.fromTime = DateValidator.parseTimeInMillis(fromText); + } + if(vTo) { + String toText = txtLmTo.getEditFieldControlText().trim(); + this.toTime = DateValidator.parseTimeInMillis(toText); + } + return vFrom && vTo; + } + return true; + } + + /** + * The method handling the selection event. + * + * @param e The selection event. + */ + protected void optionChecked(SelectionEvent e) { + Object src = e.getSource(); + boolean specified = false; + if(src == fBtnLmNotRem) { + choice = OPTION_NOT_REMEMBER; + } + else if(src == fBtnLmLastWeek) { + choice = OPTION_LAST_WEEK; + } + else if(src == fBtnLmPastMonth) { + choice = OPTION_LAST_MONTH; + } + else if(src == fBtnLmPastYear) { + choice = OPTION_LAST_YEAR; + } + else if(src == fBtnLmSpecified) { + choice = OPTION_SPECIFIED; + specified = true; + } + if (txtLmFrom != null) txtLmFrom.setEnabled(specified); + if (txtLmTo != null) txtLmTo.setEnabled(specified); + fireOptionChanged(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.interfaces.ISearchMatcher#match(java.lang.Object) + */ + @Override + public boolean match(Object element) { + if (element instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode) element; + long now = System.currentTimeMillis(); + switch (choice) { + case OPTION_NOT_REMEMBER: + return true; + case OPTION_LAST_WEEK: + return node.attr.mtime > now - WEEK; + case OPTION_LAST_MONTH: + return node.attr.mtime > now - MONTH; + case OPTION_LAST_YEAR: + return node.attr.mtime > now - YEAR; + case OPTION_SPECIFIED: + return node.attr.mtime >= fromTime && node.attr.mtime < toTime; + } + } + return false; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/FSSizeSearchable.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/FSSizeSearchable.java new file mode 100644 index 000000000..fbd42c2ce --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/FSSizeSearchable.java @@ -0,0 +1,255 @@ +/******************************************************************************* + * 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.te.tcf.filesystem.ui.internal.search; + +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.events.SelectionListener; +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.Text; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.tcf.te.ui.controls.BaseEditBrowseTextControl; +import org.eclipse.tcf.te.ui.search.TreeViewerSearchDialog; + +/** + * The searchable that provides a UI to collect and test + * the size of a file during searching. + */ +public class FSSizeSearchable extends FSBaseSearchable { + // Constant values of size options + private static final int OPTION_NOT_REMEMBER = 0; + private static final int OPTION_SIZE_SMALL = 1; + private static final int OPTION_SIZE_MEDIUM = 2; + private static final int OPTION_SIZE_LARGE = 3; + private static final int OPTION_SIZE_SPECIFIED = 4; + + // Constant values of different size unit, used for matching purpose. + private static final long KB = 1024; + private static final long MB = 1024 * KB; + + private static final long SIZE_SMALL = 100 * KB; + private static final long SIZE_MEDIUM = 1*MB; + + // The choice selected + private int choice; + // The lower bound of size + private int lowerSize; + // The upper bound of size + private int upperSize; + + // UI elements for input + private Button fBtnSizeNotRem; + private Button fBtnSizeSmall; + private Button fBtnSizeMedium; + private Button fBtnSizeLarge; + private Button fBtnSizeSpecified; + private BaseEditBrowseTextControl txtSizeFrom; + private BaseEditBrowseTextControl txtSizeTo; + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.ui.utils.AbstractSearchable#createAdvancedPart(org.eclipse.tcf.te.ui.search.TreeViewerSearchDialog, org.eclipse.swt.widgets.Composite) + */ + @Override + public void createAdvancedPart(TreeViewerSearchDialog dialog, Composite parent) { + SelectionListener l = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + optionChecked(e); + } + }; + + Composite sizeComp = createSection(parent, Messages.FSSizeSearchable_WhatSize); + sizeComp.setLayout(new GridLayout(5, false)); + + fBtnSizeNotRem = new Button(sizeComp, SWT.RADIO); + fBtnSizeNotRem.setText(Messages.FSSizeSearchable_DontRemember); + fBtnSizeNotRem.setSelection(true); + GridData data = new GridData(); + data.horizontalSpan = 5; + fBtnSizeNotRem.setLayoutData(data); + fBtnSizeNotRem.addSelectionListener(l); + + fBtnSizeSmall = new Button(sizeComp, SWT.RADIO); + fBtnSizeSmall.setText(Messages.FSSizeSearchable_Small); + data = new GridData(); + data.horizontalSpan = 5; + fBtnSizeSmall.setLayoutData(data); + fBtnSizeSmall.addSelectionListener(l); + + fBtnSizeMedium = new Button(sizeComp, SWT.RADIO); + fBtnSizeMedium.setText(Messages.FSSizeSearchable_Medium); + data = new GridData(); + data.horizontalSpan = 5; + fBtnSizeMedium.setLayoutData(data); + fBtnSizeMedium.addSelectionListener(l); + + fBtnSizeLarge = new Button(sizeComp, SWT.RADIO); + fBtnSizeLarge.setText(Messages.FSSizeSearchable_Large); + data = new GridData(); + data.horizontalSpan = 5; + fBtnSizeLarge.setLayoutData(data); + fBtnSizeLarge.addSelectionListener(l); + + fBtnSizeSpecified = new Button(sizeComp, SWT.RADIO); + fBtnSizeSpecified.setText(Messages.FSSizeSearchable_SpecifySize); + data = new GridData(); + fBtnSizeSpecified.setLayoutData(data); + fBtnSizeSpecified.addSelectionListener(l); + + Composite cmpFrom = new Composite(sizeComp, SWT.NONE); + GridLayout layout = new GridLayout(2, false); + layout.marginWidth = 0; + layout.marginHeight = 0; + layout.horizontalSpacing = 0; + layout.verticalSpacing = 0; + cmpFrom.setLayout(layout); + data = new GridData(); + cmpFrom.setLayoutData(data); + + txtSizeFrom = new BaseEditBrowseTextControl(null); + txtSizeFrom.setIsGroup(false); + txtSizeFrom.setHasHistory(false); + txtSizeFrom.setHideBrowseButton(true); + txtSizeFrom.setParentControlIsInnerPanel(true); + txtSizeFrom.setupPanel(cmpFrom); + txtSizeFrom.setEnabled(false); + txtSizeFrom.setEditFieldValidator(new SizeValidator()); + Text text = (Text) txtSizeFrom.getEditFieldControl(); + text.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + sizeModified(); + } + }); + + + Label label = new Label(sizeComp, SWT.NONE); + label.setText(Messages.FSSizeSearchable_ToText); + + Composite cmpTo = new Composite(sizeComp, SWT.NONE); + layout = new GridLayout(2, false); + layout.marginWidth = 0; + layout.marginHeight = 0; + layout.horizontalSpacing = 0; + layout.verticalSpacing = 0; + cmpTo.setLayout(layout); + data = new GridData(); + cmpTo.setLayoutData(data); + + txtSizeTo = new BaseEditBrowseTextControl(null); + txtSizeTo.setIsGroup(false); + txtSizeTo.setHasHistory(false); + txtSizeTo.setHideBrowseButton(true); + txtSizeTo.setParentControlIsInnerPanel(true); + txtSizeTo.setupPanel(cmpTo); + txtSizeTo.setEnabled(false); + txtSizeTo.setEditFieldValidator(new SizeValidator()); + text = (Text) txtSizeTo.getEditFieldControl(); + text.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + sizeModified(); + } + }); + + label = new Label(sizeComp, SWT.NONE); + label.setText(Messages.FSSizeSearchable_KBS); + } + + /** + * The modified event of the size fields. + */ + protected void sizeModified() { + fireOptionChanged(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.utils.AbstractSearchable#isInputValid() + */ + @Override + public boolean isInputValid() { + if(choice == OPTION_SIZE_SPECIFIED && txtSizeFrom != null && txtSizeTo != null) { + boolean vFrom = txtSizeFrom.isValid(); + boolean vTo = txtSizeTo.isValid(); + if(vFrom) { + String fromText = txtSizeFrom.getEditFieldControlText(); + this.lowerSize = Integer.parseInt(fromText); + } + if(vTo) { + String toText = txtSizeTo.getEditFieldControlText(); + this.upperSize = Integer.parseInt(toText); + } + return vFrom && vTo; + } + return true; + } + + /** + * The method handling the selection event. + * + * @param e The selection event. + */ + protected void optionChecked(SelectionEvent e) { + Object src = e.getSource(); + boolean specified = false; + if(src == fBtnSizeNotRem) { + choice = OPTION_NOT_REMEMBER; + } + else if(src == fBtnSizeSmall) { + choice = OPTION_SIZE_SMALL; + } + else if(src == fBtnSizeMedium) { + choice = OPTION_SIZE_MEDIUM; + } + else if(src == fBtnSizeLarge) { + choice = OPTION_SIZE_LARGE; + } + else if(src == fBtnSizeSpecified) { + choice = OPTION_SIZE_SPECIFIED; + specified = true; + } + if (txtSizeFrom != null) txtSizeFrom.setEnabled(specified); + if (txtSizeTo != null) txtSizeTo.setEnabled(specified); + fireOptionChanged(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.interfaces.ISearchMatcher#match(java.lang.Object) + */ + @Override + public boolean match(Object element) { + if (element instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode) element; + switch (choice) { + case OPTION_NOT_REMEMBER: + return true; + case OPTION_SIZE_SMALL: + return node.attr.size <= SIZE_SMALL; + case OPTION_SIZE_MEDIUM: + return node.attr.size <= SIZE_MEDIUM; + case OPTION_SIZE_LARGE: + return node.attr.size > SIZE_MEDIUM; + case OPTION_SIZE_SPECIFIED: + return node.attr.size >= lowerSize && node.attr.size < upperSize; + } + } + return false; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/FSTreeNodeMatcher.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/FSTreeNodeMatcher.java new file mode 100644 index 000000000..3d2c80d9a --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/FSTreeNodeMatcher.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2012, 2014 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.te.tcf.filesystem.ui.internal.search; + +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.ui.interfaces.ISearchMatcher; +import org.eclipse.tcf.te.ui.utils.StringMatcher; +/** + * The ISearchMatcher implementation for FSTreeNode. + */ +public class FSTreeNodeMatcher implements ISearchMatcher { + // Whether it is case sensitive + private boolean fCaseSensitive; + // Whether it is precise matching. + private boolean fMatchPrecise; + // The string matcher used for matching. + private StringMatcher fStringMatcher; + // The current selected target simulator index. + private int fTargetType; + // The current target names. + private String fTargetName; + // The flag if system files should be included + private boolean fIncludeSystem; + // The flag if hidden files should be included + private boolean fIncludeHidden; + + /** + * Constructor with different option parameters. + * + * @param caseSensitive Option of case sensitive + * @param matchPrecise Option of precise matching + * @param targetType Option of the target simulator + * @param targetName Option of the target name + * @param includeSystem Option if system files be included + * @param includeHidden Option if hidden files be included + */ + public FSTreeNodeMatcher(boolean caseSensitive, boolean matchPrecise, + int targetType, String targetName, boolean includeSystem, boolean includeHidden) { + fCaseSensitive = caseSensitive; + fTargetName = targetName; + fMatchPrecise = matchPrecise; + if (!fMatchPrecise) { + fStringMatcher = new StringMatcher(fTargetName, !fCaseSensitive, false); + } + fTargetType = targetType; + fIncludeSystem = includeSystem; + fIncludeHidden = includeHidden; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.interfaces.ISearchMatcher#match(java.lang.Object) + */ + @Override + public boolean match(Object context) { + if (context == null) return false; + if (context instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode) context; + if(fTargetType == 1 && !node.isFile() || fTargetType == 2 && !node.isDirectory()) return false; + if(!fIncludeSystem && node.isSystem()) return false; + if(!fIncludeHidden && node.isHidden()) return false; + String text = node.name; + if (text != null) { + if (fMatchPrecise) { + return fCaseSensitive ? text.equals(fTargetName) : text.equalsIgnoreCase(fTargetName); + } + return fStringMatcher.match(text); + } + } + return false; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/FSTreeNodeSearchable.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/FSTreeNodeSearchable.java new file mode 100644 index 000000000..b75fb2e0c --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/FSTreeNodeSearchable.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * 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.te.tcf.filesystem.ui.internal.search; + +import org.eclipse.osgi.util.NLS; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.tcf.te.ui.utils.CompositeSearchable; + +/** + * The ISearchable adapter for a FSTreeNode which creates a UI for the user to + * input the matching condition and returns a matcher to do the matching. + */ +public class FSTreeNodeSearchable extends CompositeSearchable { + + /** + * Create an instance with the specified node. + * + * @param node The directory node. + */ + public FSTreeNodeSearchable(FSTreeNode node) { + super(); + setSearchables(new FSGeneralSearchable(node), new FSModifiedSearchable(), new FSSizeSearchable()); + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.ui.interfaces.ISearchable#getSearchTitle(java.lang.Object) + */ + @Override + public String getSearchTitle(Object rootElement) { + return Messages.FSTreeNodeSearchable_FindFilesAndFolders; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.interfaces.ISearchable#getSearchMessage(java.lang.Object) + */ + @Override + public String getSearchMessage(Object rootElement) { + String message = Messages.FSTreeNodeSearchable_FindMessage; + FSTreeNode rootNode = (FSTreeNode) rootElement; + String rootName = getElementName(rootElement); + if (rootNode != null && !rootNode.isSystemRoot()) rootName = "\"" + rootName + "\""; //$NON-NLS-1$//$NON-NLS-2$ + message = NLS.bind(message, rootName); + return message; + } + + /** + * Get a name representation for each file node. + * + * @param rootElement The root element whose name is being retrieved. + * @return The node's name or an expression for the file system. + */ + private String getElementName(Object rootElement) { + if(rootElement == null) { + return Messages.FSTreeNodeSearchable_SelectedFileSystem; + } + FSTreeNode rootNode = (FSTreeNode) rootElement; + if(rootNode.isSystemRoot()) { + return Messages.FSTreeNodeSearchable_SelectedFileSystem; + } + return rootNode.name; + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.ui.interfaces.ISearchable#getElementText(java.lang.Object) + */ + @Override + public String getElementText(Object element) { + return getElementName(element); + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.ui.interfaces.ISearchable#getCustomMessage(java.lang.Object, java.lang.String) + */ + @Override + public String getCustomMessage(Object rootElement, String key) { + return null; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/NameValidator.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/NameValidator.java new file mode 100644 index 000000000..821e2e2df --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/NameValidator.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.search; + +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.tcf.te.ui.controls.validator.Validator; + +/** + * The validator used to validate the name entered in the search dialog. + */ +public class NameValidator extends Validator { + /** + * Constructor + */ + public NameValidator() { + super(ATTR_MANDATORY); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.controls.validator.Validator#isValid(java.lang.String) + */ + @Override + public boolean isValid(String newText) { + init(); + boolean valid = newText != null && newText.trim().length() > 0; + if(!valid) { + if (isAttribute(ATTR_MANDATORY)) { + setMessage(Messages.NameValidator_InfoPrompt, INFORMATION); + } + } + return valid; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/SizeValidator.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/SizeValidator.java new file mode 100644 index 000000000..0877e3b4b --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/search/SizeValidator.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.search; + +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.tcf.te.ui.controls.validator.NumberValidator; +import org.eclipse.tcf.te.ui.controls.validator.Validator; + +/** + * The validator used to validate the size entered in the search dialog. + */ +public class SizeValidator extends NumberValidator { + /** + * Constructor + */ + public SizeValidator() { + super(Validator.ATTR_MANDATORY, 0, -1); + setMessageText(INFO_MISSING_VALUE, Messages.SizeValidator_InfoPrompt); + setMessageText(ERROR_INVALID_VALUE, Messages.SizeValidator_ErrorIncorrectFormat); + setMessageText(ERROR_INVALID_RANGE, Messages.SizeValidator_ErrorSizeOutofRange); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/BasicFileSection.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/BasicFileSection.java new file mode 100644 index 000000000..9a78d3b8c --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/BasicFileSection.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.tabbed; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Text; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.tcf.te.ui.swt.SWTControlUtil; +import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage; + +/** + * The section that displays the basic information of a file. + */ +public class BasicFileSection extends BasicFolderSection { + + // The text field for the size of the file. + protected Text sizeText; + // The text field for the access time of the file. + protected Text accessedText; + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.tabbed.BasicFolderSection#createControls(org.eclipse.swt.widgets.Composite, org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage) + */ + @Override + public void createControls(Composite parent, TabbedPropertySheetPage aTabbedPropertySheetPage) { + super.createControls(parent, aTabbedPropertySheetPage); + sizeText = createTextField(null, Messages.GeneralInformationPage_Size); + accessedText = createTextField(sizeText, Messages.GeneralInformationPage_Accessed); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.tabbed.BasicFolderSection#refresh() + */ + @Override + public void refresh() { + SWTControlUtil.setText(sizeText, clone != null ? getSizeText(clone.attr.size) : ""); //$NON-NLS-1$ + SWTControlUtil.setText(accessedText, clone != null ? getDateText(clone.attr.atime) : ""); //$NON-NLS-1$ + super.refresh(); + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/BasicFolderSection.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/BasicFolderSection.java new file mode 100644 index 000000000..00748f2ec --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/BasicFolderSection.java @@ -0,0 +1,116 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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.te.tcf.filesystem.ui.internal.tabbed; + +import java.text.DateFormat; +import java.text.DecimalFormat; +import java.util.Date; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Text; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.adapters.FSTreeNodeAdapterFactory.FSTreeNodePeerNodeProvider; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNodeProvider; +import org.eclipse.tcf.te.tcf.ui.tabbed.BaseTitledSection; +import org.eclipse.tcf.te.ui.swt.SWTControlUtil; +import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage; + +/** + * The section that displays the basic information of a folder. + */ +public class BasicFolderSection extends BaseTitledSection { + // The formatter for the size of a file. + private static final DecimalFormat SIZE_FORMAT = new DecimalFormat(); + + // The original node to be displayed and edited. + protected FSTreeNode node; + // The copy used to be edited. + protected FSTreeNode clone; + + // The text for the name of the node. + protected Text nameText; + // The text for the type of the node. + protected Text typeText; + // The text for the location of the node. + protected Text locationText; + // The text for the modified time of the node. + protected Text modifiedText; + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.tabbed.BaseTitledSection#createControls(org.eclipse.swt.widgets.Composite, org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage) + */ + @Override + public void createControls(Composite parent, TabbedPropertySheetPage aTabbedPropertySheetPage) { + super.createControls(parent, aTabbedPropertySheetPage); + nameText = createTextField(null, Messages.GeneralInformationPage_Name); + typeText = createTextField(nameText, Messages.GeneralInformationPage_Type); + locationText = createWrapTextField(typeText, Messages.GeneralInformationPage_Location); + modifiedText = createTextField(locationText, Messages.GeneralInformationPage_Modified); + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.tabbed.BaseTitledSection#updateData(org.eclipse.tcf.te.ui.interfaces.IPropertyChangeProvider) + */ + @Override + protected void updateInput(IPeerNodeProvider input) { + Assert.isTrue(input instanceof FSTreeNodePeerNodeProvider); + this.node = ((FSTreeNodePeerNodeProvider)input).getFSTreeNode(); + this.clone = (FSTreeNode) node.clone(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.views.properties.tabbed.AbstractPropertySection#refresh() + */ + @Override + public void refresh() { + SWTControlUtil.setText(nameText, clone != null ? clone.name : ""); //$NON-NLS-1$ + SWTControlUtil.setText(typeText, clone != null ? clone.getFileType() : ""); //$NON-NLS-1$ + String location = clone == null || clone.isRoot() ? Messages.GeneralInformationPage_Computer : clone.getLocation(); + SWTControlUtil.setText(locationText, location); + SWTControlUtil.setText(modifiedText, clone != null && clone.attr != null ? getDateText(clone.attr.mtime) : ""); //$NON-NLS-1$ + super.refresh(); + } + + /** + * Get the string of the specific time using the formatter, DATE_FORMAT. + * + * @param time The time to be formatted. + * @return The string in the format of DATE_FORMAT. + */ + protected String getDateText(long time) { + DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT); + return dateFormat.format(new Date(time)); + } + + /** + * Get the string of the file size using using the formatter, SIZE_FORMAT. + * + * @param size + * The size of the file to be formatted. + * @return The string in the format of SIZE_FORMAT. + */ + protected String getSizeText(long size) { + return NLS.bind(Messages.GeneralInformationPage_FileSizeInfo, SIZE_FORMAT.format(size / 1024), SIZE_FORMAT.format(size)); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.tabbed.BaseTitledSection#getText() + */ + @Override + protected String getText() { + return Messages.BasicFolderSection_BasicInfoText; + } +}
\ No newline at end of file diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/FileFilter.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/FileFilter.java new file mode 100644 index 000000000..9ce004377 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/FileFilter.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.tabbed; + +import org.eclipse.jface.viewers.IFilter; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * The filter to test if a object is a file. + */ +public class FileFilter implements IFilter { + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.IFilter#select(java.lang.Object) + */ + @Override + public boolean select(Object toTest) { + if(toTest instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode) toTest; + return !node.isSystemRoot() && node.isFile(); + } + return false; + } + +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/FolderFilter.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/FolderFilter.java new file mode 100644 index 000000000..55b4b3e9c --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/FolderFilter.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.tabbed; + +import org.eclipse.jface.viewers.IFilter; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * The filter to select the folder from the file system. + */ +public class FolderFilter implements IFilter { + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.IFilter#select(java.lang.Object) + */ + @Override + public boolean select(Object toTest) { + if(toTest instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode) toTest; + return !node.isSystemRoot() && node.isDirectory(); + } + return false; + } + +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/LinuxFilter.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/LinuxFilter.java new file mode 100644 index 000000000..ffb5b6b78 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/LinuxFilter.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.tabbed; + +import org.eclipse.jface.viewers.IFilter; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * A filter to test if a object is a linux (non-Windows) node. + */ +public class LinuxFilter implements IFilter { + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.IFilter#select(java.lang.Object) + */ + @Override + public boolean select(Object toTest) { + if(toTest instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode) toTest; + return !node.isSystemRoot() && !node.isWindowsNode(); + } + return false; + } + +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/LinuxPermissionsSection.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/LinuxPermissionsSection.java new file mode 100644 index 000000000..2178562eb --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/LinuxPermissionsSection.java @@ -0,0 +1,139 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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.te.tcf.filesystem.ui.internal.tabbed; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.layout.FormAttachment; +import org.eclipse.swt.layout.FormData; +import org.eclipse.swt.layout.FormLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.adapters.FSTreeNodeAdapterFactory.FSTreeNodePeerNodeProvider; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNodeProvider; +import org.eclipse.tcf.te.tcf.ui.tabbed.BaseTitledSection; +import org.eclipse.tcf.te.ui.swt.SWTControlUtil; +import org.eclipse.ui.views.properties.tabbed.ITabbedPropertyConstants; +import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage; + +/** + * The property section for displaying the permissions of a linux file/folder. + */ +public class LinuxPermissionsSection extends BaseTitledSection { + // The original node. + protected FSTreeNode node; + // The copy node to be edited. + protected FSTreeNode clone; + // The button of "Permissions" + protected Button[] btnPermissions; + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.tabbed.BaseTitledSection#createControls(org.eclipse.swt.widgets.Composite, org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage) + */ + @Override + public void createControls(Composite parent, TabbedPropertySheetPage aTabbedPropertySheetPage) { + super.createControls(parent, aTabbedPropertySheetPage); + btnPermissions = new Button[9]; + Composite comp1 = createPermissionGroup(null, composite, 0, Messages.PermissionsGroup_UserPermissions); + Composite comp2 = createPermissionGroup(comp1, composite, 3, Messages.PermissionsGroup_GroupPermissions); + createPermissionGroup(comp2, composite, 6, Messages.PermissionsGroup_OtherPermissions); + } + + /** + * Create a permission group for a role, such as a user, a group or others. + * + * @param prev The previous permission group to align with. + * @param parent The parent composite. + * @param bit The permission bit index. + * @param header The group's header label. + */ + protected Composite createPermissionGroup(Composite prev, Composite parent, int bit, String header) { + Composite group = getWidgetFactory().createFlatFormComposite(parent); + FormLayout layout = (FormLayout) group.getLayout(); + layout.marginWidth = 0; + layout.marginHeight = 0; + layout.spacing = 0; + + FormData data = new FormData(); + data.left = new FormAttachment(0, STANDARD_LABEL_WIDTH); + data.right = new FormAttachment(100, 0); + if (prev == null) data.top = new FormAttachment(0, ITabbedPropertyConstants.VSPACE); + else data.top = new FormAttachment(prev, ITabbedPropertyConstants.VSPACE); + group.setLayoutData(data); + + createPermissionButton(Messages.PermissionsGroup_Readable, bit, group); + createPermissionButton(Messages.PermissionsGroup_Writable, bit + 1, group); + createPermissionButton(Messages.PermissionsGroup_Executable, bit + 2, group); + + CLabel groupLabel = getWidgetFactory().createCLabel(parent, header); + data = new FormData(); + data.left = new FormAttachment(0, 0); + data.right = new FormAttachment(group, -ITabbedPropertyConstants.HSPACE); + data.top = new FormAttachment(group, 0, SWT.TOP); + groupLabel.setLayoutData(data); + + return group; + } + + /** + * Create a check-box field for a single permission item. + * + * @param label The label of the permission. + * @param index The index of current permission bit mask index. + * @param parent The parent to hold the check-box field. + */ + private void createPermissionButton(String label, final int index, Composite parent) { + btnPermissions[index] = getWidgetFactory().createButton(parent, label, SWT.CHECK); + FormData data = new FormData(); + if ((index % 3) == 0) data.left = new FormAttachment(0, 0); + else data.left = new FormAttachment(btnPermissions[index - 1], ITabbedPropertyConstants.HSPACE); + data.right = new FormAttachment(((index % 3) + 1) * 33, 0); + if ((index % 3) == 0) data.top = new FormAttachment(0, ITabbedPropertyConstants.VSPACE); + else data.top = new FormAttachment(btnPermissions[index - 1], 0, SWT.CENTER); + btnPermissions[index].setLayoutData(data); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.tabbed.BaseTitledSection#updateData(org.eclipse.tcf.te.ui.interfaces.IPropertyChangeProvider) + */ + @Override + protected void updateInput(IPeerNodeProvider input) { + Assert.isTrue(input instanceof FSTreeNodePeerNodeProvider); + this.node = ((FSTreeNodePeerNodeProvider)input).getFSTreeNode(); + this.clone = (FSTreeNode) node.clone(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.views.properties.tabbed.AbstractPropertySection#refresh() + */ + @Override + public void refresh() { + for (int i = 0; i < 9; i++) { + final int bit = 1 << (8 - i); + final boolean on = clone != null ? (clone.attr.permissions & bit) != 0 : false; + SWTControlUtil.setSelection(btnPermissions[i], on); + } + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.tabbed.BaseTitledSection#getText() + */ + @Override + protected String getText() { + return Messages.LinuxPermissionsSection_Permissions; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/WindowsAttributesCESection.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/WindowsAttributesCESection.java new file mode 100644 index 000000000..1c73246b9 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/WindowsAttributesCESection.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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.te.tcf.filesystem.ui.internal.tabbed; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FormAttachment; +import org.eclipse.swt.layout.FormData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IWindowsFileAttributes; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.adapters.FSTreeNodeAdapterFactory.FSTreeNodePeerNodeProvider; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNodeProvider; +import org.eclipse.tcf.te.tcf.ui.tabbed.BaseTitledSection; +import org.eclipse.tcf.te.ui.swt.SWTControlUtil; +import org.eclipse.ui.views.properties.tabbed.ITabbedPropertyConstants; +import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage; + +/** + * The property section for compress and encrypt attributes of a file/folder on Windows. + */ +public class WindowsAttributesCESection extends BaseTitledSection { + + // The original node. + protected FSTreeNode node; + + // The check box to display the compress attribute. + protected Button compressButton; + // The check box to display the encrypt attributes. + protected Button encryptButton; + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.tabbed.BaseTitledSection#createControls(org.eclipse.swt.widgets.Composite, org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage) + */ + @Override + public void createControls(Composite parent, TabbedPropertySheetPage aTabbedPropertySheetPage) { + super.createControls(parent, aTabbedPropertySheetPage); + + compressButton = getWidgetFactory().createButton(composite, Messages.AdvancedAttributesDialog_Compress, SWT.CHECK); + FormData data = new FormData(); + data.left = new FormAttachment(0, 0); + data.right = new FormAttachment(100, 0); + data.top = new FormAttachment(0, ITabbedPropertyConstants.VSPACE); + compressButton.setLayoutData(data); + + encryptButton = getWidgetFactory().createButton(composite, Messages.AdvancedAttributesDialog_Compress, SWT.CHECK); + data = new FormData(); + data.left = new FormAttachment(0, 0); + data.right = new FormAttachment(100, 0); + data.top = new FormAttachment(compressButton, ITabbedPropertyConstants.VSPACE); + encryptButton.setLayoutData(data); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.tabbed.BaseTitledSection#updateData(org.eclipse.tcf.te.ui.interfaces.IPropertyChangeProvider) + */ + @Override + protected void updateInput(IPeerNodeProvider input) { + Assert.isTrue(input instanceof FSTreeNodePeerNodeProvider); + this.node = ((FSTreeNodePeerNodeProvider)input).getFSTreeNode(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.views.properties.tabbed.AbstractPropertySection#refresh() + */ + @Override + public void refresh() { + boolean on = node != null ? node.isWin32AttrOn(IWindowsFileAttributes.FILE_ATTRIBUTE_COMPRESSED) : false; + SWTControlUtil.setSelection(compressButton, on); + on = node != null ? node.isWin32AttrOn(IWindowsFileAttributes.FILE_ATTRIBUTE_ENCRYPTED) : false; + SWTControlUtil.setSelection(encryptButton, on); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.tabbed.BaseTitledSection#getText() + */ + @Override + protected String getText() { + return Messages.AdvancedAttributesDialog_CompressEncrypt; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/WindowsAttributesSection.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/WindowsAttributesSection.java new file mode 100644 index 000000000..dfc7a701c --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/WindowsAttributesSection.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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.te.tcf.filesystem.ui.internal.tabbed; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FormAttachment; +import org.eclipse.swt.layout.FormData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.adapters.FSTreeNodeAdapterFactory.FSTreeNodePeerNodeProvider; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNodeProvider; +import org.eclipse.tcf.te.tcf.ui.tabbed.BaseTitledSection; +import org.eclipse.tcf.te.ui.swt.SWTControlUtil; +import org.eclipse.ui.views.properties.tabbed.ITabbedPropertyConstants; +import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage; + +/** + * The property section for the attributes of a file/folder on Windows. + */ +public class WindowsAttributesSection extends BaseTitledSection { + // The original node. + protected FSTreeNode node; + // The copy node. + protected FSTreeNode clone; + // The check box for "Read Only" attribute. + protected Button readOnlyButton; + // The check box for "Hidden" attribute. + protected Button hiddenButton; + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.tabbed.BaseTitledSection#createControls(org.eclipse.swt.widgets.Composite, org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage) + */ + @Override + public void createControls(Composite parent, TabbedPropertySheetPage aTabbedPropertySheetPage) { + super.createControls(parent, aTabbedPropertySheetPage); + + readOnlyButton = getWidgetFactory().createButton(composite, Messages.GeneralInformationPage_ReadOnly, SWT.CHECK); + FormData data = new FormData(); + data.left = new FormAttachment(0, ITabbedPropertyConstants.HMARGIN ); + data.right = new FormAttachment(50, 0); + data.top = new FormAttachment(0, ITabbedPropertyConstants.VSPACE); + readOnlyButton.setLayoutData(data); + + hiddenButton = getWidgetFactory().createButton(composite, Messages.GeneralInformationPage_Hidden, SWT.CHECK); + data = new FormData(); + data.left = new FormAttachment(readOnlyButton, ITabbedPropertyConstants.HSPACE); + data.right = new FormAttachment(100, -ITabbedPropertyConstants.HMARGIN ); + data.top = new FormAttachment(readOnlyButton, 0, SWT.CENTER); + hiddenButton.setLayoutData(data); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.tabbed.BaseTitledSection#updateData(org.eclipse.tcf.te.ui.interfaces.IPropertyChangeProvider) + */ + @Override + protected void updateInput(IPeerNodeProvider input) { + Assert.isTrue(input instanceof FSTreeNodePeerNodeProvider); + this.node = ((FSTreeNodePeerNodeProvider)input).getFSTreeNode(); + this.clone = (FSTreeNode) node.clone(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.views.properties.tabbed.AbstractPropertySection#refresh() + */ + @Override + public void refresh() { + SWTControlUtil.setSelection(readOnlyButton, clone != null ? clone.isReadOnly() : false); + SWTControlUtil.setSelection(hiddenButton, clone != null ? clone.isHidden(): false); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.tabbed.BaseTitledSection#getText() + */ + @Override + protected String getText() { + return Messages.WindowsAttributesSection_Attributes; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/WindowsFileAISection.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/WindowsFileAISection.java new file mode 100644 index 000000000..6ac4eaa44 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/WindowsFileAISection.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.tabbed; + +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; + +/** + * The property section to display the file's archive and index attributes on Windows. + */ +public class WindowsFileAISection extends WindowsFolderAISection { + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.tabbed.WindowsFolderAISection#getAchiveText() + */ + @Override + protected String getAchiveText() { + return Messages.AdvancedAttributesDialog_FileArchive; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.tabbed.WindowsFolderAISection#getIndexText() + */ + @Override + protected String getIndexText() { + return Messages.AdvancedAttributesDialog_IndexFile; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/WindowsFileFilter.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/WindowsFileFilter.java new file mode 100644 index 000000000..d2694c893 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/WindowsFileFilter.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.tabbed; + +import org.eclipse.jface.viewers.IFilter; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * The filter to test if a object is a Windows file. + */ +public class WindowsFileFilter implements IFilter { + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.IFilter#select(java.lang.Object) + */ + @Override + public boolean select(Object toTest) { + if(toTest instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode) toTest; + return !node.isSystemRoot() && node.isWindowsNode() && node.isFile(); + } + return false; + } + +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/WindowsFilter.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/WindowsFilter.java new file mode 100644 index 000000000..85b53dc36 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/WindowsFilter.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.tabbed; + +import org.eclipse.jface.viewers.IFilter; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * The filter to test if a object is a Windows node. + */ +public class WindowsFilter implements IFilter { + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.IFilter#select(java.lang.Object) + */ + @Override + public boolean select(Object toTest) { + if(toTest instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode) toTest; + return !node.isSystemRoot() && node.isWindowsNode() && (node.isFile() || node.isDirectory()); + } + return false; + } + +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/WindowsFolderAISection.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/WindowsFolderAISection.java new file mode 100644 index 000000000..703f33ed9 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/WindowsFolderAISection.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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.te.tcf.filesystem.ui.internal.tabbed; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FormAttachment; +import org.eclipse.swt.layout.FormData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.tcf.te.tcf.filesystem.core.interfaces.IWindowsFileAttributes; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.adapters.FSTreeNodeAdapterFactory.FSTreeNodePeerNodeProvider; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNodeProvider; +import org.eclipse.tcf.te.tcf.ui.tabbed.BaseTitledSection; +import org.eclipse.tcf.te.ui.swt.SWTControlUtil; +import org.eclipse.ui.views.properties.tabbed.ITabbedPropertyConstants; +import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage; + +/** + * The property section to display a folder's archive and index attributes on Windows. + */ +public class WindowsFolderAISection extends BaseTitledSection { + + // The original node. + protected FSTreeNode node; + + // The check box for archive attribute. + protected Button archiveButton; + // The check box for index attribute. + protected Button indexButton; + + /* + * (non-Javadoc) + * @see + * org.eclipse.tcf.te.ui.views.tabbed.BaseTitledSection#createControls(org.eclipse.swt.widgets + * .Composite, org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage) + */ + @Override + public void createControls(Composite parent, TabbedPropertySheetPage aTabbedPropertySheetPage) { + super.createControls(parent, aTabbedPropertySheetPage); + + archiveButton = getWidgetFactory().createButton(composite, getAchiveText(), SWT.CHECK); + FormData data = new FormData(); + data.left = new FormAttachment(0, 0); + data.right = new FormAttachment(100, 0); + data.top = new FormAttachment(0, ITabbedPropertyConstants.VSPACE); + archiveButton.setLayoutData(data); + + indexButton = getWidgetFactory().createButton(composite, getIndexText(), SWT.CHECK); + data = new FormData(); + data.left = new FormAttachment(0, 0); + data.right = new FormAttachment(100, 0); + data.top = new FormAttachment(archiveButton, ITabbedPropertyConstants.VSPACE); + indexButton.setLayoutData(data); + } + + /** + * Get the archive's label text. + * + * @return The archive's label text. + */ + protected String getAchiveText() { + return Messages.AdvancedAttributesDialog_FolderArchive; + } + + /** + * Get the index's label text. + * + * @return The index's label text. + */ + protected String getIndexText() { + return Messages.AdvancedAttributesDialog_IndexFolder; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.tabbed.BaseTitledSection#updateData(org.eclipse.tcf.te.ui.interfaces.IPropertyChangeProvider) + */ + @Override + protected void updateInput(IPeerNodeProvider input) { + Assert.isTrue(input instanceof FSTreeNodePeerNodeProvider); + this.node = ((FSTreeNodePeerNodeProvider)input).getFSTreeNode(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.views.properties.tabbed.AbstractPropertySection#refresh() + */ + @Override + public void refresh() { + boolean on = node != null ? node.isWin32AttrOn(IWindowsFileAttributes.FILE_ATTRIBUTE_ARCHIVE) : false; + SWTControlUtil.setSelection(archiveButton, on); + on = node != null ? !node.isWin32AttrOn(IWindowsFileAttributes.FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) : false; + SWTControlUtil.setSelection(indexButton, on); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.views.tabbed.BaseTitledSection#getText() + */ + @Override + protected String getText() { + return Messages.AdvancedAttributesDialog_ArchiveIndex; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/WindowsFolderFilter.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/WindowsFolderFilter.java new file mode 100644 index 000000000..84d8d1553 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/tabbed/WindowsFolderFilter.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.tabbed; + +import org.eclipse.jface.viewers.IFilter; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; + +/** + * The filter to test if the object is a Windows folder. + */ +public class WindowsFolderFilter implements IFilter { + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.IFilter#select(java.lang.Object) + */ + @Override + public boolean select(Object toTest) { + if(toTest instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode) toTest; + return !node.isSystemRoot() && node.isWindowsNode() && node.isDirectory(); + } + return false; + } + +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/testers/CachePropertyTester.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/testers/CachePropertyTester.java new file mode 100644 index 000000000..7c54c999d --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/testers/CachePropertyTester.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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 + * William Chen (Wind River)- [345552] Edit the remote files with a proper editor + *******************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.ui.internal.testers; + +import org.eclipse.core.expressions.PropertyTester; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; + +/** + * Provide a tester to test if the current auto saving mode is on or off. + * + */ +public class CachePropertyTester extends PropertyTester { + /** + * Create a cache property tester. + */ + public CachePropertyTester() { + } + + /* (non-Javadoc) + * @see org.eclipse.core.expressions.IPropertyTester#test(java.lang.Object, java.lang.String, java.lang.Object[], java.lang.Object) + */ + @Override + public boolean test(Object receiver, String property, Object[] args, Object expectedValue) { + if(property.equals("isAutoSavingOn")){ //$NON-NLS-1$ + return UIPlugin.isAutoSaving(); + } + return false; + } + +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/testers/ClipboardPropertyTester.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/testers/ClipboardPropertyTester.java new file mode 100644 index 000000000..b01558655 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/testers/ClipboardPropertyTester.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.testers; + +import java.util.List; + +import org.eclipse.core.expressions.PropertyTester; +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.FileTransfer; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.activator.UIPlugin; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.operations.FsClipboard; +/** + * Provide a tester to test if the paste operation is enabled. + */ +public class ClipboardPropertyTester extends PropertyTester { + + /** + * Create an instance. + */ + public ClipboardPropertyTester() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.core.expressions.IPropertyTester#test(java.lang.Object, java.lang.String, java.lang.Object[], java.lang.Object) + */ + @Override + public boolean test(Object receiver, String property, Object[] args, Object expectedValue) { + Assert.isTrue(receiver instanceof IStructuredSelection); + if (property.equals("canPaste")) { //$NON-NLS-1$ + FsClipboard cb = UIPlugin.getClipboard(); + if (!cb.isEmpty()) { + List<FSTreeNode> nodes = cb.getFiles(); + boolean moving = cb.isCutOp(); + boolean copying = cb.isCopyOp(); + List<FSTreeNode> selection = ((IStructuredSelection) receiver).toList(); + FSTreeNode hovered = null; + Assert.isTrue(!selection.isEmpty()); + if (selection.size() == 1) { + FSTreeNode node = selection.get(0); + if (node.isDirectory() && moving) { + hovered = node; + } + else if (node.isRoot()) { + hovered = node; + } + else { + hovered = node.getParent(); + } + } + else { + for (FSTreeNode node : selection) { + if (hovered == null) hovered = node.getParent(); + else if (hovered != node.getParent()) return false; + } + } + if (hovered != null && hovered.isDirectory() && hovered.isWritable() && (moving || copying)) { + FSTreeNode head = nodes.get(0); + String hid = head.peerNode.getPeerId(); + String tid = hovered.peerNode.getPeerId(); + if (hid.equals(tid)) { + for (FSTreeNode node : nodes) { + if (moving && node.getParent() == hovered || node.isAncestorOf(hovered)) { + return false; + } + } + return true; + } + } + } + else { + Clipboard clipboard = cb.getSystemClipboard(); + Object contents = clipboard.getContents(FileTransfer.getInstance()); + if (contents != null) { + List<FSTreeNode> selection = ((IStructuredSelection) receiver).toList(); + FSTreeNode hovered = null; + Assert.isTrue(!selection.isEmpty()); + if (selection.size() == 1) { + FSTreeNode node = selection.get(0); + if (node.isFile()) { + hovered = node.getParent(); + } + else { + hovered = node; + } + } + else { + for (FSTreeNode node : selection) { + if (hovered == null) hovered = node.getParent(); + else if (hovered != node.getParent()) return false; + } + } + if (hovered != null && hovered.isDirectory() && hovered.isWritable()) { + return true; + } + return false; + } + } + } + return false; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/testers/EditorActivationEventPropertyTester.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/testers/EditorActivationEventPropertyTester.java new file mode 100644 index 000000000..0f4259f13 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/testers/EditorActivationEventPropertyTester.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.testers; + +import org.eclipse.core.expressions.PropertyTester; +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent; + +/** + * The property tester of a ColumnViewerEditorActivationEvent. + * The properties include "isEditorActivation" which calculates + * if the event will trigger a cell editing action. + */ +public class EditorActivationEventPropertyTester extends PropertyTester { + + /** + * Create an instance. + */ + public EditorActivationEventPropertyTester() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.core.expressions.IPropertyTester#test(java.lang.Object, java.lang.String, java.lang.Object[], java.lang.Object) + */ + @Override + public boolean test(Object receiver, String property, Object[] args, Object expectedValue) { + Assert.isTrue(receiver instanceof ColumnViewerEditorActivationEvent); + ColumnViewerEditorActivationEvent event = (ColumnViewerEditorActivationEvent) receiver; + if (property.equals("isEditorActivation")) { //$NON-NLS-1$ + return event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC; + } + return false; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/FolderValidator.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/FolderValidator.java new file mode 100644 index 000000000..6ca8422bc --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/FolderValidator.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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.te.tcf.filesystem.ui.internal.wizards; + +import org.eclipse.jface.dialogs.IMessageProvider; +import org.eclipse.osgi.util.NLS; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.tcf.te.ui.controls.validator.Validator; + +/** + * The validator to validate the path of the parent directory in the new file/folder wizard + * page is valid. It is only when it is not empty and it exists in the target peer. + * + * @see Validator + */ +public class FolderValidator extends Validator { + // The wizard page to create the new node. + private NewNodeWizardPage page; + + /** + * Create a folder validator of the specified wizard page. + * + * @param page The wizard page to create the new file/folder. + */ + public FolderValidator(NewNodeWizardPage page) { + super(ATTR_MANDATORY); + this.page = page; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.controls.validator.Validator#isValid(java.lang.String) + */ + @Override + public boolean isValid(String newText) { + if (newText == null || newText.trim().length() == 0) { + setMessage(Messages.FolderValidator_SpecifyFolder, IMessageProvider.ERROR); + return false; + } + FSTreeNode folder = page.getInputDir(); + if (folder == null) { + setMessage(NLS.bind(Messages.FolderValidator_DirNotExist, newText), IMessageProvider.ERROR); + return false; + } + if (!folder.isWritable()) { + setMessage(NLS.bind(Messages.FolderValidator_NotWritable, newText), IMessageProvider.ERROR); + return false; + } + setMessage(null, IMessageProvider.NONE); + return true; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/NameValidator.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/NameValidator.java new file mode 100644 index 000000000..5329a4f7c --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/NameValidator.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.wizards; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.runtime.SafeRunner; +import org.eclipse.jface.dialogs.IMessageProvider; +import org.eclipse.jface.util.SafeRunnable; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.Operation; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.celleditor.FSCellValidator; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.tcf.te.ui.controls.validator.Validator; + +/** + * The validator to validate the name of a file/folder in the file system of Target Explorer. + * + * @see Validator + */ +public class NameValidator extends Validator { + // The folder in which the new file/folder is to be created. + NewNodeWizardPage wizard; + + /** + * Create a NameValidator with the folder in which the file/folder is created. + * + * @param wizard The parent folder in which the file/folder is created. + */ + public NameValidator(NewNodeWizardPage wizard) { + super(ATTR_MANDATORY); + this.wizard = wizard; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.ui.controls.validator.Validator#isValid(java.lang.String) + */ + @Override + public boolean isValid(String newText) { + FSTreeNode folder = wizard.getInputDir(); + if(folder == null) { + setMessage(Messages.NameValidator_SpecifyFolder, IMessageProvider.INFORMATION); + return false; + } + if (newText == null || newText.trim().length() == 0) { + setMessage(Messages.FSRenamingAssistant_SpecifyNonEmptyName, IMessageProvider.ERROR); + return false; + } + String text = newText.trim(); + if (hasChild(text)) { + setMessage(Messages.FSRenamingAssistant_NameAlreadyExists, IMessageProvider.ERROR); + return false; + } + String formatRegex = folder.isWindowsNode() ? FSCellValidator.WIN_FILENAME_REGEX : FSCellValidator.UNIX_FILENAME_REGEX; + if (!text.matches(formatRegex)) { + setMessage(folder.isWindowsNode() ? Messages.FSRenamingAssistant_WinIllegalCharacters : Messages.FSRenamingAssistant_UnixIllegalCharacters, IMessageProvider.ERROR); + return false; + } + setMessage(null, IMessageProvider.NONE); + return true; + } + + /** + * To test if the folder has a child with the specified name. + * + * @param name The name. + * @return true if it has a child with the name. + */ + private boolean hasChild(String name) { + List<FSTreeNode> nodes = getChildren(); + for (FSTreeNode node : nodes) { + if (node.isWindowsNode()) { + if (node.name.equalsIgnoreCase(name)) return true; + } + else if (node.name.equals(name)) return true; + } + return false; + } + + /** + * Get the folder's current children. If the children has not yet been loaded, then load it. + * + * @return The current children of the folder. + */ + private List<FSTreeNode> getChildren() { + final FSTreeNode folder = wizard.getInputDir(); + if (folder.childrenQueried) { + return folder.getChildren(); + } + final List<FSTreeNode> result = new ArrayList<FSTreeNode>(); + SafeRunner.run(new SafeRunnable() { + @Override + public void handleException(Throwable e) { + // Ignore exception + } + @Override + public void run() throws Exception { + result.addAll(new Operation().getChildren(folder)); + } + }); + return result; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/NewFileWizard.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/NewFileWizard.java new file mode 100644 index 000000000..3ad1bfb76 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/NewFileWizard.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.wizards; + +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpCreate; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpCreateFile; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; + +/** + * The wizard to create a new file in the file system of Target Explorer. + */ +public class NewFileWizard extends NewNodeWizard { + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.wizards.NewNodeWizard#createWizardPage() + */ + @Override + protected NewNodeWizardPage createWizardPage() { + return new NewFileWizardPage(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.wizards.NewNodeWizard#getCreateOp(org.eclipse.tcf.te.tcf.filesystem.model.FSTreeNode, java.lang.String, org.eclipse.tcf.te.runtime.interfaces.callback.ICallback) + */ + @Override + protected OpCreate getCreateOp(FSTreeNode folder, String name) { + return new OpCreateFile(folder, name); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.wizards.NewNodeWizard#getTitle() + */ + @Override + protected String getTitle() { + return Messages.NewFileWizard_NewFileWizardTitle; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/NewFileWizardPage.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/NewFileWizardPage.java new file mode 100644 index 000000000..af1b95b01 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/NewFileWizardPage.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.wizards; + +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; + +/** + * The wizard page to create a new file in the file system of Target Explorer. + */ +public class NewFileWizardPage extends NewNodeWizardPage { + + /** + * Create a wizard page to create a new file in the specified folder. + */ + public NewFileWizardPage() { + super("NewFileWizardPage"); //$NON-NLS-1$ + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.wizards.NewNodeWizardPage#getPageTitle() + */ + @Override + protected String getPageTitle() { + return Messages.NewFileWizardPage_NewFileWizardPageTitle; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.wizards.NewNodeWizardPage#getPageDescription() + */ + @Override + protected String getPageDescription() { + return Messages.NewFileWizardPage_NewFileWizardPageDescription; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.wizards.NewNodeWizardPage#getNameFieldLabel() + */ + @Override + protected String getNameFieldLabel() { + return Messages.NewFileWizardPage_NewFileWizardPageNameLabel; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/NewFolderWizard.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/NewFolderWizard.java new file mode 100644 index 000000000..84fb4adc9 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/NewFolderWizard.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.wizards; + +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpCreate; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpCreateFolder; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; + +/** + * The wizard to create a new folder in the file system of Target Explorer. + */ +public class NewFolderWizard extends NewNodeWizard { + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.wizards.NewNodeWizard#createWizardPage() + */ + @Override + protected NewNodeWizardPage createWizardPage() { + return new NewFolderWizardPage(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.wizards.NewNodeWizard#getCreateOp(org.eclipse.tcf.te.tcf.filesystem.model.FSTreeNode, java.lang.String, org.eclipse.tcf.te.runtime.interfaces.callback.ICallback) + */ + @Override + protected OpCreate getCreateOp(FSTreeNode folder, String name) { + return new OpCreateFolder(folder, name); + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.wizards.NewNodeWizard#getTitle() + */ + @Override + protected String getTitle() { + return Messages.NewFolderWizard_NewFolderWizardTitle; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/NewFolderWizardPage.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/NewFolderWizardPage.java new file mode 100644 index 000000000..79237ca4b --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/NewFolderWizardPage.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2011, 2012 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.te.tcf.filesystem.ui.internal.wizards; + +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; + +/** + * The wizard page to create a new folder in the file system of Target Explorer. + */ +public class NewFolderWizardPage extends NewNodeWizardPage { + + /** + * Create a wizard page to create a new folder in the specified folder. + */ + public NewFolderWizardPage() { + super("NewFolderWizardPage"); //$NON-NLS-1$ + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.wizards.NewNodeWizardPage#getPageTitle() + */ + @Override + protected String getPageTitle() { + return Messages.NewFolderWizardPage_NewFolderWizardPageTitle; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.wizards.NewNodeWizardPage#getPageDescription() + */ + @Override + protected String getPageDescription() { + return Messages.NewFolderWizardPage_NewFolderWizardPageDescription; + } + + /* + * (non-Javadoc) + * @see org.eclipse.tcf.te.tcf.filesystem.internal.wizards.NewNodeWizardPage#getNameFieldLabel() + */ + @Override + protected String getNameFieldLabel() { + return Messages.NewFolderWizardPage_NewFolderWizardPageNameLabel; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/NewNodeWizard.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/NewNodeWizard.java new file mode 100644 index 000000000..ee743fcae --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/NewNodeWizard.java @@ -0,0 +1,250 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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.te.tcf.filesystem.ui.internal.wizards; + +import java.lang.reflect.InvocationTargetException; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.tcf.protocol.Protocol; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpCreate; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNode; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNodeProperties; +import org.eclipse.tcf.te.ui.views.editor.pages.AbstractTreeViewerExplorerEditorPage; +import org.eclipse.tcf.te.ui.wizards.AbstractWizard; +import org.eclipse.ui.INewWizard; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.forms.editor.FormEditor; +import org.eclipse.ui.forms.editor.IFormPage; +import org.eclipse.ui.navigator.CommonNavigator; + +/** + * The base wizard class to create a new file/folder in the file system of Target Explorer. + */ +public abstract class NewNodeWizard extends AbstractWizard implements INewWizard { + // The folder in which the new node is created. + private FSTreeNode folder; + // The target peer where the new node is created. + private IPeerNode peer; + // The wizard page used to create the new node. + private NewNodeWizardPage newPage; + + /** + * Create an instance. + */ + public NewNodeWizard() { + setNeedsProgressMonitor(true); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.IWorkbenchWizard#init(org.eclipse.ui.IWorkbench, org.eclipse.jface.viewers.IStructuredSelection) + */ + @Override + public void init(IWorkbench workbench, IStructuredSelection selection) { + super.init(workbench, selection); + // Set the window title + setWindowTitle(getTitle()); + if (!selection.isEmpty()) { + Object element = selection.getFirstElement(); + if (element instanceof FSTreeNode) { + folder = (FSTreeNode) element; + if (folder.isFile()) { + // If the selected is a file, then create the node in the parent folder. + folder = folder.getParent(); + } + peer = folder.peerNode; + } + else if (element instanceof IPeerNode) { + if(hasFileSystem((IPeerNode) element)) { + peer = (IPeerNode) element; + } + } + } + } + + /** + * Test if the specified target peer has a file system service. + * + * @param peer The target peer. + * @return true if it has a file system service. + */ + public boolean hasFileSystem(final IPeerNode peer) { + if(Protocol.isDispatchThread()) { + String services = null; + services = peer.getStringProperty(IPeerNodeProperties.PROPERTY_REMOTE_SERVICES); + if (services != null) { + // Lookup each service individually + for (String service : services.split(",")) { //$NON-NLS-1$ + if (service != null && service.trim().equals("FileSystem")) { //$NON-NLS-1$ + return true; + } + } + } + return false; + } + final boolean[] result = new boolean[1]; + Protocol.invokeAndWait(new Runnable(){ + @Override + public void run() { + result[0] = hasFileSystem(peer); + }}); + return result[0]; + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.wizard.Wizard#addPages() + */ + @Override + public void addPages() { + if (peer == null) { + addPage(new TargetSelectionPage()); + } + addPage(newPage = createWizardPage()); + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.wizard.Wizard#performFinish() + */ + @Override + public boolean performFinish() { + if (newPage != null) { + // Save the value so that next time it is used as the default input. + newPage.saveWidgetValues(); + // Get the new name and create the node. + String name = newPage.getNodeName(); + FSTreeNode dest = newPage.getInputDir(); + final OpCreate create = getCreateOp(dest, name); + IRunnableWithProgress runnable = new IRunnableWithProgress() { + @Override + public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { + create.run(monitor); + }}; + try { + getContainer().run(false, false, runnable); + final FSTreeNode newNode = create.getNode(); + getShell().getDisplay().asyncExec(new Runnable(){ + @Override + public void run() { + selectNewNode(newNode); + }}); + return true; + } + catch (InvocationTargetException e) { + newPage.setErrorMessage(e.getMessage()); + } + catch (InterruptedException e) { + } + } + return false; + } + + /** + * Select the specified node in the selection provider. + * + * @param node The node to be selected. + */ + void selectNewNode(FSTreeNode node) { + TreeViewer viewer = getFocusedViewer(); + if(viewer != null) { + viewer.refresh(folder); + ISelection selection = new StructuredSelection(node); + viewer.setSelection(selection, true); + } + } + + /** + * Get currently focused tree viewer. + * + * @return currently focused tree viewer or null. + */ + TreeViewer getFocusedViewer() { + IWorkbenchWindow window = getWorkbench() != null ? getWorkbench().getActiveWorkbenchWindow() : null; + if (window != null) { + IWorkbenchPage page = window.getActivePage(); + if (page != null) { + IWorkbenchPart part = page.getActivePart(); + if (part instanceof FormEditor) { + FormEditor formEditor = (FormEditor) part; + IFormPage formPage = formEditor.getActivePageInstance(); + if (formPage instanceof AbstractTreeViewerExplorerEditorPage) { + AbstractTreeViewerExplorerEditorPage viewerPage = (AbstractTreeViewerExplorerEditorPage) formPage; + return (TreeViewer) viewerPage.getTreeControl().getViewer(); + } + } else if (part instanceof CommonNavigator) { + CommonNavigator navigator = (CommonNavigator) part; + return navigator.getCommonViewer(); + } + } + } + return null; + } + + /** + * Create a wizard page to create a new node. + * + * @return The new wizard page. + */ + protected abstract NewNodeWizardPage createWizardPage(); + + /** + * Create a Create operation instance using the specified folder and the new name. + * + * @param folder The folder in which the new node is created. + * @param name The name of the new node. + * @return a FSCreate instance to do the creation. + */ + protected abstract OpCreate getCreateOp(FSTreeNode folder, String name); + + /** + * The wizard's title to be used. + * + * @return The wizard's title to be used. + */ + protected abstract String getTitle(); + + /** + * Get the current target peer selected. + * + * @return The target peer selected. + */ + public IPeerNode getPeer(){ + return peer; + } + + /** + * Set the currently selected target peer. + * + * @param peer The newly selected target peer. + */ + public void setPeer(IPeerNode peer) { + this.peer = peer; + newPage.setPeer(peer); + } + + /** + * Get the current selected folder. + * + * @return the current selected folder. + */ + public FSTreeNode getFolder() { + return folder; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/NewNodeWizardPage.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/NewNodeWizardPage.java new file mode 100644 index 000000000..7179beddc --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/NewNodeWizardPage.java @@ -0,0 +1,359 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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.te.tcf.filesystem.ui.internal.wizards; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.viewers.DecoratingLabelProvider; +import org.eclipse.jface.viewers.ILabelDecorator; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.jface.wizard.IWizardContainer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.NullOpExecutor; +import org.eclipse.tcf.te.tcf.filesystem.core.internal.operations.OpParsePath; +import org.eclipse.tcf.te.tcf.filesystem.core.model.FSTreeNode; +import org.eclipse.tcf.te.tcf.filesystem.ui.controls.FSTreeContentProvider; +import org.eclipse.tcf.te.tcf.filesystem.ui.controls.FSTreeViewerSorter; +import org.eclipse.tcf.te.tcf.filesystem.ui.help.IContextHelpIds; +import org.eclipse.tcf.te.tcf.filesystem.ui.interfaces.IFSConstants; +import org.eclipse.tcf.te.tcf.filesystem.ui.internal.columns.FSTreeElementLabelProvider; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNode; +import org.eclipse.tcf.te.ui.controls.BaseEditBrowseTextControl; +import org.eclipse.tcf.te.ui.forms.FormLayoutFactory; +import org.eclipse.tcf.te.ui.trees.FilterDescriptor; +import org.eclipse.tcf.te.ui.trees.ViewerStateManager; +import org.eclipse.tcf.te.ui.wizards.pages.AbstractValidatingWizardPage; +import org.eclipse.ui.IDecoratorManager; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.forms.widgets.FormToolkit; + +/** + * The base wizard page class to create a new file/folder in the file system of Target Explorer. + */ +public abstract class NewNodeWizardPage extends AbstractValidatingWizardPage { + // The form toolkit to create the content of the wizard page. + private FormToolkit toolkit; + // The control for the user to enter the new name. + private BaseEditBrowseTextControl nameControl; + // The control for the user to enter the parent directory + private BaseEditBrowseTextControl folderControl; + // The viewer of the file tree displaying the file system. + private TreeViewer treeViewer; + + /** + * Create an instance page with the specified page name. + * + * @param pageName The page name. + */ + public NewNodeWizardPage(String pageName) { + super(pageName); + } + + /** + * Get the page's title. + * + * @return The page's title. + */ + protected abstract String getPageTitle(); + + /** + * Get the page's description. + * + * @return The page's description. + */ + protected abstract String getPageDescription(); + + /** + * Get the label of the text field to enter the new name. + * + * @return The label of the text field to enter the new name. + */ + protected abstract String getNameFieldLabel(); + + /* + * (non-Javadoc) + * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createControl(Composite parent) { + // Setup title and description + setTitle(getPageTitle()); + setDescription(getPageDescription()); + + // Create the forms toolkit + toolkit = new FormToolkit(parent.getDisplay()); + + // Create the main panel + Composite mainPanel = toolkit.createComposite(parent); + mainPanel.setLayout(FormLayoutFactory.createClearGridLayout(false, 1)); + mainPanel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + mainPanel.setBackground(parent.getBackground()); + + setControl(mainPanel); + + // Setup the help + PlatformUI.getWorkbench().getHelpSystem() + .setHelp(mainPanel, IContextHelpIds.FS_NEW_FILE_WIZARD_PAGE); + + // Do not validate the page while creating the controls + boolean changed = setValidationInProgress(true); + // Create the main panel sub controls + createMainPanelControls(mainPanel); + // Reset the validation in progress state + if (changed) setValidationInProgress(false); + + // Adjust the font + Dialog.applyDialogFont(mainPanel); + + // Validate the page for the first time + setPageComplete(false); + } + + /** + * Create the main panel of this wizard page. + * + * @param parent The parent composite in which the page is created. + */ + private void createMainPanelControls(Composite parent) { + Assert.isNotNull(parent); + + // Create the client composite + Composite client = toolkit != null ? toolkit.createComposite(parent) : new Composite(parent, SWT.NONE); + client.setLayout(FormLayoutFactory.createSectionClientGridLayout(false, 2)); + client.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + client.setBackground(parent.getBackground()); + + Label label = new Label(client, SWT.NONE); + GridData data = new GridData(SWT.FILL, SWT.CENTER, true, false); + data.horizontalSpan = 2; + label.setLayoutData(data); + label.setText(Messages.NewNodeWizardPage_PromptFolderLabel); + + folderControl = new BaseEditBrowseTextControl(this); + folderControl.setIsGroup(false); + folderControl.setHasHistory(false); + folderControl.setHideBrowseButton(true); + folderControl.setHideLabelControl(true); + folderControl.setHideEditFieldControlDecoration(true); + folderControl.setFormToolkit(toolkit); + folderControl.setParentControlIsInnerPanel(true); + folderControl.setupPanel(client); + folderControl.setEditFieldValidator(new FolderValidator(this)); + NewNodeWizard wizard = getWizard(); + FSTreeNode folder = wizard.getFolder(); + if (folder != null) folderControl.setEditFieldControlText(folder.getLocation()); + + treeViewer = new TreeViewer(client, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); + data = new GridData(SWT.FILL, SWT.FILL, true, true); + data.horizontalSpan = 2; + data.heightHint = 193; + data.widthHint = 450; + treeViewer.getTree().setLayoutData(data); + treeViewer.setContentProvider(new FSTreeContentProvider()); + treeViewer.setLabelProvider(createDecoratingLabelProvider(new FSTreeElementLabelProvider())); + treeViewer.setComparator(new FSTreeViewerSorter()); + treeViewer.addFilter(new DirectoryFilter()); + IPeerNode peer = wizard.getPeer(); + if (peer != null) { + setInput(peer); + } + treeViewer.addSelectionChangedListener(new ISelectionChangedListener() { + @Override + public void selectionChanged(SelectionChangedEvent event) { + onSelectionChanged(); + } + }); + if (folder != null) treeViewer.setSelection(new StructuredSelection(folder)); + + nameControl = new BaseEditBrowseTextControl(this); + nameControl.setIsGroup(false); + nameControl.setHasHistory(false); + nameControl.setHideBrowseButton(true); + nameControl.setEditFieldLabel(getNameFieldLabel()); + nameControl.setFormToolkit(toolkit); + nameControl.setParentControlIsInnerPanel(true); + nameControl.setupPanel(client); + nameControl.setEditFieldValidator(new NameValidator(this)); + + if (folder == null) folderControl.getEditFieldControl().setFocus(); + else nameControl.getEditFieldControl().setFocus(); + + // restore the widget values from the history + restoreWidgetValues(); + } + + /** + * The viewer filter to filter out files. + */ + static class DirectoryFilter extends ViewerFilter { + @Override + public boolean select(Viewer viewer, Object parentElement, Object element) { + if (element instanceof FSTreeNode) { + FSTreeNode node = (FSTreeNode) element; + if(node.isFile()) return false; + } + return true; + } + } + + /** + * Set the input of the tree viewer and apply the appropriate filters. + * + * @param input The tree viewer's input. + */ + private void setInput(Object input) { + treeViewer.setInput(input); + FilterDescriptor[] filterDescriptors = ViewerStateManager.getInstance().getFilterDescriptors(IFSConstants.ID_TREE_VIEWER_FS, input); + Assert.isNotNull(filterDescriptors); + for (FilterDescriptor descriptor : filterDescriptors) { + if (descriptor.isEnabled()) { + treeViewer.addFilter(descriptor.getFilter()); + } + } + } + + /** + * Create a decorating label provider using the specified label provider. + * + * @param labelProvider The label provider that actually provides labels and images. + * @return The decorating label provider. + */ + private static ILabelProvider createDecoratingLabelProvider(ILabelProvider labelProvider) { + IWorkbench workbench = PlatformUI.getWorkbench(); + IDecoratorManager manager = workbench.getDecoratorManager(); + ILabelDecorator decorator = manager.getLabelDecorator(); + return new DecoratingLabelProvider(labelProvider,decorator); + } + + /** + * Event process handling method when the user select a new folder in the file tree. + */ + protected void onSelectionChanged() { + if (treeViewer.getSelection() instanceof IStructuredSelection) { + IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection(); + if (selection.getFirstElement() instanceof FSTreeNode) { + FSTreeNode folder = (FSTreeNode) selection.getFirstElement(); + folderControl.setEditFieldControlText(folder.getLocation()); + } + else { + folderControl.setEditFieldControlText(""); //$NON-NLS-1$ + } + } + + // Update the wizard container UI elements + IWizardContainer container = getContainer(); + if (container != null && container.getCurrentPage() != null) { + container.updateWindowTitle(); + container.updateTitleBar(); + container.updateButtons(); + } + validate(); + } + + /** + * Set a new peer as the input of the file tree. Called + * by the wizard to update the file tree when an alternative + * target peer is selected in the target selection page. + * + * @param peer The new target peer. + */ + public void setPeer(IPeerNode peer) { + if (peer != null) { + setInput(peer); + } + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.ui.wizards.pages.AbstractValidatingWizardPage#doValidate() + */ + @Override + protected ValidationResult doValidate() { + ValidationResult result = new ValidationResult(); + + boolean valid = true; + + if (folderControl != null) { + valid &= folderControl.isValid(); + result.setResult(folderControl); + } + + if (nameControl != null) { + valid &= nameControl.isValid(); + result.setResult(nameControl); + } + + result.setValid(valid); + + return result; + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.dialogs.DialogPage#dispose() + */ + @Override + public void dispose() { + if (nameControl != null) { nameControl.dispose(); nameControl = null; } + if (toolkit != null) { toolkit.dispose(); toolkit = null; } + super.dispose(); + } + + /** + * Get the entered name of this node. + * + * @return The entered name of this node. + */ + public String getNodeName() { + return nameControl.getEditFieldControlTextForValidation(); + } + + /** + * Get the parent wizard. Override the parent method to + * cast the result to NewNodeWizard. + */ + @Override + public NewNodeWizard getWizard() { + return (NewNodeWizard) super.getWizard(); + } + + /** + * Get the currently input directory node. It parses + * the currently entered path and tries to find the + * corresponding directory node in the file system of + * the target peer. + * + * @return The directory node if it exists or else null. + */ + public FSTreeNode getInputDir() { + NewNodeWizard wizard = getWizard(); + IPeerNode peer = wizard.getPeer(); + if (peer == null) return null; + final String text = folderControl.getEditFieldControlText(); + if (text != null) { + String path = text.trim(); + OpParsePath parser = new OpParsePath(peer, path); + new NullOpExecutor().execute(parser); + return parser.getResult(); + } + return null; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/TargetPatternFilter.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/TargetPatternFilter.java new file mode 100644 index 000000000..82baf5e34 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/TargetPatternFilter.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2005, 2014 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.tcf.te.tcf.filesystem.ui.internal.wizards; + +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNode; +import org.eclipse.tcf.te.ui.views.navigator.DelegatingLabelProvider; +import org.eclipse.ui.dialogs.PatternFilter; + +/** + * A class that handles filtering wizard node items based on a supplied matching + * string and keywords + * <p> + * This class is copied and adapted from <code>org.eclipse.ui.internal.dialogs.WizardPatternFilter</code>. + */ +public class TargetPatternFilter extends PatternFilter { + private DelegatingLabelProvider targetLabelProvider = new DelegatingLabelProvider(); + /** + * Create a new instance of a WizardPatternFilter + * @param isMatchItem + */ + public TargetPatternFilter() { + super(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.internal.dialogs.PatternFilter#isElementSelectable(java.lang.Object) + */ + @Override + public boolean isElementSelectable(Object element) { + return element instanceof IPeerNode; + } + + /* + * (non-Javadoc) + * @see org.eclipse.ui.internal.dialogs.PatternFilter#isElementMatch(org.eclipse.jface.viewers.Viewer, java.lang.Object) + */ + @Override + protected boolean isLeafMatch(Viewer viewer, Object element) { + if ( element instanceof IPeerNode) { + String text = targetLabelProvider.getText(element); + if (wordMatches(text)) { + return true; + } + } + return false; + } +} diff --git a/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/TargetSelectionPage.java b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/TargetSelectionPage.java new file mode 100644 index 000000000..d3b268055 --- /dev/null +++ b/target_explorer/plugins/org.eclipse.tcf.te.filesystem.ui/src/org/eclipse/tcf/te/tcf/filesystem/ui/internal/wizards/TargetSelectionPage.java @@ -0,0 +1,305 @@ +/******************************************************************************* + * Copyright (c) 2011, 2014 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.te.tcf.filesystem.ui.internal.wizards; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.dialogs.IMessageProvider; +import org.eclipse.jface.viewers.DecoratingStyledCellLabelProvider; +import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.IBasicPropertyConstants; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.StyledString; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.jface.wizard.IWizardContainer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.tcf.te.tcf.filesystem.ui.nls.Messages; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerModel; +import org.eclipse.tcf.te.tcf.locator.interfaces.nodes.IPeerNode; +import org.eclipse.tcf.te.tcf.locator.interfaces.services.IPeerModelQueryService; +import org.eclipse.tcf.te.tcf.locator.model.ModelManager; +import org.eclipse.tcf.te.tcf.ui.navigator.ContentProvider; +import org.eclipse.tcf.te.ui.activator.UIPlugin; +import org.eclipse.tcf.te.ui.interfaces.IUIConstants; +import org.eclipse.tcf.te.ui.views.navigator.DelegatingLabelProvider; +import org.eclipse.tcf.te.ui.wizards.pages.AbstractValidatingWizardPage; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.dialogs.FilteredTree; +import org.eclipse.ui.dialogs.PatternFilter; + +/** + * The New Target creation wizard selection page implementation. + * <p> + * This class is copied and adapted from <code>org.eclipse.tcf.te.ui.wizards.newWizard.NewWizardSelectionPage</code>. + * + * @since 3.8 + */ +public class TargetSelectionPage extends AbstractValidatingWizardPage { + // References to the page subcontrol's + private FilteredTree filteredTree; + private PatternFilter filteredTreeFilter; + + // The tree viewer to display the targets. + private TreeViewer treeViewer; + + /** + * Internal class. The wizard viewer comparator is responsible for the sorting in the tree. + * Current implementation is not prioritizing categories. + */ + /* default */static class TargetViewerComparator extends ViewerComparator { + + /* + * (non-Javadoc) + * @see org.eclipse.jface.viewers.ViewerComparator#isSorterProperty(java.lang.Object, + * java.lang.String) + */ + @Override + public boolean isSorterProperty(Object element, String property) { + // The comparator is affected if the label of the elements should change. + return property.equals(IBasicPropertyConstants.P_TEXT); + } + } + + /** + * Constructor. + * + * @param wizardRegistry The new target wizard registry. Must not be <code>null</code>. + */ + public TargetSelectionPage() { + super(TargetSelectionPage.class.getSimpleName()); + setTitle(getDefaultTitle()); + setDescription(getDefaultDescription()); + initialize(); + } + + /** + * Refresh the remote services in target peers. + */ + private void initialize() { + // Refresh the information of remote services. + IPeerModel model = ModelManager.getPeerModel(); + Assert.isNotNull(model); + IPeerNode[] peers = model.getPeerNodes(); + if (peers != null) { + IPeerModelQueryService service = model.getService(IPeerModelQueryService.class); + for (IPeerNode peer : peers) { + service.queryRemoteServices(peer); + } + } + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.wizard.WizardPage#getWizard() + */ + @Override + public NewNodeWizard getWizard() { + return (NewNodeWizard) super.getWizard(); + } + + /** + * Returns the default page title. + * + * @return The default page title. Must be never <code>null</code>. + */ + protected String getDefaultTitle() { + return Messages.TargetSelectionPage_Title; + } + + /** + * Returns the default page description. + * + * @return The default page description. Must be never <code>null</code>. + */ + protected String getDefaultDescription() { + return Messages.TargetSelectionPage_Description; + } + + /** + * A styled label provider for the target selection list. + */ + static class TargetStyledLabelProvider extends DelegatingLabelProvider implements IStyledLabelProvider { + @Override + public StyledString getStyledText(Object element) { + return new StyledString(getText(element)); + } + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) + */ + @Override + public void createControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NONE); + composite.setLayout(new GridLayout()); + composite.setLayoutData(new GridData(GridData.FILL_BOTH)); + + Label label = new Label(composite, SWT.NONE); + label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + label.setText(Messages.TargetSelectionPage_Targets); + label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + filteredTreeFilter = new TargetPatternFilter(); + filteredTree = new FilteredTree(composite, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER, filteredTreeFilter, true); + filteredTree.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); + GridData layoutData = new GridData(GridData.FILL_BOTH); + layoutData.heightHint = 250; + layoutData.widthHint = 450; + filteredTree.setLayoutData(layoutData); + + treeViewer = filteredTree.getViewer(); + treeViewer.setContentProvider(new ContentProvider()); + IBaseLabelProvider labelProvider = new DecoratingStyledCellLabelProvider(new TargetStyledLabelProvider(), new DelegatingLabelProvider(), null); + treeViewer.setLabelProvider(labelProvider); + treeViewer.setComparator(new TargetViewerComparator()); + ViewerFilter fsPeerFilter = new ViewerFilter() { + @Override + public boolean select(Viewer viewer, Object parentElement, Object element) { + if (element instanceof IPeerNode) { + IPeerNode peer = (IPeerNode) element; + + + + NewNodeWizard wizard = getWizard(); + return wizard.hasFileSystem(peer); + } + return false; + } + }; + treeViewer.addFilter(fsPeerFilter); + treeViewer.addSelectionChangedListener(new ISelectionChangedListener() { + @Override + public void selectionChanged(SelectionChangedEvent event) { + onSelectionChanged(); + } + }); + treeViewer.addDoubleClickListener(new IDoubleClickListener() { + @Override + public void doubleClick(DoubleClickEvent event) { + // Double-click on a connection type is triggering the sub wizard + if (event.getSelection() instanceof IStructuredSelection) { + IStructuredSelection selection = (IStructuredSelection) event.getSelection(); + // The tree is single selection, so look for the first element only. + Object element = selection.getFirstElement(); + if (element instanceof IPeerNode) { + // Double-click on a connection type is triggering the sub wizard + getWizard().getContainer().showPage(getNextPage()); + } + else if (event.getViewer() instanceof TreeViewer) { + TreeViewer viewer = (TreeViewer) event.getViewer(); + if (viewer.isExpandable(element)) { + viewer.setExpandedState(element, !viewer.getExpandedState(element)); + } + } + } + } + }); + + treeViewer.setInput(ModelManager.getPeerModel()); + NewNodeWizard wizard = getWizard(); + IPeerNode peer = wizard.getPeer(); + if (wizard.getPeer() != null) { + treeViewer.setSelection(new StructuredSelection(peer), true); + } + + // apply the standard dialog font + Dialog.applyDialogFont(composite); + + setControl(composite); + + // Restore the tree state + restoreWidgetValues(); + + // Initialize the context help id + PlatformUI.getWorkbench().getHelpSystem() + .setHelp(getControl(), IUIConstants.HELP_NEW_WIZARD_SELECTION_PAGE); + + setPageComplete(peer != null); + } + + /* (non-Javadoc) + * @see org.eclipse.tcf.te.ui.wizards.pages.AbstractValidatingWizardPage#doValidate() + */ + @Override + protected ValidationResult doValidate() { + ValidationResult result = new ValidationResult(); + + boolean valid = true; + + ISelection selection = treeViewer.getSelection(); + if (selection.isEmpty()) { + result.setResult(getDefaultDescription(), IMessageProvider.ERROR); + result.setValid(valid); + } + + return result; + } + + /** + * Called from the selection listener to propagate the current system type selection to the + * underlying wizard. + */ + protected void onSelectionChanged() { + if (filteredTree.getViewer().getSelection() instanceof IStructuredSelection) { + IStructuredSelection filteredTreeSelection = (IStructuredSelection) filteredTree + .getViewer().getSelection(); + NewNodeWizard wizard = getWizard(); + if (filteredTreeSelection.getFirstElement() instanceof IPeerNode) { + wizard.setPeer((IPeerNode) filteredTreeSelection.getFirstElement()); + } + else { + wizard.setPeer(null); + } + } + + // Update the wizard container UI elements + IWizardContainer container = getContainer(); + if (container != null && container.getCurrentPage() != null) { + container.updateWindowTitle(); + container.updateTitleBar(); + container.updateButtons(); + } + validate(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.wizard.WizardPage#getDialogSettings() + */ + @Override + protected IDialogSettings getDialogSettings() { + // If the wizard is set and returns dialog settings, we re-use them here + IDialogSettings settings = super.getDialogSettings(); + // If the dialog settings could not set from the wizard, fallback to the plugin's + // dialog settings store. + if (settings == null) settings = UIPlugin.getDefault().getDialogSettings(); + String sectionName = this.getClass().getName(); + if (settings.getSection(sectionName) == null) settings.addNewSection(sectionName); + settings = settings.getSection(sectionName); + + return settings; + } +} |