diff --git a/.paket/Paket.Restore.targets b/.paket/Paket.Restore.targets
index 305e736c..52f41c60 100644
--- a/.paket/Paket.Restore.targets
+++ b/.paket/Paket.Restore.targets
@@ -11,23 +11,49 @@
$(MSBuildThisFileDirectory)..\
$(PaketRootPath)paket-files\paket.restore.cached
$(PaketRootPath)paket.lock
+ classic
+ proj
+ assembly
+ native
/Library/Frameworks/Mono.framework/Commands/mono
mono
-
- $(PaketRootPath)paket.exe
- $(PaketToolsPath)paket.exe
- "$(PaketExePath)"
- $(MonoPath) --runtime=v4.0.30319 "$(PaketExePath)"
-
+
+ $(PaketRootPath)paket.bootstrapper.exe
+ $(PaketToolsPath)paket.bootstrapper.exe
+ $([System.IO.Path]::GetDirectoryName("$(PaketBootStrapperExePath)"))\
+
+
+
+
+ $(PaketRootPath)paket.exe
+ $(PaketToolsPath)paket.exe
+ $(PaketToolsPath)paket.exe
+ $(_PaketBootStrapperExeDir)paket.exe
+ paket.exe
+
+
+ $(PaketRootPath)paket
+ $(PaketToolsPath)paket
+ $(PaketToolsPath)paket
+
+
+ $(PaketRootPath)paket.exe
+ $(PaketToolsPath)paket.exe
+
+
+ $(PaketBootStrapperExeDir)paket.exe
+
+
+ paket
+
+
<_PaketExeExtension>$([System.IO.Path]::GetExtension("$(PaketExePath)"))
- dotnet "$(PaketExePath)"
+ dotnet "$(PaketExePath)"
+ $(MonoPath) --runtime=v4.0.30319 "$(PaketExePath)"
+ "$(PaketExePath)"
-
- "$(PaketExePath)"
- $(PaketRootPath)paket.bootstrapper.exe
- $(PaketToolsPath)paket.bootstrapper.exe
"$(PaketBootStrapperExePath)"
$(MonoPath) --runtime=v4.0.30319 "$(PaketBootStrapperExePath)"
@@ -36,9 +62,16 @@
true
true
+
+
+ True
-
+
+
+
+
+
@@ -72,12 +105,16 @@
true
-
+
+
true
-
+
@@ -141,16 +178,19 @@
+ $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',').Length)
$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[0])
$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[1])
$([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[4])
- $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[5])
+ $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[5])
%(PaketReferencesFileLinesInfo.PackageVersion)
All
- runtime
+ runtime
+ runtime
true
+ true
@@ -182,19 +222,27 @@
false
+ $(MSBuildVersion)
+ 15.8.0
<_NuspecFilesNewLocation Include="$(BaseIntermediateOutputPath)$(Configuration)\*.nuspec"/>
+
+
$(MSBuildProjectDirectory)/$(MSBuildProjectFile)
true
- false
- true
+ false
+ true
+ false
+ true
+ false
+ true
$(BaseIntermediateOutputPath)$(Configuration)
$(BaseIntermediateOutputPath)
@@ -209,9 +257,52 @@
-
-
+
+
-
/// Checking whether point belongs to line.
@@ -54,5 +55,25 @@ public static bool BelongsToLine(Point lineStart, Point lineEnd, Point point)
/// Second point.
/// Distance between two points.
public static double GetDistance(Point p1, Point p2) => (p1 - p2).Length;
+
+ ///
+ /// Round position of the vertex, so it would stand in the check
+ ///
+ /// Given position
+ /// The scale of the check in the net
+ /// Necessary for nodes which labels are wider then pictures
+ public static System.Windows.Point RoundPosition(System.Windows.Point currentPosition, double checkScale, double currentWidth = wantedWidth)
+ {
+ double difference = 0;
+ if (currentWidth != wantedWidth && currentWidth != 0)
+ {
+ difference = (currentWidth - wantedWidth) / 2;
+ }
+
+ currentPosition.X = Math.Round(currentPosition.X / checkScale) * checkScale - difference;
+ currentPosition.Y = Math.Round(currentPosition.Y / checkScale) * checkScale;
+
+ return currentPosition;
+ }
}
}
diff --git a/src/WpfControlsLib/Controls/Scene/NetVisualHost.cs b/src/WpfControlsLib/Controls/Scene/NetVisualHost.cs
new file mode 100644
index 00000000..92b6a6e2
--- /dev/null
+++ b/src/WpfControlsLib/Controls/Scene/NetVisualHost.cs
@@ -0,0 +1,100 @@
+using System;
+using System.Windows;
+using System.Windows.Media;
+
+namespace WpfControlsLib.Controls.Scene
+{
+ ///
+ /// Class that provides net for scene
+ ///
+ public class NetVisualHost : FrameworkElement
+ {
+ ///
+ /// Create a collection of child visual objects
+ ///
+ private readonly VisualCollection children;
+
+ ///
+ /// Init parameters and create new visual collection
+ ///
+ /// Height of the scene on the screen
+ /// Width of the scene on the screen
+ /// The scale of net check
+ /// The point that user presses on to move scene
+ public NetVisualHost(double height, double width, double scale, Point point)
+ {
+ children = new VisualCollection(this)
+ {
+ CreateDrawingVisualLines(height, width, scale, point)
+ };
+ }
+
+ ///
+ /// Change the net when params have changed
+ ///
+ /// Height of the scene on the screen
+ /// Width of the scene on the screen
+ /// The scale of net check
+ /// The point that user presses on to move scene
+ public void ChangeNet(double height, double width, double scale, Point point)
+ {
+ children.Clear();
+ children.Add(CreateDrawingVisualLines(height, width, scale, point));
+ }
+
+ ///
+ /// Draw the net
+ ///
+ /// Height of the scene on the screen
+ /// Width of the scene on the screen
+ /// The scale of net check
+ /// The point that user presses on to move scene
+ /// Net, element of visual collection
+ private DrawingVisual CreateDrawingVisualLines(double height, double width, double scale, Point point)
+ {
+ DrawingVisual drawingVisual = new DrawingVisual();
+ DrawingContext drawingContext = drawingVisual.RenderOpen();
+
+ point = Geometry.RoundPosition(point, scale);
+
+ Pen drawingpen = new Pen(Brushes.WhiteSmoke, 1);
+ for (var i = point.Y; i < height + point.Y; i += scale)
+ {
+ drawingContext.DrawLine(drawingpen, new Point(-width + point.X, i), new Point(width + point.X, i));
+ }
+ for (var i = point.Y; i > -height + point.Y; i -= scale)
+ {
+ drawingContext.DrawLine(drawingpen, new Point(-width + point.X, i), new Point(width + point.X, i));
+ }
+ for (var i = point.X; i < width + point.X; i += scale)
+ {
+ drawingContext.DrawLine(drawingpen, new Point(i, -height + point.Y), new Point(i, height + point.Y));
+ }
+ for (var i = point.X; i > -width + point.X; i -= scale)
+ {
+ drawingContext.DrawLine(drawingpen, new Point(i, -height + point.Y), new Point(i, height + point.Y));
+ }
+
+ drawingContext.Close();
+ return drawingVisual;
+ }
+
+ ///
+ /// Provide a required override for the VisualChildrenCount property
+ ///
+ protected override int VisualChildrenCount => children.Count;
+
+ ///
+ /// Provide a required override for the GetVisualChild method
+ ///
+ protected override Visual GetVisualChild(int index)
+ {
+ if (index < 0 || index >= children.Count)
+ {
+ throw new ArgumentOutOfRangeException();
+ }
+
+ return children[index];
+ }
+ }
+}
diff --git a/src/WpfControlsLib/Controls/Scene/NewVertexName.cs b/src/WpfControlsLib/Controls/Scene/NewVertexName.cs
new file mode 100644
index 00000000..ee0b16f1
--- /dev/null
+++ b/src/WpfControlsLib/Controls/Scene/NewVertexName.cs
@@ -0,0 +1,36 @@
+using System.Collections.Generic;
+
+namespace WpfControlsLib.Controls.Scene
+{
+ ///
+ /// Class for work with vertices names
+ ///
+ public static class VertexName
+ {
+ ///
+ /// Change new element name so there would be no same names
+ ///
+ /// New element
+ public static void NewVertexName(Repo.IElement element, List vertexNames)
+ {
+ var name = element.Name;
+ if (element.Name.LastIndexOf('.') != -1)
+ {
+ name = string.Empty;
+ for (var i = 0; i < element.Name.LastIndexOf('.'); i++)
+ {
+ name += element.Name[i];
+ }
+ }
+
+ var counter = 1;
+ while (vertexNames.Contains("a" + name + "." + counter))
+ {
+ counter++;
+ }
+
+ element.Name = name + "." + counter;
+ vertexNames.Add("a" + element.Name);
+ }
+ }
+}
diff --git a/src/WpfControlsLib/Controls/Scene/Scene.xaml b/src/WpfControlsLib/Controls/Scene/Scene.xaml
index 3dc4c8d0..c304b917 100644
--- a/src/WpfControlsLib/Controls/Scene/Scene.xaml
+++ b/src/WpfControlsLib/Controls/Scene/Scene.xaml
@@ -21,11 +21,14 @@
xmlns:graphx="http://schemas.panthernet.ru/graphx/"
xmlns:scene="clr-namespace:WpfControlsLib.Controls.Scene"
mc:Ignorable="d"
- d:DesignHeight="300" d:DesignWidth="300">
+ d:DesignHeight="300" d:DesignWidth="300" Loaded="LoadNet">
-
+
+
+
+
diff --git a/src/WpfControlsLib/Controls/Scene/Scene.xaml.cs b/src/WpfControlsLib/Controls/Scene/Scene.xaml.cs
index 996de698..9fc0dda0 100644
--- a/src/WpfControlsLib/Controls/Scene/Scene.xaml.cs
+++ b/src/WpfControlsLib/Controls/Scene/Scene.xaml.cs
@@ -15,6 +15,7 @@
namespace WpfControlsLib.Controls.Scene
{
using System;
+ using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
@@ -42,10 +43,13 @@ public partial class Scene : UserControl
private VertexControl currentVertex;
private EdgeControl edgeControl;
private Point position;
+ private Point mousePosition;
+ private double checkScale = 26.7;
private Model model;
private Controller controller;
private IElementProvider elementProvider;
+ private NetVisualHost visualHost;
public Scene()
{
@@ -57,9 +61,14 @@ public Scene()
this.graphArea.VertexSelected += this.VertexSelectedAction;
this.graphArea.EdgeSelected += this.EdgeSelectedAction;
+ this.graphArea.LostMouseCapture += (sender, args) => this.FixPos();
this.zoomControl.Click += this.ClearSelection;
this.zoomControl.MouseDown += this.OnSceneMouseDown;
this.zoomControl.Drop += this.ZoomControlDrop;
+ this.zoomControl.MouseDown += (sender, args) => this.LoadNet(sender, args);
+ this.zoomControl.ZoomAnimationCompleted += (sender, args) => this.LoadNet(sender, args);
+ this.zoomControl.MaxZoom = 1.1;
+ mousePosition = new Point(0, 0);
}
public event EventHandler ElementManipulationDone;
@@ -72,6 +81,11 @@ public Scene()
public event EventHandler ElementRemoved;
+ ///
+ /// Send when there`s something to be told to the user
+ ///
+ public event EventHandler HaveMessage;
+
public Graph Graph { get; set; }
private void InitGraphXLogicCore()
@@ -109,6 +123,9 @@ public void Init(Model model, Controller controller, IElementProvider elementPro
this.Graph.AddNewVertexControl += (sender, args) => this.AddNewVertexControl(args.DataVertex);
this.Graph.AddNewEdgeControl += (sender, args) => this.AddNewEdgeControl(args.EdgeViewModel);
this.InitGraphXLogicCore();
+ this.model.SavePositions += (sender, args) => this.SavePositions();
+ this.model.PlaceVertexCorrectly += (sender, args) => this.PlaceVertexCorrectly();
+ this.model.InitVertexNames += (sender, args) => this.InitVertexNames();
}
public void Clear() => this.Graph.DataGraph.Clear();
@@ -146,7 +163,7 @@ public void SelectNode(string name)
if (this.Graph.DataGraph.Vertices.ToList()[i].Name == name)
{
var vertex = this.Graph.DataGraph.Vertices.ToList()[i];
- this.NodeSelected?.Invoke(this, new NodeSelectedEventArgs {Node = vertex});
+ this.NodeSelected?.Invoke(this, new NodeSelectedEventArgs { Node = vertex });
foreach (var ed in this.graphArea.VertexList)
{
if (ed.Key == vertex)
@@ -191,6 +208,7 @@ private void ZoomControlDrop(object sender, DragEventArgs e)
if (element.Metatype == Repo.Metatype.Node)
{
this.position = this.zoomControl.TranslatePoint(e.GetPosition(this.zoomControl), this.graphArea);
+ VertexName.NewVertexName(element, this.model.VertexNames);
this.CreateNewNode(element);
this.ElementManipulationDone?.Invoke(this, EventArgs.Empty);
}
@@ -335,7 +353,7 @@ private void HandleRoutingPoints(EdgeViewModel edge, GraphX.Measure.Point mouseP
private void AddNewVertexControl(NodeViewModel vertex)
{
var vc = new VertexControl(vertex);
- vc.SetPosition(this.position);
+ vc.SetPosition(Geometry.RoundPosition(this.position, checkScale, vc.ActualWidth));
this.graphArea.AddVertex(vertex, vc);
}
@@ -379,6 +397,7 @@ private void MenuItemClickedOnVertex(object sender, EventArgs e)
command.Add(new RemoveNodeCommand(this.model, vertex.Node));
this.controller.Execute(command);
this.DrawGraph();
+ PlaceVertexCorrectly();
}
private void MenuItemClickEdge(object sender, EventArgs e)
@@ -445,5 +464,113 @@ private void CreateNewNode(Repo.IElement element)
var command = new CreateNodeCommand(this.model, element);
this.controller.Execute(command);
}
+
+ ///
+ /// Save positions to model.positionsTable when the model is saved.
+ /// If there are some vertices have same names, user will be warned.
+ ///
+ private void SavePositions()
+ {
+ this.model.PositionsTable = new Dictionary();
+ var currentPositions = this.graphArea.GetVertexPositions();
+ var firstWarning = false;
+ foreach (var key in currentPositions.Keys)
+ {
+ Point point = new Point(currentPositions[key].X, currentPositions[key].Y);
+ try
+ {
+ this.model.PositionsTable.Add(key.Name, point);
+ }
+ catch (ArgumentException)
+ {
+ if (!firstWarning)
+ {
+ this.HaveMessage?.Invoke(this, "There are vertices with the same names in the model");
+ firstWarning = true;
+ }
+ }
+ }
+ }
+
+ ///
+ /// Arranges the vertices according to model.positionsTable
+ /// If not all vertices are in the positionsTable, first time user will be warned,
+ /// then absent vertices will be added just somewhere
+ ///
+ private void PlaceVertexCorrectly()
+ {
+ if (this.model.PositionsTable.Count == 0)
+ {
+ return;
+ }
+
+ var vertexList = this.graphArea.VertexList;
+ var firstWarning = false;
+ foreach (var key in vertexList.Keys)
+ {
+ try
+ {
+ vertexList[key].SetPosition(this.model.PositionsTable[key.Name]);
+ }
+ catch (KeyNotFoundException)
+ {
+ if (!firstWarning)
+ {
+ this.HaveMessage?.Invoke(this, "Not all vertices are in the file with positions");
+ firstWarning = true;
+ }
+ }
+ }
+ }
+
+ ///
+ /// Fill the list of taken names
+ ///
+ private void InitVertexNames()
+ {
+ this.model.VertexNames = new List();
+ foreach (var key in this.graphArea.GetVertexPositions().Keys)
+ {
+ this.model.VertexNames.Add(key.Name);
+ }
+ }
+
+ ///
+ /// Fix positions so vertices would be in the checks after moving on scene
+ ///
+ private void FixPos()
+ {
+ var key = this.currentVertex.GetDataVertex();
+ var vertexList = this.graphArea.VertexList;
+ var currentPosition = vertexList[key].GetPosition();
+ var width = vertexList[key].ActualWidth;
+ vertexList[key].SetPosition(Geometry.RoundPosition(currentPosition, checkScale, width));
+ }
+
+ ///
+ /// Create a host visual derived from the FrameworkElement class
+ /// Take point from the screen and draw around it the net with necessary size and scale
+ ///
+ private void LoadNet(object sender, EventArgs e)
+ {
+ var chosenPoint = e as MouseButtonEventArgs;
+ if (chosenPoint != null)
+ {
+ mousePosition = chosenPoint.GetPosition(canvas);
+ }
+
+ if (this.visualHost == null)
+ {
+ this.visualHost = new NetVisualHost(zoomControl.ActualHeight / zoomControl.Zoom,
+ zoomControl.ActualWidth / zoomControl.Zoom, checkScale, mousePosition);
+ canvas.Children.Add(visualHost);
+ }
+ else
+ {
+ this.visualHost.ChangeNet(zoomControl.ActualHeight / zoomControl.Zoom,
+ zoomControl.ActualWidth / zoomControl.Zoom, checkScale, mousePosition);
+ }
+ }
}
}
+
diff --git a/src/WpfControlsLib/Model/Model.cs b/src/WpfControlsLib/Model/Model.cs
index 80029d36..79b873ce 100644
--- a/src/WpfControlsLib/Model/Model.cs
+++ b/src/WpfControlsLib/Model/Model.cs
@@ -15,6 +15,8 @@
namespace WpfControlsLib.Model
{
using System;
+ using System.Collections.Generic;
+ using System.Windows;
using EditorPluginInterfaces;
///
@@ -32,6 +34,7 @@ public Model()
{
this.Repo = global::Repo.RepoFactory.Create();
this.Constraints = new Constraints.Constraints();
+ SaveStartModelsNames();
}
public event EventHandler NewVertexAdded;
@@ -44,6 +47,17 @@ public Model()
public event EventHandler UnsavedChanges;
+ public event EventHandler SavePositions;
+
+ public event EventHandler PlaceVertexCorrectly;
+
+ public event EventHandler InitVertexNames;
+
+ ///
+ /// Send when there`s something to be told to the user
+ ///
+ public event EventHandler HaveMessage;
+
///
/// Notifies all views that there are changes so massive that the model shall be completely reloaded
/// (for example, when creating new or opening existing file).
@@ -71,7 +85,8 @@ public bool HasUnsavedChanges
{
get => hasUnsavedChanges;
- private set {
+ private set
+ {
if (hasUnsavedChanges && !value)
{
hasUnsavedChanges = value;
@@ -85,6 +100,16 @@ private set {
}
}
+ ///
+ /// Contains positions of the nodes of this model
+ ///
+ public Dictionary PositionsTable { get; set; }
+
+ ///
+ /// List of vertex names in this model
+ ///
+ public List VertexNames { get; set; }
+
///
/// Clears the contents of current repository and creates new empty one. Things like "Do you want to save
/// changes?" dialog or even new model selection are not supported yet.
@@ -94,7 +119,9 @@ public void New()
this.Repo = global::Repo.RepoFactory.Create();
this.CurrentFileName = "";
this.HasUnsavedChanges = false;
+ this.PositionsTable = new Dictionary();
this.Reinit?.Invoke(this, EventArgs.Empty);
+ SaveStartModelsNames();
}
///
@@ -107,6 +134,17 @@ public void Open(string fileName)
this.CurrentFileName = fileName;
this.HasUnsavedChanges = false;
this.Reinit?.Invoke(this, EventArgs.Empty);
+ this.InitVertexNames?.Invoke(this, null);
+ try
+ {
+ this.PositionsTable = PositionsLoad.OpenPositions(CurrentFileName);
+ }
+ catch (FormatException)
+ {
+ this.HaveMessage?.Invoke(this, "The file with vertices positions has data in wrong format");
+ this.PositionsTable = new Dictionary();
+ }
+ this.PlaceVertexCorrectly?.Invoke(this, null);
}
///
@@ -120,6 +158,8 @@ public void Save()
}
this.Repo.Save(CurrentFileName);
+ this.SavePositions?.Invoke(this, null);
+ PositionsLoad.SavePositionsTable(CurrentFileName, PositionsTable);
this.HasUnsavedChanges = false;
}
@@ -170,8 +210,8 @@ public void CreateNode(Repo.IElement element)
public void CreateEdge(Repo.IEdge edge, Repo.IElement source, Repo.IElement destination)
{
if (this.Constraints.AllowCreateOrExistEdge(
- this.Repo.Model(this.ModelName).Edges,
- source.Name,
+ this.Repo.Model(this.ModelName).Edges,
+ source.Name,
destination.Name))
{
var model = this.Repo.Model(this.ModelName);
@@ -192,6 +232,9 @@ public void CreateEdge(Repo.IEdge edge, Repo.IElement source, Repo.IElement dest
public void RemoveElement(Repo.IElement element)
{
+ this.SavePositions?.Invoke(this, null);
+ PositionsLoad.SavePositionsTable(CurrentFileName, PositionsTable);
+ this.VertexNames.Remove(element.Name);
var model = this.Repo.Model(this.ModelName);
model.DeleteElement(element);
HasUnsavedChanges = true;
@@ -229,5 +272,23 @@ private void RaiseElementRemoved(Repo.IElement element)
this.ElementRemoved?.Invoke(this, args);
}
+
+ ///
+ /// Adds to the VertexNames the names of the nodes in start models.
+ /// Need special method, because the first nodes on the scene are not in the graphArea yet
+ ///
+ private void SaveStartModelsNames()
+ {
+ this.VertexNames = new List();
+
+ var enumerator = this.Repo.Models.GetEnumerator();
+ while (enumerator.MoveNext())
+ {
+ foreach (var node in enumerator.Current.Nodes)
+ {
+ VertexNames.Add(node.Name);
+ }
+ }
+ }
}
}
diff --git a/src/WpfControlsLib/Model/PositionsLoad.cs b/src/WpfControlsLib/Model/PositionsLoad.cs
new file mode 100644
index 00000000..12b36710
--- /dev/null
+++ b/src/WpfControlsLib/Model/PositionsLoad.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Windows;
+
+namespace WpfControlsLib.Model
+{
+ ///
+ /// Is used to open and save positions from txt file with same name as model
+ ///
+ public static class PositionsLoad
+ {
+ ///
+ /// Save dictionary with node positions
+ ///
+ /// Name of the file with model
+ public static void SavePositionsTable(string fileName, Dictionary positionsTable)
+ {
+ var positionsFileName = GetDicFileName(fileName);
+ using (FileStream fstream = new FileStream(positionsFileName, FileMode.OpenOrCreate))
+ {
+ foreach (var nodeName in positionsTable.Keys)
+ {
+ byte[] array1 = System.Text.Encoding.Default.GetBytes(
+ nodeName + " " + Convert.ToString(positionsTable[nodeName].X)
+ + " " + Convert.ToString(positionsTable[nodeName].Y + " "));
+ fstream.Write(array1, 0, array1.Length);
+ }
+ }
+ }
+
+ ///
+ /// Opens file with node positions and fills dictionary
+ ///
+ /// Name of the file with saved model to open
+ /// Whether the positionsFile existed
+ public static Dictionary OpenPositions(string fileName)
+ {
+ var positionsTable = new Dictionary();
+ string positionsFileName = GetDicFileName(fileName);
+
+ if (!File.Exists(positionsFileName))
+ {
+ return new Dictionary();
+ }
+
+ using (var reader = new StreamReader(positionsFileName))
+ {
+ var str = reader.ReadLine().Split(' ');
+ for (var i = 0; i < str.Length - 1; i += 3)
+ {
+ positionsTable.Add(str[i], new Point(
+ Convert.ToDouble(str[i + 1]), Convert.ToDouble(str[i + 2])));
+ }
+ }
+
+ return positionsTable;
+ }
+
+ ///
+ /// Make name for file with node positions
+ ///
+ /// Name of the file containing model
+ /// the name for file with node positions
+ private static string GetDicFileName(string fileName)
+ {
+ if (fileName == "")
+ {
+ return "StartModel.txt";
+ }
+
+ string dicFileName = null;
+ for (var i = 0; i <= fileName.LastIndexOf('.'); i++)
+ {
+ dicFileName += fileName[i];
+ }
+ dicFileName += "txt";
+ return dicFileName;
+ }
+ }
+}
diff --git a/src/WpfControlsLib/WpfControlsLib.csproj b/src/WpfControlsLib/WpfControlsLib.csproj
index 9e260150..d694df4f 100644
--- a/src/WpfControlsLib/WpfControlsLib.csproj
+++ b/src/WpfControlsLib/WpfControlsLib.csproj
@@ -128,6 +128,8 @@
+
+
@@ -149,6 +151,7 @@
+
diff --git a/src/WpfEditor/View/MainWindow.xaml.cs b/src/WpfEditor/View/MainWindow.xaml.cs
index 81cf0f2f..958b0d23 100644
--- a/src/WpfEditor/View/MainWindow.xaml.cs
+++ b/src/WpfEditor/View/MainWindow.xaml.cs
@@ -82,6 +82,7 @@ public MainWindow()
this.scene.ElementRemoved += (sender, args) => this.modelExplorer.RemoveElement(args.Element);
this.scene.NodeSelected += (sender, args) => this.attributesView.DataContext = args.Node;
this.scene.EdgeSelected += (sender, args) => this.attributesView.DataContext = args.Edge;
+ this.scene.HaveMessage += ShowMessage;
this.scene.Init(this.model, this.controller, new PaletteAdapter(this.palette));
@@ -90,6 +91,8 @@ public MainWindow()
this.InitAndLaunchPlugins();
this.InitToolbar();
+
+ this.model.HaveMessage += ShowMessage;
}
private void Reinit(object sender, EventArgs e)
@@ -246,5 +249,14 @@ private void SaveAs()
model.SaveAs(dialog.FileName);
}
}
+
+ ///
+ /// Show the message in extra window
+ ///
+ /// The message
+ private void ShowMessage(object sender, string message)
+ {
+ MessageBox.Show(message);
+ }
}
}
\ No newline at end of file
diff --git a/src/WpfEditor/View/Templates/GeneralTemplate.xaml b/src/WpfEditor/View/Templates/GeneralTemplate.xaml
index ea6349ca..4942adf6 100644
--- a/src/WpfEditor/View/Templates/GeneralTemplate.xaml
+++ b/src/WpfEditor/View/Templates/GeneralTemplate.xaml
@@ -22,7 +22,7 @@