📄 lithiumcontrol.cs
字号:
int max = Shapes.Count-1;
if(max<0) return;
ShapeBase shape = Shapes[rnd.Next(0,max)];
shape.AddChild(newName);
DrawTree();
}
#endregion
#region New diagram
/// <summary>
/// Starts a new diagram and forgets about everything
/// You need to call the Save method before this if you wish to keep the current diagram.
/// </summary>
/// <param name="rootName">the text of the root in the new diagram</param>
public void NewDiagram(string rootName)
{
this.graphAbstract=new GraphAbstract();
this.AddRoot(rootName);
CenterRoot();
Invalidate();
}
/// <summary>
/// Starts a new diagram and forgets about everything
/// You need to call the Save method before this if you wish to keep the current diagram.
/// </summary>
public void NewDiagram()
{
this.graphAbstract = new GraphAbstract();
this.AddRoot(defaultRootName);
CenterRoot();
Invalidate();
}
#endregion
/// <summary>
/// Adds the root of the diagram to the canvas
/// </summary>
/// <param name="rootText"></param>
private ShapeBase AddRoot(string rootText)
{
if(Shapes.Count>0)
throw new Exception("You cannot set the root unless the diagram is empty");
SimpleRectangle root = new SimpleRectangle(this);
root.Location = new Point(Width/2+50,Height/2+50);
root.Width = 50;
root.Height = 25;
root.Text = rootText;
root.ShapeColor = Color.SteelBlue;
root.IsRoot = true;
root.Font = Font;
root.visible = false;
root.level = 0;
Fit(root);
//set the root of the diagram
this.graphAbstract.Root = root;
Shapes.Add(root);
return root;
}
/// <summary>
/// Centers the root on the control's canvas
/// </summary>
public void CenterRoot()
{
graphAbstract.Root.rectangle.Location = new Point(Width/2,Height/2);
//Invalidate();
DrawTree();
}
/// <summary>
/// Adds a shape to the canvas or diagram
/// </summary>
/// <param name="shape"></param>
public ShapeBase AddShape(ShapeBase shape)
{
Shapes.Add(shape);
shape.Site = this;
this.Invalidate();
return shape;
}
/// <summary>
/// Adds a predefined shape
/// </summary>
/// <param name="type"></param>
/// <param name="location"></param>
public ShapeBase AddShape(ShapeTypes type, Point location)
{
ShapeBase shape = null;
switch(type)
{
case ShapeTypes.Rectangular:
shape = new SimpleRectangle(this);
break;
case ShapeTypes.Oval:
shape = new OvalShape(this);
break;
case ShapeTypes.TextLabel:
shape = new TextLabel(this);
shape.Location = location;
shape.ShapeColor = Color.Transparent;
shape.Text = "A text label (change the text in the property grid)";
shape.Width = 350;
shape.Height = 30;
Shapes.Add(shape);
return shape;
}
if(shape==null) return null;
shape.ShapeColor = Color.FromArgb(rnd.Next(0,255),rnd.Next(0,255),rnd.Next(0,255));
shape.Location = location;
Shapes.Add(shape);
return shape;
}
/// <summary>
/// Move with the given vector
/// </summary>
/// <param name="p"></param>
public void MoveDiagram(Point p)
{
//move the whole diagram
foreach(ShapeBase shape in Shapes)
{
shape.Move(p);
Invalidate();
}
return;
}
#region Mouse event handlers
/// <summary>
/// Handles the mouse-down event
/// </summary>
/// <param name="e"></param>
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown (e);
Point p = new Point(e.X - this.AutoScrollPosition.X, e.Y - this.AutoScrollPosition.Y);
Rectangle r;
#region SHIFT
// if(Control.ModifierKeys==Keys.Shift)
// {
// globalMove = true;
// refp = p; //useful for all kind of things
// return;
// }
#endregion
ShapeBase sh ;
#region LMB & RMB
//test for shapes
for(int k=0; k<Shapes.Count; k++)
{
sh = Shapes[k];
if(sh.childNodes.Count>0)//has a [+/-]
{
if(layoutDirection==TreeDirection.Vertical)
r = new Rectangle(sh.Left + sh.Width/2 - 5, sh.Bottom, 10, 10);
else
r = new Rectangle(sh.Right, sh.Y + sh.Height/2-5, 10, 10);
if(r.Contains(p))
{
if(sh.expanded)
sh.Collapse(true);
else
sh.Expand();
DrawTree();
}
}
if(Shapes[k].Hit(p))
{
//shapes[k].ShapeColor = Color.WhiteSmoke;
if(selectedEntity!=null)
selectedEntity.IsSelected=false;
selectedEntity = Shapes[k];
selectedEntity.IsSelected = true;
sh = selectedEntity as ShapeBase;
#region CONTROL
// if(Control.ModifierKeys==Keys.Control && !sh.IsRoot)
// {
// tracking = true;
// //remove from parent
// sh.parentNode.childNodes.Remove(sh);
// Connections.Remove(sh, sh.parentNode);
// //...but keep the reference in case the user didn't find a new location
// memChild = sh;
// memParent = sh.parentNode;
// //now remove the reference
// sh.parentNode = null;
// }
#endregion
//set the point for the next round
refp=p;
#region Double-click
if(e.Button==MouseButtons.Left && e.Clicks==2)
{
if(sh.expanded)
sh.Collapse(true);
else
sh.Expand();
DrawTree();
}
#endregion
#region ALT
// if(Control.ModifierKeys==Keys.Alt)
// {
// sh.AddChild("New");
// DrawTree();
// }
#endregion
if(OnShowProps!=null)
OnShowProps(Shapes[k]);
return;
}
}
if(selectedEntity!=null) selectedEntity.IsSelected=false;
selectedEntity = null;
Invalidate();
refp = p; //useful for all kind of things
//nothing was selected but we'll show the props of the control in this case
if(OnShowProps!=null)
OnShowProps(this.proxy);
#endregion
}
/// <summary>
/// Handles the mouse-move event
/// </summary>
/// <param name="e"></param>
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove (e);
Point p = new Point(e.X - this.AutoScrollPosition.X, e.Y - this.AutoScrollPosition.Y);
//move the whole diagram
if(globalMove)
{
foreach(ShapeBase shape in Shapes)
{
shape.Move(new Point(p.X-refp.X,p.Y-refp.Y));
Invalidate();
}
refp=p;
return;
}
//move just one and its kids
if(tracking)
{
ShapeBase sh = selectedEntity as ShapeBase;
ResetPickup(); //forget about what happened before
Pickup(sh); //pickup the shape hanging underneath the shape to move next
foreach(ShapeBase shape in Shapes)
{
if(!shape.pickup) continue;
shape.Move(new Point(p.X-refp.X,p.Y-refp.Y));
Invalidate();
}
refp=p;
//try to find the new parent
SeekNewParent(sh);
Invalidate();
return;
}
//hovering stuff
for(int k=0; k<Shapes.Count; k++)
{
if(Shapes[k].Hit(p))
{
if(hoveredEntity!=null) hoveredEntity.hovered = false;
Shapes[k].hovered = true;
hoveredEntity = Shapes[k];
//hoveredEntity.Invalidate();
Invalidate();
return;
}
}
for(int k=0; k<Connections.Count; k++)
{
if(Connections[k].Hit(p))
{
if(hoveredEntity!=null) hoveredEntity.hovered = false;
Connections[k].hovered = true;
hoveredEntity = Connections[k];
hoveredEntity.Invalidate();
Invalidate();
return;
}
}
//reset the whole process if nothing happened above
HoverNone();
Invalidate();
}
/// <summary>
/// Handles the mouse-up event
/// </summary>
/// <param name="e"></param>
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp (e);
globalMove = false;
Connection con = null;
//test if we connected a connection
if(tracking)
{
tracking = false;
//make the volatile solid
if(neoCon!=null)
{
con = new Connection(neoCon.To, neoCon.From);
con.site = this;
Connections.Add(con);
//the From is the shape seeking a parent
neoCon.To.childNodes.Add(neoCon.From);
neoCon.From.parentNode = neoCon.To;
con.visible = true;
neoCon.To.Expand();
neoCon.From.connection = con;
}
else //the user hasn't released near anything, so reset to the original situation
{
con = new Connection(memChild, memParent);
con.site = this;
Connections.Add(con);
memParent.childNodes.Add(memChild);
memChild.parentNode = memParent;
con.visible = true;
memChild.connection = con;
}
//either case, restart the process next
neoCon = null;
memChild = null;
memParent = null;
DrawTree();
}
}
/// <summary>
/// Find a new parent for the given shape. This creates a new volatile connection which will be solidified
/// in the MouseUp handler.
/// </summary>
/// <param name="shape">the shape being moved around by the user</param>
private void SeekNewParent(ShapeBase shape)
{
/* this is the fast way but gives problems when the shape is surrounded by other shapes
* which makes it difficult to attach it to one you want
for(int k=0;k<Shapes.Count; k++)
{
if(Shapes[k]!=shape && Environment(Shapes[k],shape) && Shapes[k].parentNode!=shape && !Shapes[k].pickup)
{
neoCon = new Connection(shape, Shapes[k], Color.Red,2f);
neoCon.visible = true;
Invalidate();
return;
}
}
*/
double best = 10000d;
int chosen = -1;
double dist;
ShapeBase other;
for(int k=0;k<Shapes.Count; k++)
{
other = Shapes[k];
if(other!=shape && other.visible && other.parentNode!=shape && !other.pickup)
{
dist = Math.Sqrt((other.X-shape.X)*(other.X-shape.X)+(other.Y-shape.Y)*(other.Y-shape.Y));
if(dist<best && dist< 120)
chosen = k;
}
}
if(chosen>-1)
{
neoCon = new Connection(shape, Shapes[chosen], Color.Red,2f);
neoCon.visible = true;
neoCon.site = this;
return;
}
neoCon = null;
}
private bool Environment(ShapeBase shape1, ShapeBase shape2)
{
return Math.Sqrt((shape1.X-shape2.X)*(shape1.X-shape2.X)+(shape1.Y-shape2.Y)*(shape1.Y-shape2.Y))<100;
}
private void ResetPickup()
{
for(int k=0; k<Shapes.Count; k++)
Shapes[k].pickup = false;
}
private void Pickup(ShapeBase shape)
{
shape.pickup=true;
for(int k =0; k< shape.childNodes.Count; k++)
{
shape.childNodes[k].pickup = true;
if(shape.childNodes[k].childNodes.Count>0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -