Click here to Skip to main content
15,860,972 members
Articles / Programming Languages / C#

CodeDom Assistant

Rate me:
Please Sign up or sign in to vote.
4.84/5 (26 votes)
21 Sep 20074 min read 136.5K   6.6K   82  
Generating CodeDom Code By Parsing C# or VB
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;

namespace ScintillaNet
{
	[TypeConverterAttribute(typeof(System.ComponentModel.ExpandableObjectConverter))]
	public class DropMarkers : ScintillaHelperBase
	{
		internal DropMarkers(Scintilla scintilla) : base(scintilla) { }

		private Stack<DropMarker> _markerStack = new Stack<DropMarker>();
		private static Dictionary<string, Stack<DropMarker>> _sharedStack = new Dictionary<string, Stack<DropMarker>>();

		internal bool ShouldSerialize()
		{
			return ShouldSerializeSharedStackName();
		}

		#region SharedStackName
		private string _sharedStackName = string.Empty;
		public string SharedStackName
		{
			get
			{
				return _sharedStackName;
			}
			set
			{
				if (value == null)
					value = string.Empty;

				if (_sharedStackName == value)
					return;

				
				if (value == string.Empty)
				{
					//	If we had a shared stack name but are now clearing it
					//	we need to create our own private DropMarkerStack again
					_markerStack = new Stack<DropMarker>();

					//	If this was the last subscriber of a shared stack
					//	remove the name to free up resources
					if (_sharedStack.ContainsKey(_sharedStackName) && _sharedStack[_sharedStackName].Count == 1)
						_sharedStack.Remove(_sharedStackName);
				}
				else
				{
					//	We're using one of the shared stacks. Of course if it hasn't 
					//	already been registered with the list we need to create it.
					if (!_sharedStack.ContainsKey(_sharedStackName))
						_sharedStack[_sharedStackName] = new Stack<DropMarker>();

					_markerStack = _sharedStack[_sharedStackName];
				}

				_sharedStackName = value;
			}
		}

		private bool ShouldSerializeSharedStackName()
		{
			return _sharedStackName != string.Empty;
		}

		private void ResetSharedStackName()
		{
			_sharedStackName = string.Empty;
		} 
		#endregion

		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public Stack<DropMarker> MarkerStack
		{
			get
			{
				return _markerStack;
			}

			//	That's right kids you can actually provide your own MarkerStack. This
			//	is really useful for MDI applications where you want a single master
			//	MarkerStack that will automatically switch documents (a la CodeRush).
			//	Of course you can let the control do this for you automatically by 
			//	setting the SharedStackName property of multiple instances.
			set
            {
            	_markerStack = value;
            }
		}

		private DropMarkerList _allDocumentDropMarkers = new DropMarkerList();
		[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public DropMarkerList AllDocumentDropMarkers
		{
			get
			{
				return _allDocumentDropMarkers;
			}
			set
			{
				_allDocumentDropMarkers = value;
			}
		}

		public DropMarker Drop()
		{
			return Drop(NativeScintilla.GetCurrentPos());
		}

		public DropMarker Drop(int position)
		{
			DropMarker dm = new DropMarker(position, position, getCurrentTopOffset(), Scintilla);
			_allDocumentDropMarkers.Add(dm);
			_markerStack.Push(dm);
			Scintilla.ManagedRanges.Add(dm);

			//	Force the Drop Marker to paint
			Scintilla.Invalidate(dm.GetClientRectangle());
			return dm;
		}

		public void Collect()
		{
			while (_markerStack.Count > 0)
			{
				DropMarker dm = _markerStack.Pop();
				
				//	If the Drop Marker was deleted in the document by
				//	a user action it will be disposed but not removed
				//	from the marker stack. In this case just pretend
				//	like it doesn't exist and go on to the next one
				if (dm.IsDisposed)
					continue;

				//	The MarkerCollection fires a cancellable event.
				//	If it is canclled the Collect() method will return
				//	false. In this case we need to push the marker back
				//	on the stack so that it will still be collected in
				//	the future.
				if (!dm.Collect())
					_markerStack.Push(dm);

				return;
			}
		}

		private int getCurrentTopOffset()
		{
			return -1;
		}

	}

	public class DropMarkerList : System.Collections.ObjectModel.KeyedCollection<Guid, DropMarker>
	{
		protected override Guid GetKeyForItem(DropMarker item)
		{
			return item.Key;
		}
	}

	public class DropMarker : ManagedRange
	{
		private int _topOffset;
		public int TopOffset
		{
			get
			{
				return _topOffset;
			}
			set
			{
				_topOffset = value;
			}
		}

		private Guid _key = Guid.NewGuid();
		public Guid Key
		{
			get
			{
				return _key;
			}
			set
			{
				_key = value;
			}
		}


		public DropMarker(int start, int end, int topOffset, Scintilla scintilla)
			: base(start, end, scintilla)
		{
			base.Start		= start;
			base.End		= end;
			this._topOffset = topOffset;
		}

		public override void Change(int newStart, int newEnd)
		{
			Invalidate();			
			//	This actually changes Start and End
			base.Change(newStart, newEnd);
		}

		public void Invalidate()
		{
			if(Scintilla != null && Start > 0)
			{
				//	Invalidate the old Marker Location so that we don't get "Ghosts"
				Scintilla.Invalidate(GetClientRectangle());
			}
		}

		//	Drop Markers are points, not a spanned range. Though this could change in the future.
		public override bool IsPoint
		{
			get
			{
				return Start == End;
			}
		}

		protected internal override void Paint(Graphics g)
		{
			base.Paint(g);

			if (IsDisposed)
				return;

			int x = NativeScintilla.PointXFromPosition(Start);
			int y = NativeScintilla.PointYFromPosition(Start) + NativeScintilla.TextHeight(0) - 2;

			//	Draw a red Triangle with a dark red border at the marker position
			g.FillPolygon(Brushes.Red, new Point[] { new Point(x-2, y+4), new Point(x, y), new Point(x+2, y+4) });
			g.DrawPolygon(Pens.DarkRed, new Point[] { new Point(x-2, y+4), new Point(x, y), new Point(x+2, y+4) });
		}

		public bool Collect()
		{
			return Collect(true);
		}

		internal bool Collect(bool dispose)
		{
			DropMarkerCollectEventArgs e = new DropMarkerCollectEventArgs(this);
			Scintilla.OnDropMarkerCollect(e);

			if (e.Cancel)
				return false;

			GotoStart();

			if (dispose)
				Dispose();

			return true;
		}

		public override void Dispose()
		{
			Scintilla.DropMarkers.AllDocumentDropMarkers.Remove(this);
			Invalidate();
			base.Dispose();
		}		

		public Rectangle GetClientRectangle()
		{
			int x = NativeScintilla.PointXFromPosition(Start);
			int y = NativeScintilla.PointYFromPosition(Start) + NativeScintilla.TextHeight(0) - 2;

			//	Invalidate the old Marker Location so that we don't get "Ghosts"
			return new Rectangle(x - 2, y, 5, 5);
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions