private void BeforeTreeViewExpand(object sender, TreeViewCancelEventArgs args)
        {
            performanceTreeView.BeginUpdate();

            TreeNode node = args.Node;

            if (node.Nodes.Count == 0 || "replace me".Equals(node.Nodes[0].Tag))
            {
                node.Nodes.Clear();

                if (node.Tag is Performance.Group)
                {
                    Performance.Group group = (Performance.Group)node.Tag;
                    for (int i = 0; i < group.Files.Count; i++)
                    {
                        TreeNode fileNode = args.Node.Nodes.Add("Datei " + (i + 1) + ": " + Units.FormatTime(group.Files[i].Time(true, true)));
                        fileNode.Tag = group.Files[i];
                        fileNode.Nodes.Add("Loading...").Tag = "replace me";
                    }
                }
                else if (node.Tag is Performance.File)
                {
                    Performance.File file = (Performance.File)node.Tag;
                    for (int i = 0; i < file.Chunks.Count; i++)
                    {
                        TreeNode chunkNode = node.Nodes.Add("Chunk " + (i + 1) + ": " + Units.FormatTime(file.Chunks[i].Time));
                        chunkNode.Tag = file.Chunks[i];
                    }
                }
            }

            performanceTreeView.EndUpdate();
        }
        public void SelectGroup(Performance.Group group)
        {
            TreeNode node = performanceTreeView.Nodes.OfType <TreeNode>().First(n => n.Tag == group);

            if (node != null)
            {
                performanceTreeView.SelectedNode = node;
            }
        }
        private void UpdateInfo(Performance.Group group)
        {
            string[] details =
            {
                "Gesamtdauer: " + Units.FormatTime(group.Time(true,                                                                                   true)),
                "Größe: " + Units.FormatSize(group.TotalSize) + " (" + group.FileCount + " Dateien mit je " + Units.FormatSize(group.FileSize) + ")",
                "",
                "Übertragungsrate: " + Units.FormatRate(group.TransmissionRate(true,                                                                  true)),
                "... ohne Verzögerung vor Stream: " + Units.FormatRate(group.TransmissionRate(false,                                                  true)),
                "... ohne Verzögerung nach Stream: " + Units.FormatRate(group.TransmissionRate(true,                                                  false)),
                "... ohne Verzögerungen: " + Units.FormatRate(group.TransmissionRate(false,                                                           false))
            };
            detailsTextBox.Text = string.Join("\r\n", details);

            performanceGraphView.CreateGraph(group);
        }
        public void CreateGraph(Performance.Group group)
        {
            ulong totalTime   = group.Time(true, true);
            ulong totalSize   = group.TotalSize;
            ulong currentTime = 0;
            ulong currentSize = 0;

            PointF[] points     = new PointF[group.FileCount + 1];
            int      pointIndex = 0;

            points[pointIndex++] = new PointF(0, 0);

            foreach (Performance.File file in group.Files)
            {
                currentTime += file.Time(true, true);
                currentSize += file.FileSize;

                points[pointIndex++] = new PointF(currentTime, currentSize);
            }

            Axis axisX = new Axis()
            {
                Range  = new Range(0, totalTime),
                Label  = "Zeit",
                Format = (f) => "" + Units.FormatTime((ulong)f)
            };

            Axis axisY = new Axis()
            {
                Range  = new Range(0, totalSize),
                Label  = "Größe",
                Format = (f) => Units.FormatSize(f)
            };

            graph = new Graph()
            {
                Points = points, AxisX = axisX, AxisY = axisY
            };
            Refresh();
        }