diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/VectorImage/Controls/VectorImageControl.cs b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/VectorImage/Controls/VectorImageControl.cs index 2851e51b..06ad95e5 100644 --- a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/VectorImage/Controls/VectorImageControl.cs +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/VectorImage/Controls/VectorImageControl.cs @@ -23,6 +23,7 @@ using System.Collections.Generic; using MBS.Framework.Drawing; using MBS.Framework.UserInterface; using MBS.Framework.UserInterface.Drawing; +using MBS.Framework.UserInterface.Input.Mouse; using UniversalEditor.ObjectModels.Multimedia.VectorImage; using UniversalEditor.ObjectModels.Multimedia.VectorImage.VectorItems; @@ -30,6 +31,12 @@ namespace UniversalEditor.Editors.Multimedia.VectorImage.Controls { public class VectorImageControl : CustomControl { + DragManager dragManager = new DragManager(); + public VectorImageControl() + { + dragManager.Register(this); + } + protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); @@ -46,6 +53,84 @@ namespace UniversalEditor.Editors.Multimedia.VectorImage.Controls } } + public VectorItem HitTest(Vector2D point) + { + VectorImageEditor editor = (Parent as VectorImageEditor); + if (editor == null) return null; + + VectorImageObjectModel vec = (editor.ObjectModel as VectorImageObjectModel); + if (vec == null) return null; + + for (int i = 0; i < vec.Items.Count; i++) + { + if (vec.Items[i].Contains(point)) + return vec.Items[i]; + } + return null; + } + + private VectorItem m_HoverItem = null; + private double dx = 0, dy = 0; + private double cx = 0, cy = 0; + private double gx = 0, gy = 0; + + protected override void OnMouseDown(MouseEventArgs e) + { + base.OnMouseDown(e); + if (e.Buttons == MouseButtons.Primary) + { + m_HoverItem = HitTest(e.Location); + if (m_HoverItem is LineVectorItem) + { + dx = (m_HoverItem as LineVectorItem).X1.GetValue(MeasurementUnit.Pixel); + dy = (m_HoverItem as LineVectorItem).Y1.GetValue(MeasurementUnit.Pixel); + gx = ((m_HoverItem as LineVectorItem).X2.GetValue(MeasurementUnit.Pixel) - (m_HoverItem as LineVectorItem).X1.GetValue(MeasurementUnit.Pixel)); + gy = ((m_HoverItem as LineVectorItem).Y2.GetValue(MeasurementUnit.Pixel) - (m_HoverItem as LineVectorItem).Y1.GetValue(MeasurementUnit.Pixel)); + } + cx = e.Location.X; + cy = e.Location.Y; + Refresh(); + } + } + protected override void OnMouseMove(MouseEventArgs e) + { + base.OnMouseMove(e); + + if (e.Buttons == MouseButtons.None) + { + VectorItem _item = HitTest(e.Location); + if (_item != m_HoverItem) + { + m_HoverItem = _item; + Refresh(); + } + + if (_item != null) + { + Cursor = Cursors.Move; + } + else + { + Cursor = Cursors.Default; + } + } + else if (e.Buttons == MouseButtons.Primary) + { + if (m_HoverItem != null) + { + if (m_HoverItem is LineVectorItem) + { + Measurement mx = new Measurement(dx + (e.X - cx), MeasurementUnit.Pixel), my = new Measurement(dy + (e.Y - cy), MeasurementUnit.Pixel); + Measurement mgx = new Measurement(gx + (e.X - cx), MeasurementUnit.Pixel), mgy = new Measurement(gy + (e.Y - cy), MeasurementUnit.Pixel); + ((LineVectorItem)m_HoverItem).X1 = mx; + ((LineVectorItem)m_HoverItem).X2 = mgx; + ((LineVectorItem)m_HoverItem).Y1 = my; + ((LineVectorItem)m_HoverItem).Y2 = mgy; + } + } + } + } + private void DrawVectorItem(Graphics graphics, VectorItem vectorItem) { if (vectorItem is PolygonVectorItem) @@ -67,6 +152,21 @@ namespace UniversalEditor.Editors.Multimedia.VectorImage.Controls { graphics.DrawPolygon(new Pen(poly.Style.BorderColor), points); } + + if (m_HoverItem == poly) + { + graphics.DrawPolygon(new Pen(SystemColors.HighlightBackground), points); + } + } + else if (vectorItem is LineVectorItem) + { + LineVectorItem line = (vectorItem as LineVectorItem); + + graphics.DrawLine(new Pen(line.Style.BorderColor), line.X1.GetValue(), line.Y1.GetValue(), line.X2.GetValue(), line.Y2.GetValue()); + if (m_HoverItem == line) + { + graphics.DrawLine(new Pen(SystemColors.HighlightBackground), line.X1.GetValue(), line.Y1.GetValue(), line.X2.GetValue(), line.Y2.GetValue()); + } } } } diff --git a/Plugins/UniversalEditor.Plugins.Multimedia/ObjectModels/Multimedia/VectorImage/VectorItem.cs b/Plugins/UniversalEditor.Plugins.Multimedia/ObjectModels/Multimedia/VectorImage/VectorItem.cs index 6ff135dc..3c51ffe0 100644 --- a/Plugins/UniversalEditor.Plugins.Multimedia/ObjectModels/Multimedia/VectorImage/VectorItem.cs +++ b/Plugins/UniversalEditor.Plugins.Multimedia/ObjectModels/Multimedia/VectorImage/VectorItem.cs @@ -19,6 +19,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . using System; +using MBS.Framework.Drawing; + namespace UniversalEditor.ObjectModels.Multimedia.VectorImage { public abstract class VectorItem : ICloneable @@ -28,6 +30,18 @@ namespace UniversalEditor.ObjectModels.Multimedia.VectorImage } + public Rectangle Bounds { get; set; } = Rectangle.Empty; + public VectorImageStyle Style { get; set; } = new VectorImageStyle(); + public abstract object Clone(); + + protected virtual bool ContainsInternal(Vector2D point) + { + return Bounds.Contains(point); + } + public bool Contains(Vector2D point) + { + return ContainsInternal(point); + } } } diff --git a/Plugins/UniversalEditor.Plugins.Multimedia/ObjectModels/Multimedia/VectorImage/VectorItems/LineVectorItem.cs b/Plugins/UniversalEditor.Plugins.Multimedia/ObjectModels/Multimedia/VectorImage/VectorItems/LineVectorItem.cs new file mode 100644 index 00000000..c79915ce --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.Multimedia/ObjectModels/Multimedia/VectorImage/VectorItems/LineVectorItem.cs @@ -0,0 +1,53 @@ +// +// LineVectorItem.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +using MBS.Framework.Drawing; + +namespace UniversalEditor.ObjectModels.Multimedia.VectorImage.VectorItems +{ + public class LineVectorItem : VectorItem + { + public Measurement X1 { get; set; } = Measurement.Empty; + public Measurement X2 { get; set; } = Measurement.Empty; + public Measurement Y1 { get; set; } = Measurement.Empty; + public Measurement Y2 { get; set; } = Measurement.Empty; + + protected override bool ContainsInternal(Vector2D point) + { + double m = (Y2.GetValue(MeasurementUnit.Pixel) - Y1.GetValue(MeasurementUnit.Pixel)) / (X2.GetValue(MeasurementUnit.Pixel) - X1.GetValue(MeasurementUnit.Pixel)); + double b = (Y2.GetValue(MeasurementUnit.Pixel) - (m * (X2.GetValue(MeasurementUnit.Pixel)))); + + double y = (m * point.X) + b; + double pb = 4; + return (y >= point.Y - pb) && (y <= point.Y + pb); + } + + public override object Clone() + { + LineVectorItem clone = new LineVectorItem(); + clone.X1 = X1; + clone.X2 = X2; + clone.Y1 = Y1; + clone.Y2 = Y2; + return clone; + } + } +} diff --git a/Plugins/UniversalEditor.Plugins.Multimedia/ObjectModels/Multimedia/VectorImage/VectorItems/PolygonVectorItem.cs b/Plugins/UniversalEditor.Plugins.Multimedia/ObjectModels/Multimedia/VectorImage/VectorItems/PolygonVectorItem.cs index 05ed3e34..31875d0a 100644 --- a/Plugins/UniversalEditor.Plugins.Multimedia/ObjectModels/Multimedia/VectorImage/VectorItems/PolygonVectorItem.cs +++ b/Plugins/UniversalEditor.Plugins.Multimedia/ObjectModels/Multimedia/VectorImage/VectorItems/PolygonVectorItem.cs @@ -20,23 +20,18 @@ // along with this program. If not, see . using System; using System.Collections.Generic; +using MBS.Framework.Drawing; namespace UniversalEditor.ObjectModels.Multimedia.VectorImage.VectorItems { public class PolygonVectorItem : VectorItem { - public double X { get; set; } = 0; - public double Y { get; set; } = 0; - - public VectorImageStyle Style { get; set; } = new VectorImageStyle(); - public List Points { get; } = new List(); public override object Clone() { PolygonVectorItem clone = new PolygonVectorItem(); - clone.X = X; - clone.Y = Y; + clone.Bounds = Bounds; clone.Style = Style.Clone() as VectorImageStyle; for (int i = 0; i < Points.Count; i++) { diff --git a/Plugins/UniversalEditor.Plugins.Multimedia/UniversalEditor.Plugins.Multimedia.csproj b/Plugins/UniversalEditor.Plugins.Multimedia/UniversalEditor.Plugins.Multimedia.csproj index b3c7afc6..f769641f 100644 --- a/Plugins/UniversalEditor.Plugins.Multimedia/UniversalEditor.Plugins.Multimedia.csproj +++ b/Plugins/UniversalEditor.Plugins.Multimedia/UniversalEditor.Plugins.Multimedia.csproj @@ -341,6 +341,7 @@ + diff --git a/Plugins/UniversalEditor.Plugins.Office/Associations/VectorImage/OpenDocumentVectorImageDataFormat.uexml b/Plugins/UniversalEditor.Plugins.Office/Associations/VectorImage/OpenDocumentVectorImageDataFormat.uexml new file mode 100644 index 00000000..2c3109a6 --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.Office/Associations/VectorImage/OpenDocumentVectorImageDataFormat.uexml @@ -0,0 +1,25 @@ + + + + + + + + *.odg + + + + PK + + + + + + + + + + + + + diff --git a/Plugins/UniversalEditor.Plugins.Office/DataFormats/VectorImage/OpenDocument/OpenDocumentVectorImageDataFormat.cs b/Plugins/UniversalEditor.Plugins.Office/DataFormats/VectorImage/OpenDocument/OpenDocumentVectorImageDataFormat.cs new file mode 100644 index 00000000..04201afd --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.Office/DataFormats/VectorImage/OpenDocument/OpenDocumentVectorImageDataFormat.cs @@ -0,0 +1,151 @@ +// +// OpenDocumentVectorImageDataFormat.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +using System.Collections.Generic; +using MBS.Framework.Drawing; +using UniversalEditor.Accessors; +using UniversalEditor.DataFormats.Markup.XML; +using UniversalEditor.DataFormats.Package.OpenDocument; +using UniversalEditor.ObjectModels.FileSystem; +using UniversalEditor.ObjectModels.Markup; +using UniversalEditor.ObjectModels.Multimedia.VectorImage; +using UniversalEditor.ObjectModels.Package; + +namespace UniversalEditor.Plugins.Office.DataFormats.VectorImage.OpenDocument +{ + public class OpenDocumentVectorImageDataFormat : OpenDocumentDataFormat + { + private static DataFormatReference _dfr = null; + protected override DataFormatReference MakeReferenceInternal() + { + if (_dfr == null) + { + _dfr = new DataFormatReference(GetType()); + _dfr.Capabilities.Add(typeof(VectorImageObjectModel), DataFormatCapabilities.All); + } + return _dfr; + } + + protected override void BeforeLoadInternal(Stack objectModels) + { + objectModels.Push(new PackageObjectModel()); + base.BeforeLoadInternal(objectModels); + } + protected override void AfterLoadInternal(Stack objectModels) + { + base.AfterLoadInternal(objectModels); + + PackageObjectModel package = (objectModels.Pop() as PackageObjectModel); + if (package == null) throw new ObjectModelNotSupportedException(); + + VectorImageObjectModel vec = (objectModels.Pop() as VectorImageObjectModel); + if (vec == null) throw new ObjectModelNotSupportedException(); + + XMLDataFormat xdf = new XMLDataFormat(); + MarkupObjectModel mom_content = new MarkupObjectModel(); + File file_content_xml = package.FileSystem.Files["content.xml"]; + if (file_content_xml == null) + throw new InvalidDataFormatException("content.xml not found in root directory"); + + Document.Load(mom_content, xdf, new EmbeddedFileAccessor(file_content_xml)); + + MarkupTagElement tagContent = mom_content.FindElementUsingSchema(OpenDocumentXMLSchemas.Office, "document-content") as MarkupTagElement; + if (tagContent == null) + throw new InvalidDataFormatException("content.xml does not contain a top-level document-content tag"); + + MarkupTagElement tagBody = tagContent.FindElementUsingSchema(OpenDocumentXMLSchemas.Office, "body") as MarkupTagElement; + if (tagBody != null) + { + MarkupTagElement tagDrawing = tagBody.FindElementUsingSchema(OpenDocumentXMLSchemas.Office, "drawing") as MarkupTagElement; + if (tagDrawing != null) + { + MarkupTagElement tagPage = tagDrawing.FindElementUsingSchema(OpenDocumentXMLSchemas.Draw, "page") as MarkupTagElement; + if (tagPage != null) + { + MarkupAttribute attName = tagPage.FindAttributeUsingSchema(OpenDocumentXMLSchemas.Draw, "name"); + if (attName != null) + { + + } + + for (int i = 0; i < tagPage.Elements.Count; i++) + { + MarkupTagElement tag = tagPage.Elements[i] as MarkupTagElement; + if (tag == null) continue; + + if (tag.Name == "line" && tag.XMLSchema == OpenDocumentXMLSchemas.Draw) + { + MarkupAttribute attX1 = tag.FindAttributeUsingSchema(OpenDocumentXMLSchemas.Svg, "x1"); + MarkupAttribute attY1 = tag.FindAttributeUsingSchema(OpenDocumentXMLSchemas.Svg, "y1"); + MarkupAttribute attX2 = tag.FindAttributeUsingSchema(OpenDocumentXMLSchemas.Svg, "x2"); + MarkupAttribute attY2 = tag.FindAttributeUsingSchema(OpenDocumentXMLSchemas.Svg, "y2"); + if (attX1 == null || attY1 == null || attX2 == null || attY2 == null) + { + continue; + } + + UniversalEditor.ObjectModels.Multimedia.VectorImage.VectorItems.LineVectorItem lvi = new UniversalEditor.ObjectModels.Multimedia.VectorImage.VectorItems.LineVectorItem(); + + // if stroke color is null + lvi.Style.BorderColor = Colors.Black; // Colors.CornflowerBlue; + + lvi.X1 = Measurement.Parse(attX1.Value); + lvi.X2 = Measurement.Parse(attX2.Value); + lvi.Y1 = Measurement.Parse(attY1.Value); + lvi.Y2 = Measurement.Parse(attY2.Value); + lvi.Bounds = new Rectangle(lvi.X1.GetValue(MeasurementUnit.Pixel), lvi.Y1.GetValue(MeasurementUnit.Pixel), lvi.X2.GetValue(MeasurementUnit.Pixel) - lvi.X1.GetValue(MeasurementUnit.Pixel), lvi.Y2.GetValue(MeasurementUnit.Pixel) - lvi.Y1.GetValue(MeasurementUnit.Pixel)); + vec.Items.Add(lvi); + } + else if (tag.Name == "custom-shape" && tag.XMLSchema == OpenDocumentXMLSchemas.Draw) + { + MarkupAttribute attX = tag.FindAttributeUsingSchema(OpenDocumentXMLSchemas.Svg, "x"); + MarkupAttribute attY = tag.FindAttributeUsingSchema(OpenDocumentXMLSchemas.Svg, "y"); + MarkupAttribute attWidth = tag.FindAttributeUsingSchema(OpenDocumentXMLSchemas.Svg, "width"); + MarkupAttribute attHeight = tag.FindAttributeUsingSchema(OpenDocumentXMLSchemas.Svg, "height"); + + MarkupTagElement tagEnhancedGeometry = tag.FindElementUsingSchema(OpenDocumentXMLSchemas.Draw, "enhanced-geometry") as MarkupTagElement; + if (tagEnhancedGeometry != null) + { + MarkupAttribute attType = tagEnhancedGeometry.FindAttributeUsingSchema(OpenDocumentXMLSchemas.Draw, "type"); + if (attType != null) + { + + } + } + } + } + } + } + } + } + + protected override void BeforeSaveInternal(Stack objectModels) + { + base.BeforeSaveInternal(objectModels); + + VectorImageObjectModel vec = (objectModels.Pop() as VectorImageObjectModel); + if (vec == null) throw new ObjectModelNotSupportedException(); + + PackageObjectModel package = new PackageObjectModel(); + objectModels.Push(package); + } + } +} diff --git a/Plugins/UniversalEditor.Plugins.Office/DataFormats/VectorImage/OpenDocument/OpenDocumentXMLSchemas.cs b/Plugins/UniversalEditor.Plugins.Office/DataFormats/VectorImage/OpenDocument/OpenDocumentXMLSchemas.cs new file mode 100644 index 00000000..2250cd93 --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.Office/DataFormats/VectorImage/OpenDocument/OpenDocumentXMLSchemas.cs @@ -0,0 +1,30 @@ +// +// OpenDocumentSchemas.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2020 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +namespace UniversalEditor.Plugins.Office.DataFormats.VectorImage.OpenDocument +{ + public static class OpenDocumentXMLSchemas + { + public const string Office = "urn:oasis:names:tc:opendocument:xmlns:office:1.0"; + public const string Draw = "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"; + public const string Svg = "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"; + } +} diff --git a/Plugins/UniversalEditor.Plugins.Office/UniversalEditor.Plugins.Office.csproj b/Plugins/UniversalEditor.Plugins.Office/UniversalEditor.Plugins.Office.csproj index 49f6838a..d27d7b19 100644 --- a/Plugins/UniversalEditor.Plugins.Office/UniversalEditor.Plugins.Office.csproj +++ b/Plugins/UniversalEditor.Plugins.Office/UniversalEditor.Plugins.Office.csproj @@ -46,6 +46,8 @@ + + @@ -57,6 +59,9 @@ + + + @@ -67,9 +72,18 @@ {30467E5C-05BC-4856-AADC-13906EF4CADD} UniversalEditor.Essential + + {BE4D0BA3-0888-42A5-9C09-FC308A4509D2} + UniversalEditor.Plugins.Multimedia + + + {00266B21-35C9-4A7F-A6BA-D54D7FDCC25C} + MBS.Framework + + \ No newline at end of file