Browse Source

Implemented SD2-1293 - Creating a DependentUpon file in the Project Browser:

Dragging a file onto another creates a dependency.
Dragging a file onto its parent directory removes a dependency.
Added two items to the file node context menu to add new and existing files as dependent files.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3457 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Christian Hornung 17 years ago
parent
commit
c8de34803e
  1. 10
      AddIns/ICSharpCode.SharpDevelop.addin
  2. BIN
      data/resources/StringResources.de.resources
  3. BIN
      data/resources/StringResources.es-mx.resources
  4. BIN
      data/resources/StringResources.es.resources
  5. 64
      src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/DefaultFileNodeCommands.cs
  6. 29
      src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/FolderNodeCommands.cs
  7. 65
      src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/DirectoryNode.cs
  8. 57
      src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/FileNode.cs
  9. BIN
      src/Main/StartUp/Project/Resources/StringResources.resources

10
AddIns/ICSharpCode.SharpDevelop.addin

@ -404,6 +404,16 @@ @@ -404,6 +404,16 @@
label = "${res:ProjectComponent.ContextMenu.NewFolder}"
icon = "Icons.16x16.NewFolderIcon"
class = "ICSharpCode.SharpDevelop.Project.Commands.AddNewFolderToProject"/>
<MenuItem id = "AddDependentSeparator"
type = "Separator" />
<MenuItem id = "NewDependentItem"
label = "${res:ProjectComponent.ContextMenu.NewDependentItem}"
icon = "ProjectBrowser.CodeBehind"
class = "ICSharpCode.SharpDevelop.Project.Commands.AddNewDependentItemsToProject"/>
<MenuItem id = "ExistingItemAsDependent"
label = "${res:ProjectComponent.ContextMenu.ExistingItemAsDependent}"
icon = "ProjectBrowser.CodeBehind"
class = "ICSharpCode.SharpDevelop.Project.Commands.AddExistingItemsToProjectAsDependent"/>
</MenuItem>
<MenuItem id = "AddSeparator" type = "Separator" />
</Condition>

BIN
data/resources/StringResources.de.resources

Binary file not shown.

BIN
data/resources/StringResources.es-mx.resources

Binary file not shown.

BIN
data/resources/StringResources.es.resources

Binary file not shown.

64
src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/DefaultFileNodeCommands.cs

@ -9,6 +9,7 @@ using System; @@ -9,6 +9,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using ICSharpCode.Core;
@ -272,4 +273,67 @@ namespace ICSharpCode.SharpDevelop.Project.Commands @@ -272,4 +273,67 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
((AbstractProjectBrowserTreeNode)node.Parent).Refresh();
}
}
public class AddNewDependentItemsToProject : AddNewItemsToProject
{
public override void Run()
{
AddDependentItemsToProject(base.AddNewItems);
}
public static void AddDependentItemsToProject(Func<IEnumerable<FileProjectItem>> itemAdder)
{
DirectoryNode dir = ProjectBrowserPad.Instance.ProjectBrowserControl.SelectedDirectoryNode;
if (dir == null) return;
FileNode fileNode = ProjectBrowserPad.Instance.ProjectBrowserControl.SelectedNode as FileNode;
if (fileNode == null) {
LoggingService.Warn("ProjectBrowser: AddNewDependentItemsToProject called on node that is not a FileNode, but: " + fileNode);
return;
}
LoggingService.Debug("ProjectBrowser: AddNewDependentItemsToProject on '" + fileNode.FileName + "'");
// Attention: base.AddNewItems may recreate the subnodes,
// thus invalidating fileNode.
var addedItems = itemAdder();
if (addedItems == null) return;
fileNode = dir.AllNodes.OfType<FileNode>().Single(node => FileUtility.IsEqualFileName(node.FileName, fileNode.FileName));
// Find the file nodes that correspond to the added items which
// do not already have a dependency.
var dict = addedItems
.Where(fpi => String.IsNullOrEmpty(fpi.DependentUpon))
.ToDictionary(
fpi => dir.AllNodes.OfType<FileNode>().Single(
node => node.ProjectItem == fpi
)
);
if (dict.Count == 0) return;
foreach (KeyValuePair<FileNode, FileProjectItem> pair in dict) {
LoggingService.Debug("ProjectBrowser: AddNewDependentItemsToProject: Creating dependency for '" + pair.Value.FileName + "' upon '" + fileNode.FileName + "'");
pair.Value.DependentUpon = Path.GetFileName(fileNode.FileName);
pair.Key.Remove();
pair.Key.FileNodeStatus = FileNodeStatus.BehindFile;
pair.Key.AddTo(fileNode);
}
fileNode.Project.Save();
FileNode primaryAddedNode = dict.Keys.First();
primaryAddedNode.EnsureVisible();
primaryAddedNode.TreeView.SelectedNode = primaryAddedNode;
}
}
public class AddExistingItemsToProjectAsDependent : AddExistingItemsToProject
{
public override void Run()
{
AddNewDependentItemsToProject.AddDependentItemsToProject(base.AddExistingItems);
}
}
}

29
src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/FolderNodeCommands.cs

@ -160,6 +160,11 @@ namespace ICSharpCode.SharpDevelop.Project.Commands @@ -160,6 +160,11 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
}
public override void Run()
{
this.AddExistingItems();
}
protected IEnumerable<FileProjectItem> AddExistingItems()
{
TreeNode selectedNode = ProjectBrowserPad.Instance.ProjectBrowserControl.SelectedNode;
DirectoryNode node = selectedNode as DirectoryNode;
@ -167,11 +172,13 @@ namespace ICSharpCode.SharpDevelop.Project.Commands @@ -167,11 +172,13 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
node = selectedNode.Parent as DirectoryNode;
}
if (node == null) {
return;
return null;
}
node.Expanding();
node.Expand();
List<FileProjectItem> addedItems = new List<FileProjectItem>();
using (OpenFileDialog fdiag = new OpenFileDialog()) {
fdiag.AddExtension = true;
string[] fileFilters = (string[])(AddInTree.GetTreeNode("/SharpDevelop/Workbench/FileFilter").BuildChildItems(this)).ToArray(typeof(string));
@ -219,6 +226,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands @@ -219,6 +226,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
FileProjectItem fileProjectItem = new FileProjectItem(node.Project, node.Project.GetDefaultItemType(fileName), relFileName);
fileProjectItem.SetEvaluatedMetadata("Link", Path.Combine(node.RelativePath, Path.GetFileName(fileName)));
fileProjectItem.DependentUpon = pair.Value;
addedItems.Add(fileProjectItem);
fileNode.ProjectItem = fileProjectItem;
fileNode.AddTo(node);
ProjectService.AddProjectItem(node.Project, fileProjectItem);
@ -226,11 +234,11 @@ namespace ICSharpCode.SharpDevelop.Project.Commands @@ -226,11 +234,11 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
node.Project.Save();
if (addedDependentFiles)
node.RecreateSubNodes();
return;
return addedItems.AsReadOnly();
}
if (res == 2) {
// Cancel
return;
return addedItems.AsReadOnly();
}
// only continue for res==0 (Copy)
}
@ -249,6 +257,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands @@ -249,6 +257,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
}
FileProjectItem item = CopyFile(pair.Key, node, true);
if (item != null) {
addedItems.Add(item);
item.DependentUpon = pair.Value;
}
}
@ -257,6 +266,8 @@ namespace ICSharpCode.SharpDevelop.Project.Commands @@ -257,6 +266,8 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
node.RecreateSubNodes();
}
}
return addedItems.AsReadOnly();
}
}
@ -271,19 +282,27 @@ namespace ICSharpCode.SharpDevelop.Project.Commands @@ -271,19 +282,27 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
public class AddNewItemsToProject : AbstractMenuCommand
{
public override void Run()
{
this.AddNewItems();
}
protected IEnumerable<FileProjectItem> AddNewItems()
{
DirectoryNode node = ProjectBrowserPad.Instance.ProjectBrowserControl.SelectedDirectoryNode;
if (node == null) {
return;
return null;
}
node.Expand();
node.Expanding();
List<FileProjectItem> addedItems = new List<FileProjectItem>();
using (NewFileDialog nfd = new NewFileDialog(node.Directory)) {
if (nfd.ShowDialog(ICSharpCode.SharpDevelop.Gui.WorkbenchSingleton.MainForm) == DialogResult.OK) {
bool additionalProperties = false;
foreach (KeyValuePair<string, FileDescriptionTemplate> createdFile in nfd.CreatedFiles) {
FileProjectItem item = node.AddNewFile(createdFile.Key);
addedItems.Add(item);
if (createdFile.Value.SetProjectItemProperties(item)) {
additionalProperties = true;
@ -295,6 +314,8 @@ namespace ICSharpCode.SharpDevelop.Project.Commands @@ -295,6 +314,8 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
}
}
}
return addedItems.AsReadOnly();
}
}

65
src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/DirectoryNode.cs

@ -615,7 +615,23 @@ namespace ICSharpCode.SharpDevelop.Project @@ -615,7 +615,23 @@ namespace ICSharpCode.SharpDevelop.Project
CopyDirectoryHere(node.Directory, performMove);
}
/// <summary>
/// Copies or moves a file to this directory, discarding its DependentUpon value.
/// </summary>
/// <param name="fileName">The name of the file to copy or move.</param>
/// <param name="performMove">true to move the file, false to copy it.</param>
public void CopyFileHere(string fileName, bool performMove)
{
this.CopyFileHere(fileName, performMove, false);
}
/// <summary>
/// Copies or moves a file to this directory.
/// </summary>
/// <param name="fileName">The name of the file to copy or move.</param>
/// <param name="performMove">true to move the file, false to copy it.</param>
/// <param name="keepDependency">true to copy the DependentUpon value of the file to the target if possible, false to discard the DependentUpon value.</param>
public void CopyFileHere(string fileName, bool performMove, bool keepDependency)
{
string shortFileName = Path.GetFileName(fileName);
string copiedFileName = Path.Combine(Directory, shortFileName);
@ -644,6 +660,11 @@ namespace ICSharpCode.SharpDevelop.Project @@ -644,6 +660,11 @@ namespace ICSharpCode.SharpDevelop.Project
continue;
if (newItem != null && FileUtility.IsEqualFileName(fileItem.FileName, fileName)) {
fileItem.CopyMetadataTo(newItem);
if (!keepDependency) {
// Prevent the DependentUpon from being copied
// because the referenced file is now in a different directory.
newItem.DependentUpon = String.Empty;
}
}
if (!string.Equals(fileItem.DependentUpon, shortFileName, StringComparison.OrdinalIgnoreCase))
continue;
@ -651,7 +672,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -651,7 +672,7 @@ namespace ICSharpCode.SharpDevelop.Project
if (!FileUtility.IsEqualFileName(sourceDirectory, Path.GetDirectoryName(itemPath)))
continue;
// this file is dependend on the file being copied/moved: copy it, too
CopyFileHere(itemPath, performMove);
CopyFileHere(itemPath, performMove, true);
dependendElementsCopied = true;
}
if (dependendElementsCopied)
@ -672,6 +693,12 @@ namespace ICSharpCode.SharpDevelop.Project @@ -672,6 +693,12 @@ namespace ICSharpCode.SharpDevelop.Project
}
}
/// <summary>
/// Copies or moves a file node (and the corresponding file, if applicable) to this directory,
/// discarding its DependentUpon value.
/// </summary>
/// <param name="fileNode">The file node to copy or move.</param>
/// <param name="performMove">true to move the file node, false to copy it.</param>
public void CopyFileHere(FileNode node, bool performMove)
{
if (node.FileNodeStatus == FileNodeStatus.None) {
@ -743,6 +770,13 @@ namespace ICSharpCode.SharpDevelop.Project @@ -743,6 +770,13 @@ namespace ICSharpCode.SharpDevelop.Project
return DragDropEffects.Copy;
}
return proposedEffect;
} else {
// Dragging a dependent file onto its parent directory
// removes the dependency.
FileProjectItem fpi = fileNode.ProjectItem as FileProjectItem;
if (fpi != null && !String.IsNullOrEmpty(fpi.DependentUpon)) {
return DragDropEffects.Move;
}
}
}
@ -771,7 +805,24 @@ namespace ICSharpCode.SharpDevelop.Project @@ -771,7 +805,24 @@ namespace ICSharpCode.SharpDevelop.Project
try {
if (dataObject.GetDataPresent(typeof(FileNode))) {
FileNode fileNode = (FileNode)dataObject.GetData(typeof(FileNode));
CopyFileHere(fileNode, effect == DragDropEffects.Move);
LoggingService.Debug("ProjectBrowser: Dragging file '" + fileNode.FileName + "' onto directory '" + this.Directory + "'");
if (!FileUtility.IsEqualFileName(Directory, fileNode.FileName) && !FileUtility.IsEqualFileName(Directory, Path.GetDirectoryName(fileNode.FileName))
&& !(fileNode.ProjectItem is FileProjectItem && FileUtility.IsEqualFileName(Directory, Path.GetDirectoryName(GetFullVirtualName((FileProjectItem)fileNode.ProjectItem))))) {
LoggingService.Debug("-> Not in same directory, performing " + effect.ToString());
CopyFileHere(fileNode, effect == DragDropEffects.Move);
} else {
// Dragging a dependent file onto its parent directory
// removes the dependency.
LoggingService.Debug("-> In same directory, removing dependency");
((FileProjectItem)fileNode.ProjectItem).DependentUpon = String.Empty;
fileNode.Remove();
if (!File.Exists(fileNode.FileName)) {
fileNode.FileNodeStatus = FileNodeStatus.Missing;
} else {
fileNode.FileNodeStatus = FileNodeStatus.InProject;
}
fileNode.AddTo(this);
}
} else if (dataObject.GetDataPresent(typeof(DirectoryNode))) {
DirectoryNode directoryNode = (DirectoryNode)dataObject.GetData(typeof(DirectoryNode));
CopyDirectoryHere(directoryNode, effect == DragDropEffects.Move);
@ -793,6 +844,16 @@ namespace ICSharpCode.SharpDevelop.Project @@ -793,6 +844,16 @@ namespace ICSharpCode.SharpDevelop.Project
MessageService.ShowError(e);
}
}
static string GetFullVirtualName(FileProjectItem item)
{
if (Path.IsPathRooted(item.VirtualName)) {
return item.VirtualName;
} else if (item.Project != null) {
return Path.Combine(item.Project.Directory, item.VirtualName);
}
return item.VirtualName;
}
#endregion
}
}

57
src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/FileNode.cs

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
using System;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using ICSharpCode.Core;
@ -183,11 +184,67 @@ namespace ICSharpCode.SharpDevelop.Project @@ -183,11 +184,67 @@ namespace ICSharpCode.SharpDevelop.Project
public override DragDropEffects GetDragDropEffect(IDataObject dataObject, DragDropEffects proposedEffect)
{
if (dataObject.GetDataPresent(typeof(FileNode))) {
// Dragging a file onto another creates a dependency.
// If we are in the same directory, allow moving only.
if (this.Project.ReadOnly)
return DragDropEffects.None;
FileNode other = (FileNode)dataObject.GetData(typeof(FileNode));
if (other == this || !(other.ProjectItem is FileProjectItem) || !(this.ProjectItem is FileProjectItem))
return DragDropEffects.None;
if (FileUtility.IsEqualFileName(Path.GetDirectoryName(this.FileName), Path.GetDirectoryName(other.FileName))) {
return DragDropEffects.Move;
} else {
return proposedEffect;
}
}
return ((ExtTreeNode)Parent).GetDragDropEffect(dataObject, proposedEffect);
}
public override void DoDragDrop(IDataObject dataObject, DragDropEffects effect)
{
if (dataObject.GetDataPresent(typeof(FileNode))) {
// Dragging a file onto another creates a dependency.
FileNode other = (FileNode)dataObject.GetData(typeof(FileNode));
LoggingService.Debug("ProjectBrowser: Dragging file '" + other.FileName + "' onto file '" + this.FileName + "'");
// Copy/move the file to the correct directory
// if the target is in a different directory than the source.
if (!FileUtility.IsEqualFileName(Path.GetDirectoryName(this.FileName), Path.GetDirectoryName(other.FileName))) {
LoggingService.Debug("-> Source file is in different directory, performing " + effect.ToString());
ExtTreeNode p = this;
DirectoryNode parentDirectory;
do {
p = (ExtTreeNode)p.Parent;
parentDirectory = p as DirectoryNode;
} while (parentDirectory == null && p != null);
if (parentDirectory == null) {
throw new InvalidOperationException("File '" + this.FileName + "' does not have a parent directory.");
}
LoggingService.Debug("-> Copying/Moving source file to parent directory of target: " + parentDirectory.Directory);
string otherFileName = Path.GetFileName(other.FileName);
parentDirectory.CopyFileHere(other, effect == DragDropEffects.Move);
// Find the copied or moved file node again
other = parentDirectory.AllNodes.OfType<FileNode>().SingleOrDefault(n => FileUtility.IsEqualFileName(Path.GetFileName(n.FileName), otherFileName));
}
if (other != null) {
other.Remove();
((FileProjectItem)other.ProjectItem).DependentUpon = Path.GetFileName(this.FileName);
other.FileNodeStatus = FileNodeStatus.BehindFile;
other.AddTo(this);
LoggingService.Debug("-> Created new dependency, saving solution");
ProjectService.SaveSolution();
} else {
LoggingService.Debug("-> Could not find the copied or moved file node in the new parent directory.");
}
return;
}
((ExtTreeNode)Parent).DoDragDrop(dataObject, effect);
}
#endregion

BIN
src/Main/StartUp/Project/Resources/StringResources.resources

Binary file not shown.
Loading…
Cancel
Save