⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lithiumcontrol.cs

📁 英语句子自然语言处理统计分析例子 Statistical parsing of English sentences Shows how to generate parse trees for
💻 CS
📖 第 1 页 / 共 3 页
字号:
using System;
using System.Diagnostics;
using System.Xml;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using System.IO;
using System.Collections;
namespace Netron.Lithium
{
	/// <summary>
	/// Netron's 'Lithium'  tree control
	/// </summary>
	public class LithiumControl : ScrollableControl
	{
		#region Events
	

		/// <summary>
		/// notifies the host to show the properties usually in the property grid
		/// </summary>
		public event ShowProps OnShowProps;

		/// <summary>
		/// occurs when a new node is added to the diagram
		/// </summary>
		public event ShapeData OnNewNode;

		/// <summary>
		/// occurs when certain objects send info out
		/// </summary>
		public event Messager OnInfo;

		/// <summary>
		/// occurs when a shape is deleted
		/// </summary>
		public event ShapeData OnDeleteNode;

		#endregion

		#region Fields

		/// <summary>
		/// the current layout direction
		/// </summary>
		protected TreeDirection layoutDirection = TreeDirection.Vertical;

		/// <summary>
		/// the space between the nodes
		/// </summary>
		protected int wordSpacing = 20;

		/// <summary>
		/// the height between branches
		/// </summary>
		protected int branchHeight = 60;

		/// <summary>
		/// whether the tree layout algorithm will do its work by default
		/// </summary>
		protected bool layoutEnabled = true;
		/// <summary>
		/// the default name when the root is added
		/// </summary>
		protected readonly string defaultRootName = "Root";
		/// <summary>
		/// the abstract representation of the graph
		/// </summary>
		protected internal GraphAbstract graphAbstract;		
		/// <summary>
		/// the entity hovered by the mouse
		/// </summary>
		protected Entity hoveredEntity;
		/// <summary>
		/// the unique entity currently selected
		/// </summary>
		protected Entity selectedEntity;
		/// <summary>
		/// whether we are tracking, i.e. moving something around
		/// </summary>
		protected bool tracking = false;
		/// <summary>
		/// just a reference point for the OnMouseDown event
		/// </summary>
		protected Point refp;
		/// <summary>
		/// the context menu of the control
		/// </summary>
		protected ContextMenu menu;
		/// <summary>
		/// A simple, general purpose random generator
		/// </summary>
		protected Random rnd;
		/// <summary>
		/// simple proxy for the propsgrid of the control
		/// </summary>
		protected Proxy proxy;
		/// <summary>
		/// whether the diagram is moved globally
		/// </summary>
		protected bool globalMove = false;

		/// <summary>
		/// just the default gridsize used in the paint-background method
		/// </summary>
		protected Size gridSize = new Size(10,10);

		/// <summary>
		/// the new but volatile connection
		/// </summary>
		protected internal Connection neoCon = null;

		/// <summary>
		/// memory of a connection if the volatile does not end up to a solid connection
		/// </summary>
		protected ShapeBase memChild = null, memParent = null;

		/// <summary>
		/// the type of connection
		/// </summary>
		protected ConnectionType connectionType = ConnectionType.Default;

		#endregion

		#region Properties
		
		/// <summary>
		/// Gets or sets the type of connection drawn
		/// </summary>
		public ConnectionType ConnectionType
		{
			get{return connectionType;}
			set{connectionType = value;
			Invalidate();
			}
		}

		/// <summary>
		/// Gets or sets the direction the tree-layout expands the tree
		/// </summary>
		public TreeDirection LayoutDirection
		{
			get{return layoutDirection;}
			set{layoutDirection = value;
			//update in case it has changed
				switch(value)
				{
					case TreeDirection.Horizontal:
						branchHeight = 120;
						wordSpacing = 20;
						break;
					case TreeDirection.Vertical:
						branchHeight = 70;
						wordSpacing = 20;
						break;

				}
				DrawTree();
			}
		}
		/// <summary>
		/// Gets or sets whether the tree layout algorithm will do its work by default
		/// </summary>
		public bool LayoutEnabled
		{
			get{return layoutEnabled ;}
			set{
				layoutEnabled = value;
				if(value) //if set to true, let's rectify what eventually has been distorted by the user
					DrawTree();
			}
		}

		/// <summary>
		/// Gets or sets the shape collection
		/// </summary>
		[Browsable(false)]
		public ShapeCollection Shapes
		{
			get{return graphAbstract.Shapes;}
			set{graphAbstract.Shapes = value;}
		}
		/// <summary>
		/// Gets or sets the connection collection
		/// </summary>
		[Browsable(false)]
		public ConnectionCollection Connections
		{
			get{return graphAbstract.Connections;}
			set{graphAbstract.Connections = value;}
		}
	
		/// <summary>
		/// Gets the root of the diagram
		/// </summary>
		[Browsable(false)]
		public ShapeBase Root
		{
			get{return graphAbstract.Root;}
		}

		/// <summary>
		/// Gets or sets the height between the tree branches
		/// </summary>
		[Browsable(true)]
		public int BranchHeight
		{
			get{return branchHeight;}
			set{
				branchHeight = value;
				DrawTree();
			}
		}
		/// <summary>
		/// Gets or sets the spacing between the nodes
		/// </summary>
		[Browsable(true)]
		public int WordSpacing
		{
			get{return wordSpacing;}
			set
			{
				wordSpacing = value;
				DrawTree();
			}
		}


		#endregion

		#region Constructor
		/// <summary>
		/// Default ctor
		/// </summary>
		public LithiumControl()
		{
			//double-buffering
			SetStyle(ControlStyles.AllPaintingInWmPaint, true);
			SetStyle(ControlStyles.DoubleBuffer, true);
			SetStyle(ControlStyles.UserPaint, true);
			SetStyle(ControlStyles.ResizeRedraw, true);

			//init the abstract
			graphAbstract = new GraphAbstract();			
			graphAbstract.Shapes.OnShapeAdded+=new ShapeData(OnShapeAdded);

			AddRoot(defaultRootName);

			//default menu, can be overwritten in the design of the application
			menu = new ContextMenu();
			BuildMenu();
			this.ContextMenu = menu;

			//init the randomizer
			rnd = new Random();

			//init the proxy
			proxy = new Proxy(this);

			//allow scrolling
			this.AutoScroll=true;						this.HScroll=true;			this.VScroll=true;
		}

		#endregion

		#region Methods

		private void visitor_OnDelete(ShapeBase shape)
		{
			if(OnDeleteNode!=null)
				OnDeleteNode(shape);
		}
		/// <summary>
		/// Passes the event from the abstracts shape collection to the outside.
		/// Having the event in the GraphAbstract being raised centralizes it,
		/// otherwise the event should be raise in various places
		/// </summary>
		/// <param name="shape"></param>
		private void OnShapeAdded(ShapeBase shape)
		{
			if(this.OnNewNode!=null)
				OnNewNode(shape);
		}

		/// <summary>
		/// Builds the context menu
		/// </summary>
		private void BuildMenu()
		{
			MenuItem mnuDelete = new MenuItem("Delete",new EventHandler(OnDelete));
			menu.MenuItems.Add(mnuDelete);
			
			MenuItem mnuProps = new MenuItem("Properties", new EventHandler(OnProps));
			menu.MenuItems.Add(mnuProps);

			MenuItem mnuDash = new MenuItem("-");
			menu.MenuItems.Add(mnuDash);			

			MenuItem mnuShapes = new MenuItem("Change to");
			menu.MenuItems.Add(mnuShapes);

			MenuItem mnuRecShape = new MenuItem("Rectangular shape", new EventHandler(OnRecShape));
			mnuShapes.MenuItems.Add(mnuRecShape);
			
			MenuItem mnuOvalShape = new MenuItem("Oval shape", new EventHandler(OnOvalShape));
			mnuShapes.MenuItems.Add(mnuOvalShape);

			MenuItem mnuDash2 = new MenuItem("-");
			menu.MenuItems.Add(mnuDash2);

			MenuItem mnuTLShape = new MenuItem("Add Text label", new EventHandler(OnTextLabelShape));
			menu.MenuItems.Add(mnuTLShape);


			
		}


		#region Menu handlers
		/// <summary>
		/// Deletes the currently selected object from the canvas
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void OnDelete(object sender, EventArgs e)
		{
			if(selectedEntity!=null)
			{
				if(typeof(ShapeBase).IsInstanceOfType(selectedEntity))
				{
					this.Shapes.Remove(selectedEntity as ShapeBase);
					this.Invalidate();
				}
				else
					if(typeof(Connection).IsInstanceOfType(selectedEntity))
				{
					this.Connections.Remove(selectedEntity as Connection);
					this.Invalidate();
				}

			}
		}


		/// <summary>
		/// Asks the host to show the props
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void OnProps(object sender, EventArgs e)
		{
			object thing;
			if(this.selectedEntity==null) 
				thing = this.proxy;
			else
				thing =selectedEntity;
			if(this.OnShowProps!=null)
				OnShowProps(thing);

		}

		
		private void OnRecShape(object sender, EventArgs e)
		{
			throw new NotImplementedException("Sorry, not implemented yet");
		}
		private void OnOvalShape(object sender, EventArgs e)
		{
			throw new NotImplementedException("Sorry, not implemented yet");
		}
		private void OnTextLabelShape(object sender, EventArgs e)
		{
			AddShape(ShapeTypes.TextLabel,refp);
		}
	
		#endregion

		/// <summary>
		/// Paints the control
		/// </summary>
		/// <remarks>
		/// If you switch the painting order of Connections and shapes the connection line
		/// will be underneath/above the shape
		/// </remarks>
		/// <param name="e"></param>
		protected override void OnPaint(PaintEventArgs e)
		{
			Graphics g = e.Graphics;
			//use the best quality, with a performance penalty
			g.SmoothingMode= System.Drawing.Drawing2D.SmoothingMode.AntiAlias;		

			int scrollPositionX = this.AutoScrollPosition.X;
			int scrollPositionY = this.AutoScrollPosition.Y;
			g.TranslateTransform(scrollPositionX, scrollPositionY);

			//zoom
			//g.ScaleTransform(0.1f,0.1f);

			//draw the Connections
			for(int k=0; k<Connections.Count; k++)
			{
				Connections[k].Paint(g);				
			}
			if(neoCon!=null) neoCon.Paint(g);
			//loop over the shapes and draw
			for(int k=0; k<Shapes.Count; k++)
			{
				if(Shapes[k].visible)
					Shapes[k].Paint(g);
			}
			
			
		}
		/// <summary>
		/// Paints the background
		/// </summary>
		/// <param name="e"></param>
		protected override void OnPaintBackground(PaintEventArgs e)
		{
			base.OnPaintBackground (e);
//			Graphics g = e.Graphics;
//
//			g.DrawString("Lithium Tree Layout Control [version " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString() + "]",Font,Brushes.SlateGray,new Point(20,10));
//			g.DrawString("<Shift>: move the diagram",Font,Brushes.SlateGray,new Point(20,30));
//			g.DrawString("<Ctrl>: move a node to a new parent",Font,Brushes.SlateGray,new Point(20,40));
//			g.DrawString("<Alt>: add a new child node",Font,Brushes.SlateGray,new Point(20,50));
		}
		

		#region Add random node
		/// <summary>
		/// Adds a random node 
		/// </summary>
		public void AddRandomNode()
		{
			AddRandomNode("Random");
		}		

		/// <summary>
		/// Adds a random node to the diagram
		/// </summary>
		/// <param name="newName">the text of the newly added shape</param>
		public void AddRandomNode(string newName)
		{
			//Random rnd = new Random();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -