private void UpdateNode(Node node, Network network) { try { lock (network) { if (debug) { Console.Out.WriteLine("*** Updating node {0} from network {1}.", node.NickName, network.NetworkName); } Hashtable node2nodegroup = network.Properties["node2nodegroup"] as Hashtable; if (!node2nodegroup.ContainsKey(node)) { throw new Exception("Unable to modify node: could not find the nodegroup which contains the specified node: " + node.NickName); } NodeGroup ng = node2nodegroup[node] as NodeGroup; PointD position = ng.Position; DeleteNode(node, network); AddNode(node, network, position); if (debug) { Console.Out.WriteLine("### Node update complete for node {0} from network {1}.", node.NickName, network.NetworkName); } } } catch (Exception ex) { OnError(ex); } }
public ZoomableNetworkMap() { noticeIcon = Gui.LoadIcon(24, "dialog-information"); rng = new Random(); networkZOrder = ArrayList.Synchronized(new ArrayList()); selectedGroup = null; nodeDragging = false; nodeDraggingLastX = 0; nodeDraggingLastY = 0; Runtime.Core.NetworkAdded += (NetworkEventHandler)DispatchService.GuiDispatch(new NetworkEventHandler(AddNetwork)); Runtime.Core.NetworkRemoved += (NetworkEventHandler)DispatchService.GuiDispatch(new NetworkEventHandler(DeleteNetwork)); foreach (Network network in Runtime.Core.Networks) { AddNetwork(network); } base.ButtonPressEvent += base_ButtonPressEvent; base.ButtonReleaseEvent += base_ButtonReleaseEvent; base.MotionNotifyEvent += base_MotionNotifyEvent; this.render = DrawContents; this.overlay = DrawOverlay; this.QueueDraw(); }
private SizeD CalculateNodeGroupTitleTextSize(NodeGroup ng, Cairo.Context gc) { Pango.Layout layout = new Pango.Layout(this.PangoContext); layout.FontDescription = this.PangoContext.FontDescription.Copy(); layout.FontDescription.Size = Pango.Units.FromDouble(NodegroupNameFontSize); layout.SetText(ng.Name); Gdk.Size size = GetTextSize(layout); return(new SizeD(size.Width, size.Height)); }
private SizeD CalculateNodeGroupSize(NodeGroup ng, Cairo.Context gc) { var titleTextSize = CalculateNodeGroupTitleTextSize(ng, gc); var titleTextHeight = titleTextSize.Height + (Padding * 2.0); var heightNodeCount = (ng.Nodes.Count < 3) ? 1 : ng.Nodes.Count; var width = Math.Max(titleTextSize.Width + (Padding * 2.0), (ng.Nodes.Count * AvatarDimension) + (Padding * 2.0) + (Padding * ng.Nodes.Count)); var height = (heightNodeCount * AvatarDimension) + titleTextHeight + (Padding * 2.0) + (Padding * heightNodeCount); return(new SizeD(width, height)); }
private void DeleteNode(Node node, Network network) { lock (network) { if (debug) { Console.Out.WriteLine("*** Deleting node {0} from network {1}.", node.NickName, network.NetworkName); } Hashtable nodegroups = network.Properties["nodegroups"] as Hashtable; Hashtable node2nodegroup = network.Properties["node2nodegroup"] as Hashtable; //string nodeIP = (node.ExternalIP == string.Empty) ? node.NickName : node.ExternalIP; if (!node2nodegroup.ContainsKey(node)) { throw new Exception("Unable to delete node: could not find the nodegroup which contains the specified node: " + node.NickName); } NodeGroup ng = node2nodegroup[node] as NodeGroup; if (debug) { Console.Out.WriteLine(" -> Found node {0} in nodegroup {1} / network {2}.", node.NickName, ng.Name, network.NetworkName); } ng.Nodes.Remove(node); node2nodegroup.Remove(node); if (debug) { Console.Out.WriteLine(" -> Deleted node {0} in nodegroup {1} / network {2}.", node.NickName, ng.Name, network.NetworkName); } // If nodegroup is empty, delete that too. if (ng.Nodes.Count == 0) { if (debug) { Console.Out.WriteLine(" -> Nodegroup {0} / network {1} empty, deleting.", ng.Name, network.NetworkName); } nodegroups.Remove(ng.Name); if (debug) { Console.Out.WriteLine(" -> Nodegroup {0} / network {1} deleted.", ng.Name, network.NetworkName); } } } }
private void AddNode(Node node, Network network, PointD position) { lock (network) { if (debug) { Console.Out.WriteLine("*** Adding node {0} to network {1}...", node.NickName, network.NetworkName); } Hashtable nodegroups = network.Properties["nodegroups"] as Hashtable; Hashtable node2nodegroup = network.Properties["node2nodegroup"] as Hashtable; IPAddress address = GetExternalIPv4Address(node); string nodeIP = (address.Equals(IPAddress.None)) ? node.NickName : address.ToString(); if (nodegroups.ContainsKey(nodeIP)) { NodeGroup ng = nodegroups[nodeIP] as NodeGroup; ng.Nodes.Add(node); node2nodegroup.Add(node, ng); if (debug) { Console.Out.WriteLine(" -> Added node {0} to network {1} / nodegroup {2}", node.NickName, network.NetworkName, ng.Name); } } else { NodeGroup ng = new NodeGroup(nodeIP, position); ng.Nodes.Add(node); node2nodegroup.Add(node, ng); nodegroups.Add(nodeIP, ng); if (debug) { Console.Out.WriteLine(" -> Added node {0} to network {1} / new nodegroup {2}", node.NickName, network.NetworkName, ng.Name); } } } }
private void RenderNodeGroup(NodeGroup ng, Network network, Cairo.Context gc) { gc.Save(); SizeD size = CalculateNodeGroupSize(ng, gc); ng.Dimension = size; CreateRoundedRectPath(gc, ng.Position.X, ng.Position.Y, size.Width, size.Height, 20); gc.Color = new Cairo.Color(0, 0, 0, 0.5); gc.FillPreserve(); if (selectedGroup == ng) { gc.Save(); gc.Color = orangeOverlay; gc.StrokePreserve(); gc.Restore(); } var titleTextSize = CalculateNodeGroupTitleTextSize(ng, gc); var titleSize = new SizeD(size.Width, titleTextSize.Height + (Padding * 2.0)); gc.Clip(); gc.Rectangle(ng.Position.X, ng.Position.Y, titleSize.Width, titleSize.Height); gc.Fill(); gc.ResetClip(); gc.Color = lightGray; double hostTextX = ng.Position.X + (titleSize.Width / 2.0) - (titleTextSize.Width / 2.0); double hostTextY = ng.Position.Y + (titleSize.Height / 2.0) - (titleTextSize.Height / 2.0); gc.MoveTo(hostTextX, hostTextY /* + titleTextSize.Height */); Pango.Layout layout = new Pango.Layout(this.PangoContext); layout.FontDescription = this.PangoContext.FontDescription.Copy(); layout.FontDescription.Size = Pango.Units.FromDouble(NodegroupNameFontSize); layout.SetText(ng.Name); Pango.CairoHelper.ShowLayout(gc, layout); SizeD nodesSize = CalculateNodeGroupSize(ng, gc); if (ng.Nodes.Count == 1) { double positionY = ng.Position.Y + titleSize.Height + Padding; double positionX = ng.Position.X + (ng.Dimension.Width / 2.0) - HalfAvatarDimension; RenderNode(gc, (Node)ng.Nodes[0], positionX, positionY); } else if (ng.Nodes.Count == 2) { // position them side-by-side, separated by (padding) number of pixels, centered in the // space. double positionY = ng.Position.Y + titleSize.Height + Padding; double position1X = ng.Position.X + (ng.Dimension.Width / 2.0) - (Padding / 2.0) - AvatarDimension; double position2X = position1X + Padding + AvatarDimension; RenderNode(gc, (Node)ng.Nodes[0], position1X, positionY); RenderNode(gc, (Node)ng.Nodes[1], position2X, positionY); } else { double deg = 0; double x = 0; double y = 0; var contentY = ng.Position.Y + titleSize.Height; var contentHeight = size.Height - titleSize.Height; var middle = new System.Drawing.Point(Convert.ToInt32(ng.Position.X + size.Width - (size.Width / 2.0)), Convert.ToInt32(contentY + contentHeight - (contentHeight / 2.0))); int nodeSize = Convert.ToInt32(AvatarDimension); for (int i = 0; i < ng.Nodes.Count; i++) { x = Math.Sin(deg) * ((size.Width / 2.0) - (nodeSize)) + middle.X - (nodeSize / 2.0); y = Math.Cos(deg) * ((contentHeight / 2.0) - (nodeSize)) + middle.Y - (nodeSize / 2.0); RenderNode(gc, (Node)ng.Nodes[i], x, y); deg += Math.PI / (ng.Nodes.Count / 2.0); } } gc.Restore(); }
private void base_ButtonPressEvent(object sender, Gtk.ButtonPressEventArgs args) { Gdk.EventButton eb = args.Event; double mouseX = eb.X; double mouseY = eb.Y; DeviceToUser(ref mouseX, ref mouseY); if (debug) { Console.Out.WriteLine("Button Pressed {0}: user coords {1},{2}", eb.Button, mouseX, mouseY); } PointD thePoint = new PointD(mouseX, mouseY); NodeGroup firstNodeGroupHit = null; Node firstNodeHit = null; foreach (Network network in networkZOrder) { Rectangle networkRect = (Rectangle)network.Properties["rect"]; if (Inside(thePoint, networkRect)) { if (debug) { Console.Out.WriteLine("Click inside network {0}", network.NetworkName); } Hashtable nodegroups = (Hashtable)network.Properties["nodegroups"]; foreach (NodeGroup ng in nodegroups.Values) { //PointD ngPosition = new PointD (ng.Position.X + networkRect.X, // ng.Position.Y + networkRect.Y); if (Inside(thePoint, ng.Position, ng.Dimension)) { if (debug) { Console.Out.WriteLine("Click inside group {0}", ng.Name); } firstNodeGroupHit = ng; foreach (Node n in ng.Nodes) { PointD np = (PointD)n.Properties["position"]; // np = new PointD (np.X + ngPosition.X, // np.Y + ngPosition.Y); if (Inside(thePoint, np, AvatarSizeD)) { firstNodeHit = n; if (debug) { Console.Out.WriteLine("Click inside node {0}", n); } break; // clicked node n } } break; // click in ng but not any node } } break; // click in network but not any ng } } if (eb.Button == 1 | eb.Button == 3) { selectedNode = firstNodeHit; if (SelectedNodeChanged != null) { SelectedNodeChanged(selectedNode); } } switch (eb.Button) { case 1: selectedGroup = firstNodeGroupHit; if (selectedGroup != null) { this.nodeDragging = true; nodeDraggingLastX = eb.X; nodeDraggingLastY = eb.Y; // we're dragging... this.GdkWindow.Cursor = new Gdk.Cursor(Gdk.CursorType.Plus); } if (selectedNode != null) { if (eb.Type == Gdk.EventType.TwoButtonPress) { ResetDrag(); if (NodeDoubleClicked != null) { NodeDoubleClicked(selectedNode); } } } break; case 3: if (firstNodeGroupHit == null) { // clicked on map background Menu mapMenu = (Menu)Runtime.UIManager.GetWidget("/MapPopupMenu"); mapMenu.Popup(); } else { if (firstNodeHit != null) { UserMenu userMenu = new UserMenu(firstNodeHit.Network, firstNodeHit); userMenu.Popup(); } } break; } }