#develop (short for SharpDevelop) is a free IDE for .NET programming languages.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

400 lines
12 KiB

// SharpDevelop samples
// Copyright (c) 2007, AlphaSierraPapa
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice, this list
// of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// - Neither the name of the SharpDevelop team nor the names of its contributors may be used to
// endorse or promote products derived from this software without specific prior written
// permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &AS IS& AND ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.Core.WinForms;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.NAnt.Gui
{
/// <summary>
/// NAnt pad's tree view. Shows a high level view of build file in
/// a set of projects.
/// </summary>
public class NAntPadTreeView : System.Windows.Forms.UserControl, IOwnerState
{
private System.Windows.Forms.TreeView treeView;
const string ContextMenuAddInTreePath = "/SharpDevelop/Pads/NAntPad/ContextMenu";
/// <summary>
/// The possible states of the tree view.
/// </summary>
public enum NAntPadTreeViewState {
Nothing = 0,
BuildFileSelected = 1,
TargetSelected = 2,
ErrorSelected = 4
}
/// <summary>
/// The current state of the tree view.
/// </summary>
NAntPadTreeViewState state = NAntPadTreeViewState.Nothing;
delegate void AddSolutionInvoker(Solution solution);
public NAntPadTreeView()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
treeView.Sorted = true;
treeView.HideSelection = false;
treeView.ImageList = NAntPadTreeViewImageList.GetImageList();
treeView.ContextMenuStrip = MenuService.CreateContextMenu(this, ContextMenuAddInTreePath);
treeView.DoubleClick += new EventHandler(TreeViewDoubleClick);
}
/// <summary>
/// Gets the "ownerstate" condition.
/// </summary>
public Enum InternalState {
get {
return state;
}
}
/// <summary>
/// Clears all items from the tree view.
/// </summary>
public void Clear()
{
if (InvokeRequired) {
MethodInvoker invoker = new MethodInvoker(Clear);
Invoke(invoker);
} else {
treeView.Nodes.Clear();
}
}
/// <summary>
/// Adds items to the tree view for each build file that exists
/// in all the solution's subprojects.
/// </summary>
/// <param name="solution">A solution containing projects.</param>
public void AddSolution(Solution solution)
{
if (InvokeRequired) {
AddSolutionInvoker invoker = new AddSolutionInvoker(AddSolution);
Invoke(invoker);
} else {
foreach (IProject project in solution.Projects) {
AddProject(project);
}
}
}
/// <summary>
/// Adds items to the tree view for each build file that exist
/// in a project.
/// </summary>
/// <param name="project">A SharpDevelop project.</param>
public void AddProject(IProject project)
{
Debug.Assert(!InvokeRequired, "AddProject InvokeRequired");
foreach (ProjectItem projectItem in project.Items) {
if (NAntBuildFile.IsBuildFile(projectItem.FileName)) {
AddBuildFile(project.Name, projectItem.FileName);
}
}
}
/// <summary>
/// Removes the specified build file from the
/// tree view.</summary>
public void RemoveBuildFile(string fileName)
{
Debug.Assert(!InvokeRequired, "RemoveBuildFile InvokeRequired");
NAntBuildFileTreeNode node = FindMatchingNode(fileName);
if (node != null) {
node.Remove();
}
}
/// <summary>
/// Renames the build file.
/// </summary>
/// <param name="oldFileName">The filename to update.</param>
/// <param name="newFileName">The updated filename.</param>
public void RenameBuildFile(string oldFileName, string newFileName)
{
Debug.Assert(!InvokeRequired, "RenameBuildFile InvokeRequired");
NAntBuildFileTreeNode node = FindMatchingNode(oldFileName);
if (node != null) {
node.FileName = Path.GetFileName(newFileName);
}
}
/// <summary>
/// Updates the build file in the tree view.
/// </summary>
/// <param name="fileName">The build file name.</param>
public void UpdateBuildFile(string fileName)
{
Debug.Assert(!InvokeRequired, "UpdateBuildFile InvokeRequired");
NAntBuildFileTreeNode node = FindMatchingNode(fileName);
if (node != null) {
NAntBuildFile buildFile = new NAntBuildFile(fileName);
node.BuildFile = buildFile;
} else {
AddBuildFile(String.Empty, fileName);
}
}
/// <summary>
/// Adds a build file to the tree.
/// </summary>
/// <param name="projectName">The name of the project.</param>
/// <param name="fileName">The build file name.</param>
/// <param name="debug"><see langword="true"/> if the project's
/// active configuration is debug; <see langword="false"/>
/// otherwise.</param>
public void AddBuildFile(string projectName, string fileName)
{
Debug.Assert(!InvokeRequired, "AddBuildFile InvokeRequired");
if (File.Exists(fileName)) {
NAntBuildFile buildFile = new NAntBuildFile(fileName);
NAntBuildFileTreeNode node = new NAntBuildFileTreeNode(projectName, buildFile);
treeView.Nodes.Add(node);
}
}
/// <summary>
/// Gets the currently selected <see cref="NAntBuildFile"/>.
/// </summary>
/// <remarks>This will return a NAntBuildFile if
/// a target node is selected.</remarks>
public NAntBuildFile SelectedBuildFile {
get {
NAntBuildFile buildFile = null;
TreeNode selectedNode = treeView.SelectedNode;
if (selectedNode is NAntBuildFileTreeNode) {
NAntBuildFileTreeNode buildNode = (NAntBuildFileTreeNode)selectedNode;
buildFile = buildNode.BuildFile;
} else if(selectedNode is NAntBuildTargetTreeNode) {
NAntBuildTargetTreeNode targetNode = (NAntBuildTargetTreeNode)selectedNode;
NAntBuildFileTreeNode buildNode = (NAntBuildFileTreeNode)targetNode.Parent;
buildFile = buildNode.BuildFile;
} else if(selectedNode is NAntBuildFileErrorTreeNode) {
NAntBuildFileErrorTreeNode errorNode = (NAntBuildFileErrorTreeNode)selectedNode;
NAntBuildFileTreeNode buildNode = (NAntBuildFileTreeNode)errorNode.Parent;
buildFile = buildNode.BuildFile;
}
return buildFile;
}
}
/// <summary>
/// Gets the current selected <see cref="NAntBuildTarget"/>
/// </summary>
public NAntBuildTarget SelectedTarget {
get {
NAntBuildTarget target = null;
NAntBuildTargetTreeNode targetNode = treeView.SelectedNode as NAntBuildTargetTreeNode;
if (targetNode != null) {
target = targetNode.Target;
}
return target;
}
}
/// <summary>
/// Gets the current selected <see cref="NAntBuildFileError"/>
/// </summary>
public NAntBuildFileError SelectedError {
get {
NAntBuildFileError error = null;
NAntBuildFileErrorTreeNode errorNode = treeView.SelectedNode as NAntBuildFileErrorTreeNode;
if (errorNode != null) {
error = errorNode.Error;
}
return error;
}
}
/// <summary>
/// Gets whether a target is selected.
/// </summary>
public bool IsTargetSelected {
get {
bool isSelected = false;
if (SelectedTarget != null) {
isSelected = true;
}
return isSelected;
}
}
#region Windows Forms Designer generated code
/// <summary>
/// This method is required for Windows Forms designer support.
/// Do not change the method contents inside the source code editor. The Forms designer might
/// not be able to load this method if it was changed manually.
/// </summary>
private void InitializeComponent() {
this.treeView = new System.Windows.Forms.TreeView();
this.SuspendLayout();
//
// treeView
//
this.treeView.Dock = System.Windows.Forms.DockStyle.Fill;
this.treeView.ImageIndex = -1;
this.treeView.Location = new System.Drawing.Point(0, 0);
this.treeView.Name = "treeView";
this.treeView.SelectedImageIndex = -1;
this.treeView.Size = new System.Drawing.Size(292, 266);
this.treeView.TabIndex = 0;
this.treeView.MouseDown += new System.Windows.Forms.MouseEventHandler(this.TreeViewMouseDown);
//
// NAntPadTreeView
//
this.Controls.Add(this.treeView);
this.Name = "NAntPadTreeView";
this.Size = new System.Drawing.Size(292, 266);
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// User clicked the tree view.
/// </summary>
/// <param name="sender">The event source.</param>
/// <param name="e">The event arguments.</param>
void TreeViewMouseDown(object sender, MouseEventArgs e)
{
TreeNode node = treeView.GetNodeAt(e.X, e.Y);
treeView.SelectedNode = node;
state = NAntPadTreeViewState.Nothing;
if (IsBuildFileNodeSelected) {
state = NAntPadTreeViewState.BuildFileSelected;
}
if (IsBuildTargetNodeSelected) {
state = NAntPadTreeViewState.TargetSelected;
}
if (IsBuildFileErrorNodeSelected) {
state = NAntPadTreeViewState.ErrorSelected;
}
}
/// <summary>
/// Gets whether a build file is selected.
/// </summary>
bool IsBuildFileNodeSelected {
get {
return treeView.SelectedNode is NAntBuildFileTreeNode;
}
}
/// <summary>
/// Gets whether a target is selected.
/// </summary>
bool IsBuildTargetNodeSelected {
get {
return treeView.SelectedNode is NAntBuildTargetTreeNode;
}
}
/// <summary>
/// Gets whether a build file error is selected.
/// </summary>
bool IsBuildFileErrorNodeSelected {
get {
return treeView.SelectedNode is NAntBuildFileErrorTreeNode;
}
}
/// <summary>
/// Double clicking a node on the tree view opens the corresponding
/// file.
/// </summary>
/// <param name="sender">The event source.</param>
/// <param name="e">The event arguments.</param>
void TreeViewDoubleClick(object sender, EventArgs e)
{
NAntBuildFile buildFile = SelectedBuildFile;
if (buildFile != null) {
string fileName = Path.Combine(buildFile.Directory, buildFile.FileName);
if (IsBuildTargetNodeSelected) {
FileService.JumpToFilePosition(fileName, SelectedTarget.Line, SelectedTarget.Column);
} else if (IsBuildFileErrorNodeSelected) {
FileService.JumpToFilePosition(fileName, SelectedError.Line, SelectedError.Column);
} else {
FileService.OpenFile(fileName);
}
}
}
/// <summary>
/// Looks for the tree node that is displaying the specified
/// build file.
/// </summary>
/// <param name="fileName">The build file to look for.</param>
/// <returns>The matching tree node if the build file exists
/// in the tree; otherwise <see langword="null"/>.</returns>
NAntBuildFileTreeNode FindMatchingNode(string fileName)
{
foreach (NAntBuildFileTreeNode node in treeView.Nodes) {
string nodeFileName = Path.Combine(node.BuildFile.Directory, node.BuildFile.FileName);
if (String.Compare(Path.GetFullPath(fileName), Path.GetFullPath(nodeFileName), true) == 0) {
return node;
}
}
return null;
}
}
}