1 | using System;
|
---|
2 | using System.Collections.Generic;
|
---|
3 | using System.ComponentModel;
|
---|
4 | using System.Drawing;
|
---|
5 | namespace Netron.Diagramming.Core {
|
---|
6 | /// <summary>
|
---|
7 | /// This layout places nodes inside the visible area at a random location. The animation generated by this layout
|
---|
8 | /// allows you to see how nodes move from one location to another. Although it seems this layout does not
|
---|
9 | /// generate a clean organization is does help to perceive information in different perspectives and can be at times
|
---|
10 | /// really useful.
|
---|
11 | /// </summary>
|
---|
12 | class RandomLayout : LayoutBase {
|
---|
13 | #region Fields
|
---|
14 |
|
---|
15 | private const double speed = 0.1D;
|
---|
16 |
|
---|
17 | private Random rnd;
|
---|
18 | double vectorx;
|
---|
19 | double vectory;
|
---|
20 |
|
---|
21 | CollectionBase<IDiagramEntity> entities;
|
---|
22 | Dictionary<IDiagramEntity, SpeedVector> speeds;
|
---|
23 | int width;
|
---|
24 | int height;
|
---|
25 | int x, y;
|
---|
26 | int time;
|
---|
27 | BackgroundWorker worker;
|
---|
28 | #endregion
|
---|
29 |
|
---|
30 | #region Constructor
|
---|
31 | ///<summary>
|
---|
32 | ///Default constructor
|
---|
33 | ///</summary>
|
---|
34 | public RandomLayout(IController controller)
|
---|
35 | : base("Random layout", controller) {
|
---|
36 | }
|
---|
37 | #endregion
|
---|
38 |
|
---|
39 | #region Methods
|
---|
40 |
|
---|
41 |
|
---|
42 |
|
---|
43 | /// <summary>
|
---|
44 | /// Runs this instance.
|
---|
45 | /// </summary>
|
---|
46 | public override void Run() {
|
---|
47 | width = this.Bounds.Width;
|
---|
48 | height = this.Bounds.Height;
|
---|
49 | Run(DefaultRunSpan);
|
---|
50 |
|
---|
51 |
|
---|
52 | }
|
---|
53 | /// <summary>
|
---|
54 | /// Stops this instance.
|
---|
55 | /// </summary>
|
---|
56 | public override void Stop() {
|
---|
57 | if (worker != null && worker.IsBusy)
|
---|
58 | worker.CancelAsync();
|
---|
59 | }
|
---|
60 | /// <summary>
|
---|
61 | /// Runs the layout for a specified time.
|
---|
62 | /// </summary>
|
---|
63 | /// <param name="time">The time.</param>
|
---|
64 | public override void Run(int time) {
|
---|
65 | rnd = new Random();
|
---|
66 | entities = this.Model.CurrentPage.DefaultLayer.Entities;
|
---|
67 | speeds = new Dictionary<IDiagramEntity, SpeedVector>();
|
---|
68 | foreach (IDiagramEntity entity in entities) {
|
---|
69 |
|
---|
70 | if (entity is IShape) {
|
---|
71 | vectorx = -20 + 40 * rnd.NextDouble();
|
---|
72 | vectory = -20 + 40 * rnd.NextDouble();
|
---|
73 | speeds.Add(entity, new SpeedVector(vectorx, vectory));
|
---|
74 | }
|
---|
75 | }
|
---|
76 |
|
---|
77 | this.time = time;
|
---|
78 | worker = new BackgroundWorker();
|
---|
79 | worker.DoWork += new DoWorkEventHandler(worker_DoWork);
|
---|
80 | worker.RunWorkerAsync(time);
|
---|
81 |
|
---|
82 | }
|
---|
83 |
|
---|
84 | void worker_DoWork(object sender, DoWorkEventArgs e) {
|
---|
85 | DateTime start = DateTime.Now;
|
---|
86 | while (DateTime.Now < start.AddMilliseconds((int)e.Argument)) {
|
---|
87 | RunStep();
|
---|
88 | }
|
---|
89 |
|
---|
90 | }
|
---|
91 |
|
---|
92 | /// <summary>
|
---|
93 | /// Runs a single step.
|
---|
94 | /// </summary>
|
---|
95 | private void RunStep() {
|
---|
96 | lock (entities)
|
---|
97 | lock (speeds) {
|
---|
98 | foreach (IDiagramEntity entity in entities) {
|
---|
99 |
|
---|
100 | if (entity is IShape) {
|
---|
101 |
|
---|
102 | x = Convert.ToInt32(speed * speeds[entity].X);
|
---|
103 | y = Convert.ToInt32(speed * speeds[entity].Y);
|
---|
104 | if (entity.Rectangle.X + x < width - entity.Rectangle.Width - 10 && entity.Rectangle.X + x > 10 && entity.Rectangle.Y + y < height - entity.Rectangle.Height - 10 && entity.Rectangle.Y + y > 10)
|
---|
105 | entity.MoveBy(new Point(x, y));
|
---|
106 | }
|
---|
107 | }
|
---|
108 | }
|
---|
109 | }
|
---|
110 |
|
---|
111 |
|
---|
112 |
|
---|
113 | #endregion
|
---|
114 | }
|
---|
115 | }
|
---|