using PaintDotNet.Annotation.Enum; using PaintDotNet.Base.SettingModel; using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Globalization; using System.Linq; using System.Runtime.Serialization; using System.Security.Permissions; namespace PaintDotNet.Annotation { using DrawList = List; public interface DocumentDirtyObserver { void IsDirty(GraphicsList gList); } /// /// 绘制对象的数组 /// 每个surface保持一个自己的list /// [Serializable] public class GraphicsList : ISerializable { public DrawList graphicsList; private List observers; private bool dirty; private const string entryCount = "Count"; private const string entryType = "Type"; public GraphicsList() { this.graphicsList = new DrawList(); this.observers = new List(); this.dirty = false; } public GraphicsList(ISurfaceBox surfaceBox) { this.graphicsList = new DrawList(); this.observers = new List(); this.dirty = false; } #region Serialization Support /// /// Save object to serialization stream /// /// /// [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)] public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue(entryCount, graphicsList.Count); int i = 0; foreach (DrawObject o in graphicsList) { info.AddValue( String.Format(CultureInfo.InvariantCulture, "{0}{1}", entryType, i), o.GetType().FullName); o.SaveToStream(info, i); i++; } } #endregion #region Other functions protected void NotifyDirty() { if (this.dirty) { foreach (DocumentDirtyObserver obs in this.observers) { obs.IsDirty(this); } } } public void Draw(Graphics g) { int n = graphicsList.Count; DrawObject o; int n3 = 0; // Enumerate list in reverse order to get first // object on the top of Z-order. for (int i = n - 1; i >= 0; i--) { o = graphicsList[i]; //如果是视场,则只绘制一次 if (o.objectType == DrawClass.View) { if (n3 == 0) { o.Draw(g); n3++; } } else { o.Draw(g); } if (o.Selected == true) { o.DrawTracker(g); } } } /// /// Dump (for debugging) /// public void Dump() { Trace.WriteLine(""); foreach (DrawObject o in graphicsList) { o.Dump(); } } /// /// Clear all objects in the list /// /// /// true if at least one object is deleted /// public bool Clear() { bool result = (graphicsList.Count > 0); graphicsList.Clear(); return result; } /// /// Tells if the document is dirty. /// public bool Dirty { get { return this.dirty; } set { this.dirty = value; if (this.dirty) { NotifyDirty(); } } } /// /// Count and this [nIndex] allow to read all graphics objects /// from GraphicsList in the loop. /// public int Count { get { return graphicsList.Count; } } public DrawObject this[int index] { get { if (index < 0 || index >= graphicsList.Count) return null; return graphicsList[index]; } } public Size GetSize() { Size size = new Size(0, 0); foreach (DrawObject obj in graphicsList) { RectangleF objRect = obj.Rectangle; size.Width = (int)Math.Max(size.Width, objRect.X + objRect.Width); size.Height = (int)Math.Max(size.Height, objRect.Y + objRect.Height); } size.Width += 20; size.Height += 20; return size; } #region Selection /// /// SelectedCount and GetSelectedObject allow to read /// selected objects in the loop /// public int SelectionCount { get { int n = 0; foreach (DrawObject o in Selection) { n++; } return n; } } public IEnumerable Selection { get { foreach (DrawObject o in graphicsList) { if (o.Selected) { yield return o; } } } } DrawObject LastDrawObject = null; /// /// 用于修改视场,获得选中的视场 /// 因为修改视场判断了只能修改一个, /// 所以找到一个被选中就返回 /// public DrawObject SelectDrawObject { get { if (graphicsList.Count((o) => o.Selected) == 1) return graphicsList.Find((o) => o.Selected); else return null; } } public event EventHandler SelectChanged; public virtual void OnSelectChanged() { if (LastDrawObject == SelectDrawObject) return; LastDrawObject = SelectDrawObject; SelectChanged?.Invoke(this, EventArgs.Empty); } public void SelectInRectangle(Rectangle rectangle) { UnselectAll(); foreach (DrawObject o in graphicsList) { if (o.IntersectsWith(rectangle) && !o.isLocked) o.Selected = true; } } public void UnselectAll() { foreach (DrawObject o in graphicsList) { o.Selected = false; } } public void SelectAll() { foreach (DrawObject o in graphicsList) { if (!o.isLocked) { o.Selected = true; } } } #endregion #region 增删改 public void Add(DrawObject obj) { obj.SelectedChanged += OnSelectChanged; graphicsList.Insert(0, obj); this.Dirty = true; } /// /// Insert object to specified place. /// Used for Undo. /// public void Insert(int index, DrawObject obj) { if (index >= 0 && index < graphicsList.Count) { graphicsList.Insert(index, obj); } } /// /// Replace object in specified place. /// Used for Undo. /// public void Replace(int index, DrawObject obj) { if (index >= 0 && index < graphicsList.Count) { graphicsList.RemoveAt(index); graphicsList.Insert(index, obj); } } /// /// Remove object by index. /// Used for Undo. /// public void RemoveAt(int index) { graphicsList.RemoveAt(index); } public void RemoveObj(DrawObject obj) { graphicsList.Remove(obj); } public void RemoveByIds(List ids) { for (int i = 0; i < ids.Count; i++) { graphicsList.RemoveAll(u => u.ID == ids[i]); } } /// /// Delete last added object from the list /// (used for Undo operation). /// public void DeleteLastAddedObject() { if (graphicsList.Count > 0) { graphicsList.RemoveAt(0); } } /// /// 删除选中,目前应用在视场 /// /// /// true if at least one object is deleted /// public bool DeleteSelection(DrawClass type) { bool result = false; int n = graphicsList.Count; for (int i = n - 1; i >= 0; i--) { if (((DrawObject)graphicsList[i]).Selected) { //这里用来区分选择的是标注、测量、还是视场 //比如选择的是测量,用删除视场的菜单就不应该生效 if (type == ((DrawObject)graphicsList[i]).objectType) { graphicsList.RemoveAt(i); result = true; } } } return result; } #endregion /// /// 删除某种类型的工具 /// /// /// public bool DeleteDrawClass(DrawClass type) { bool result = false; int n = graphicsList.Count; for (int i = n - 1; i >= 0; i--) { if (type == ((DrawObject)graphicsList[i]).objectType) { graphicsList.RemoveAt(i); result = true; } } return result; } public bool DeleteDrawClass(DrawToolType type) { bool result = false; int n = graphicsList.Count; for (int i = n - 1; i >= 0; i--) { if (type == ((DrawObject)graphicsList[i]).drawToolType) { graphicsList.RemoveAt(i); result = true; } } return result; } /// /// 清空视场 /// /// public void DeleteAllView() { int n = graphicsList.Count; for (int i = n - 1; i >= 0; i--) { if (DrawClass.View == ((DrawObject)graphicsList[i]).objectType) { graphicsList.RemoveAt(i); } } } /// /// 向上移动 /// /// public bool MoveSelectionToMoveUp() { int n = graphicsList.Count; for (int i = 0; i < n; i++) { if ((graphicsList[i]).Selected) { if (i > 0) { graphicsList.Insert(i - 1, graphicsList[i]); graphicsList.RemoveAt(i + 1); } } } return true; } /// /// 向下移动 /// /// public bool MoveSelectionToMoveDown() { int n = graphicsList.Count; for (int i = 0; i < n; i++) { if ((graphicsList[i]).Selected) { if (i < n - 1) { graphicsList.Insert(i + 2, graphicsList[i]); graphicsList.RemoveAt(i); break; } } } return true; } /// /// 移动到最上 /// Move selected items to front (beginning of the list) /// /// /// true if at least one object is moved /// public bool MoveSelectionToFront() { int n; int i; DrawList tempList; tempList = new DrawList(); n = graphicsList.Count; // Read source list in reverse order, add every selected item // to temporary list and remove it from source list for (i = n - 1; i >= 0; i--) { if ((graphicsList[i]).Selected) { tempList.Add(graphicsList[i]); graphicsList.RemoveAt(i); } } // Read temporary list in direct order and insert every item // to the beginning of the source list n = tempList.Count; for (i = 0; i < n; i++) { graphicsList.Insert(0, tempList[i]); } return (n > 0); } /// /// 移动到最下 /// Move selected items to back (end of the list) /// /// /// true if at least one object is moved /// public bool MoveSelectionToBack() { int n; int i; DrawList tempList; tempList = new DrawList(); n = graphicsList.Count; // Read source list in reverse order, add every selected item // to temporary list and remove it from source list for (i = n - 1; i >= 0; i--) { if ((graphicsList[i]).Selected) { tempList.Add(graphicsList[i]); graphicsList.RemoveAt(i); } } // Read temporary list in reverse order and add every item // to the end of the source list n = tempList.Count; for (i = n - 1; i >= 0; i--) { graphicsList.Add(tempList[i]); } return (n > 0); } #endregion /// /// 判断是否存在视场 /// /// public bool IsExsitView() { if (this.graphicsList != null && this.graphicsList.Count > 0 && this.graphicsList.FindAll(a => a.objectType == DrawClass.View).Count > 0) { return true; } return false; } /// /// 获取画布内指定大类的集合 /// /// public List GetDrawClassList(DrawClass drawClass) { return this.graphicsList.FindAll(a => a.objectType == drawClass); } /// /// 检测当前画板内是否存在指定的类型 /// /// /// public bool IsExsitSpecificObject(DrawToolType drawToolType) { if (this.graphicsList != null && this.graphicsList.Count > 0) return this.graphicsList.FindAll(a => a.drawToolType == drawToolType).Count > 0; return false; } /// /// 获取画板内指定类型的集合 /// /// /// public List GetDrawToolTypeList(DrawToolType drawToolType) { return this.graphicsList.FindAll(a => a.drawToolType == drawToolType); } public DrawObject GetById(int id) { return this.graphicsList.Find(a => a.ID == id); } public List GetLabelsOrMeasureData(DrawClass drawClass) { List list = new List(); foreach (DrawObject o in graphicsList) { if (o.objectType == drawClass) { LabelMeasureDataModel labelData = new LabelMeasureDataModel(); labelData.drawClass = o.objectType.ToString(); labelData.drawToolType = o.drawToolType.ToString(); labelData.points = o.GetPoints(); labelData.style = o.GetStyle(); labelData.content = o.GetContent(); list.Add(labelData); } } return list; } } }