Example #1
0
        public static void Failman(this Panel p, Vessel v)
        {
            // avoid corner-case when this is called in a lambda after scene changes
            v = FlightGlobals.FindVessel(v.id);

            // if vessel doesn't exist anymore, leave the panel empty
            if (v == null)
            {
                return;
            }

            // get data
            VesselData vd = v.KerbalismData();

            // if not a valid vessel, leave the panel empty
            if (!vd.IsSimulated)
            {
                return;
            }

            // set metadata
            p.Title(Lib.BuildString(Lib.Ellipsis(v.vesselName, Styles.ScaleStringLength(20)), " ", Lib.Color("Quality Management", Lib.Kolor.LightGrey)));
            p.Width(Styles.ScaleWidthFloat(355.0f));
            p.paneltype = Panel.PanelType.failures;

            string section = string.Empty;

            // get devices
            List <ReliabilityInfo> devices = vd.ReliabilityStatus();

            int deviceCount = 0;

            // for each device
            foreach (var ri in devices)
            {
                if (section != Group2Section(ri.group))
                {
                    section = Group2Section(ri.group);
                    p.AddSection(section);
                }

                string status = StatusString(ri);

                // render device entry
                p.AddContent(
                    label: ri.title,
                    value: status,
                    hover: () => Highlighter.Set(ri.partId, Color.blue));
                deviceCount++;
            }

            // no devices case
            if (deviceCount == 0)
            {
                p.AddContent("<i>no quality info</i>");
            }
        }
Example #2
0
        // set highlighting
        static void Highlight(Part p)
        {
            if (DB.Vessel(p.vessel).cfg_highlights)
            {
                // get state among all reliability components in the part
                bool broken   = false;
                bool critical = false;
                foreach (Reliability m in p.FindModulesImplementing <Reliability>())
                {
                    broken   |= m.broken;
                    critical |= m.critical;
                }

                if (broken)
                {
                    Highlighter.Set(p.flightID, !critical ? Color.yellow : Color.red);
                }
            }
        }
Example #3
0
        static void Render_sample(Panel p, uint partId, string filename, Sample sample, Drive drive, bool short_strings)
        {
            // get experiment info
            ExperimentInfo exp = Science.Experiment(filename);

            // render experiment name
            string exp_label = Lib.BuildString
                               (
                "<b>",
                Lib.Ellipsis(exp.name, Styles.ScaleStringLength(short_strings ? 24 : 38)),
                "</b> <size=", Styles.ScaleInteger(10).ToString(), ">",
                Lib.Ellipsis(ExperimentInfo.Situation(filename), Styles.ScaleStringLength((short_strings ? 32 : 62) - Lib.Ellipsis(exp.name, Styles.ScaleStringLength(short_strings ? 24 : 38)).Length)),
                "</size>"
                               );
            string exp_tooltip = Lib.BuildString
                                 (
                exp.name, "\n",
                "<color=#aaaaaa>", ExperimentInfo.Situation(filename), "</color>"
                                 );
            double exp_value = Science.Value(filename, sample.size);

            if (exp_value >= 0.1)
            {
                exp_tooltip = Lib.BuildString(exp_tooltip, "\n<b>", Lib.HumanReadableScience(exp_value), "</b>");
            }
            if (sample.mass > Double.Epsilon)
            {
                exp_tooltip = Lib.BuildString(exp_tooltip, "\n<b>", Lib.HumanReadableMass(sample.mass), "</b>");
            }

            p.AddContent(exp_label, Lib.HumanReadableSampleSize(sample.size), exp_tooltip, (Action)null, () => Highlighter.Set(partId, Color.cyan));
            p.AddIcon(sample.analyze ? Icons.lab_cyan : Icons.lab_black, "Flag the file for analysis in a <b>laboratory</b>", () => { sample.analyze = !sample.analyze; });
            p.AddIcon(Icons.toggle_red, "Dump the sample", () =>
            {
                Lib.Popup("Warning!",
                          Lib.BuildString("Do you really want to dump ", exp.FullName(filename), "?"),
                          new DialogGUIButton("Dump it", () => drive.samples.Remove(filename)),
                          new DialogGUIButton("Keep it", () => { }));
            }
                      );
        }
Example #4
0
        static void Render_file(Panel p, uint partId, string filename, File file, Drive drive, bool short_strings, Vessel v)
        {
            // get experiment info
            ExperimentInfo exp  = Science.Experiment(filename);
            double         rate = Cache.VesselInfo(v).connection.rate;

            // render experiment name
            string exp_label = Lib.BuildString
                               (
                "<b>",
                Lib.Ellipsis(exp.name, Styles.ScaleStringLength(short_strings ? 24 : 38)),
                "</b> <size=", Styles.ScaleInteger(10).ToString(), ">",
                Lib.Ellipsis(ExperimentInfo.Situation(filename), Styles.ScaleStringLength((short_strings ? 32 : 62) - Lib.Ellipsis(exp.name, Styles.ScaleStringLength(short_strings ? 24 : 38)).Length)),
                "</size>"
                               );
            string exp_tooltip = Lib.BuildString
                                 (
                exp.name, "\n",
                "<color=#aaaaaa>", ExperimentInfo.Situation(filename), "</color>"
                                 );
            double exp_value = Science.Value(filename, file.size);

            if (exp_value >= 0.1)
            {
                exp_tooltip = Lib.BuildString(exp_tooltip, "\n<b>", Lib.HumanReadableScience(exp_value), "</b>");
            }
            if (rate > 0)
            {
                exp_tooltip = Lib.BuildString(exp_tooltip, "\n<i>" + Lib.HumanReadableDuration(file.size / rate) + "</i>");
            }
            p.AddContent(exp_label, Lib.HumanReadableDataSize(file.size), exp_tooltip, (Action)null, () => Highlighter.Set(partId, Color.cyan));

            bool send = drive.GetFileSend(filename);

            p.AddIcon(send ? Icons.send_cyan : Icons.send_black, "Flag the file for transmission to <b>DSN</b>", () => { drive.Send(filename, !send); });
            p.AddIcon(Icons.toggle_red, "Delete the file", () =>
            {
                Lib.Popup("Warning!",
                          Lib.BuildString("Do you really want to delete ", exp.FullName(filename), "?"),
                          new DialogGUIButton("Delete it", () => drive.Delete_file(filename, double.MaxValue, v.protoVessel)),
                          new DialogGUIButton("Keep it", () => { }));
            }
                      );
        }
Example #5
0
        public static void Devman(this Panel p, Vessel v)
        {
            // avoid corner-case when this is called in a lambda after scene changes
            v = FlightGlobals.FindVessel(v.id);

            // if vessel doesn't exist anymore, leave the panel empty
            if (v == null)
            {
                return;
            }

            // get info from the cache
            Vessel_info vi = Cache.VesselInfo(v);

            // if not a valid vessel, leave the panel empty
            if (!vi.is_valid)
            {
                return;
            }

            // set metadata
            p.Title(Lib.BuildString(Lib.Ellipsis(v.vesselName, Styles.ScaleStringLength(20)), " <color=#cccccc>" + Localizer.Format("#KERBALISM_UI_devman") + "</color>"));
            p.Width(Styles.ScaleWidthFloat(355.0f));
            p.paneltype = Panel.PanelType.scripts;

            // time-out simulation
            if (!Lib.IsControlUnit(v) && p.Timeout(vi))
            {
                return;
            }

            // get devices
            Dictionary <uint, Device> devices = Computer.Boot(v);
            int deviceCount = 0;

            // direct control
            if (script_index == 0)
            {
                // draw section title and desc
                p.AddSection
                (
                    Localizer.Format("#KERBALISM_UI_devices"),
                    Description(),
                    () => p.Prev(ref script_index, (int)ScriptType.last),
                    () => p.Next(ref script_index, (int)ScriptType.last),
                    true
                );

                // for each device
                foreach (var pair in devices)
                {
                    // render device entry
                    Device dev = pair.Value;
                    if (!dev.IsVisible())
                    {
                        continue;
                    }
                    p.AddContent(dev.Name(), dev.Info(), string.Empty, dev.Toggle, () => Highlighter.Set(dev.Part(), Color.cyan));
                    deviceCount++;
                }
            }
            // script editor
            else
            {
                // get script
                ScriptType script_type = (ScriptType)script_index;
                string     script_name = script_type.ToString().Replace('_', ' ').ToUpper();
                Script     script      = DB.Vessel(v).computer.Get(script_type);

                // draw section title and desc
                p.AddSection
                (
                    script_name,
                    Description(),
                    () => p.Prev(ref script_index, (int)ScriptType.last),
                    () => p.Next(ref script_index, (int)ScriptType.last),
                    true
                );

                // for each device
                foreach (var pair in devices)
                {
                    Device dev = pair.Value;
                    if (!dev.IsVisible())
                    {
                        continue;
                    }

                    // determine tribool state
                    int state = !script.states.ContainsKey(pair.Key)
                                          ? -1
                                          : !script.states[pair.Key]
                                          ? 0
                                          : 1;

                    // render device entry
                    p.AddContent
                    (
                        dev.Name(),
                        state == -1 ? "<color=#999999>" + Localizer.Format("#KERBALISM_UI_dontcare") + " </color>" : state == 0 ? "<color=red>" + Localizer.Format("#KERBALISM_Generic_OFF") + "</color>" : "<color=cyan>" + Localizer.Format("#KERBALISM_Generic_ON") + "</color>",
                        string.Empty,
                        () =>
                    {
                        switch (state)
                        {
                        case -1: script.Set(dev, true); break;

                        case 0: script.Set(dev, null); break;

                        case 1: script.Set(dev, false); break;
                        }
                    },
                        () => Highlighter.Set(dev.Part(), Color.cyan)
                    );
                    deviceCount++;
                }
            }

            // no devices case
            if (deviceCount == 0)
            {
                p.AddContent("<i>no devices</i>");
            }
        }
Example #6
0
        static void Render_sample(Panel p, uint partId, Sample sample, Drive drive, bool short_strings)
        {
            // render experiment name
            string exp_label = Lib.BuildString
                               (
                "<b>",
                Lib.Ellipsis(sample.subjectData.ExperimentTitle, Styles.ScaleStringLength(short_strings ? 24 : 38)),
                "</b> <size=", Styles.ScaleInteger(10).ToString(), ">",
                Lib.Ellipsis(sample.subjectData.SituationTitle, Styles.ScaleStringLength((short_strings ? 32 : 62) - Lib.Ellipsis(sample.subjectData.ExperimentTitle, Styles.ScaleStringLength(short_strings ? 24 : 38)).Length)),
                "</size>"
                               );
            string exp_tooltip = Lib.BuildString
                                 (
                sample.subjectData.ExperimentTitle, "\n",
                Lib.Color(sample.subjectData.SituationTitle, Lib.Kolor.LightGrey)
                                 );

            double exp_value = sample.size * sample.subjectData.SciencePerMB;

            if (exp_value >= 0.1)
            {
                exp_tooltip = Lib.BuildString(exp_tooltip, "\n<b>", Lib.HumanReadableScience(exp_value, false), "</b>");
            }
            if (sample.mass > Double.Epsilon)
            {
                exp_tooltip = Lib.BuildString(exp_tooltip, "\n<b>", Lib.HumanReadableMass(sample.mass), "</b>");
            }
            if (!string.IsNullOrEmpty(sample.resultText))
            {
                exp_tooltip = Lib.BuildString(exp_tooltip, "\n", Lib.WordWrapAtLength(sample.resultText, 50));
            }

            p.AddContent(exp_label, Lib.HumanReadableSampleSize(sample.size), exp_tooltip, (Action)null, () => Highlighter.Set(partId, Color.cyan));
            p.AddRightIcon(sample.analyze ? Textures.lab_cyan : Textures.lab_black, Local.FILEMANAGER_analysis, () => { sample.analyze = !sample.analyze; }); //"Flag the file for analysis in a <b>laboratory</b>"
            p.AddRightIcon(Textures.toggle_red, Local.FILEMANAGER_Dumpsample, () =>                                                                           //"Dump the sample"
            {
                Lib.Popup(Local.FILEMANAGER_Warning_title,                                                                                                    //"Warning!"
                          Local.FILEMANAGER_DumpConfirm.Format(sample.subjectData.FullTitle),                                                                 //"Do you really want to dump <<1>>?",
                          new DialogGUIButton(Local.FILEMANAGER_DumpConfirm_button1, () => drive.Delete_sample(sample.subjectData)),                          //"Dump it"
                          new DialogGUIButton(Local.FILEMANAGER_DumpConfirm_button2, () => { }));                                                             //"Keep it"
            }
                           );
        }
Example #7
0
        static void Render_file(Panel p, uint partId, File file, Drive drive, bool short_strings, Vessel v)
        {
            // render experiment name
            string exp_label = Lib.BuildString
                               (
                "<b>",
                Lib.Ellipsis(file.subjectData.ExperimentTitle, Styles.ScaleStringLength(short_strings ? 24 : 38)),
                "</b> <size=", Styles.ScaleInteger(10).ToString(), ">",
                Lib.Ellipsis(file.subjectData.SituationTitle, Styles.ScaleStringLength((short_strings ? 32 : 62) - Lib.Ellipsis(file.subjectData.ExperimentTitle, Styles.ScaleStringLength(short_strings ? 24 : 38)).Length)),
                "</size>"
                               );
            string exp_tooltip = Lib.BuildString
                                 (
                file.subjectData.ExperimentTitle, "\n",
                Lib.Color(file.subjectData.SituationTitle, Lib.Kolor.LightGrey)
                                 );

            double exp_value = file.size * file.subjectData.SciencePerMB;

            if (file.subjectData.ScienceRemainingToRetrieve > 0f && file.size > 0.0)
            {
                exp_tooltip = Lib.BuildString(exp_tooltip, "\n<b>", Lib.HumanReadableScience(exp_value, false), "</b>");
            }
            if (file.transmitRate > 0.0)
            {
                if (file.size > 0.0)
                {
                    exp_tooltip = Lib.Color(Lib.BuildString(exp_tooltip, "\n", Local.FILEMANAGER_TransmittingRate.Format(Lib.HumanReadableDataRate(file.transmitRate)), " : <i>", Lib.HumanReadableCountdown(file.size / file.transmitRate), "</i>"), Lib.Kolor.Cyan);                    //Transmitting at <<1>>
                }
                else
                {
                    exp_tooltip = Lib.Color(Lib.BuildString(exp_tooltip, "\n", Local.FILEMANAGER_TransmittingRate.Format(Lib.HumanReadableDataRate(file.transmitRate))), Lib.Kolor.Cyan);                    //Transmitting at <<1>>
                }
            }
            else if (v.KerbalismData().Connection.rate > 0.0)
            {
                exp_tooltip = Lib.BuildString(exp_tooltip, "\n", Local.FILEMANAGER_Transmitduration, "<i>", Lib.HumanReadableDuration(file.size / v.KerbalismData().Connection.rate), "</i>");                //Transmit duration :
            }
            if (!string.IsNullOrEmpty(file.resultText))
            {
                exp_tooltip = Lib.BuildString(exp_tooltip, "\n", Lib.WordWrapAtLength(file.resultText, 50));
            }

            string size;

            if (file.transmitRate > 0.0)
            {
                if (file.size == 0.0)
                {
                    size = Lib.Color(Lib.BuildString("↑ ", Lib.HumanReadableDataRate(file.transmitRate)), Lib.Kolor.Cyan);
                }
                else
                {
                    size = Lib.Color(Lib.BuildString("↑ ", Lib.HumanReadableDataSize(file.size)), Lib.Kolor.Cyan);
                }
            }
            else
            {
                size = Lib.HumanReadableDataSize(file.size);
            }

            p.AddContent(exp_label, size, exp_tooltip, (Action)null, () => Highlighter.Set(partId, Color.cyan));

            bool send = drive.GetFileSend(file.subjectData.Id);

            p.AddRightIcon(send ? Textures.send_cyan : Textures.send_black, Local.FILEMANAGER_send, () => { drive.Send(file.subjectData.Id, !send); }); //"Flag the file for transmission to <b>DSN</b>"
            p.AddRightIcon(Textures.toggle_red, Local.FILEMANAGER_Delete, () =>                                                                         //"Delete the file"
            {
                Lib.Popup(Local.FILEMANAGER_Warning_title,                                                                                              //"Warning!"
                          Local.FILEMANAGER_DeleteConfirm.Format(file.subjectData.FullTitle),                                                           //Lib.BuildString(, "?"),//"Do you really want to delete <<1>>",
                          new DialogGUIButton(Local.FILEMANAGER_DeleteConfirm_button1, () => drive.Delete_file(file.subjectData)),                      //"Delete it"
                          new DialogGUIButton(Local.FILEMANAGER_DeleteConfirm_button2, () => { }));                                                     //"Keep it"
            }
                           );
        }
Example #8
0
        public static void Devman(this Panel p, Vessel v)
        {
            // avoid corner-case when this is called in a lambda after scene changes
            v = FlightGlobals.FindVessel(v.id);

            // if vessel doesn't exist anymore, leave the panel empty
            if (v == null)
            {
                return;
            }

            // get data
            VesselData vd = v.KerbalismData();

            // if not a valid vessel, leave the panel empty
            if (!vd.IsSimulated)
            {
                return;
            }

            // set metadata
            p.Title(Lib.BuildString(Lib.Ellipsis(v.vesselName, Styles.ScaleStringLength(20)), Lib.Color("#KERBALISM_UI_devman", Lib.Kolor.LightGrey)));
            p.Width(Styles.ScaleWidthFloat(355.0f));
            p.paneltype = Panel.PanelType.scripts;

            // time-out simulation
            if (!Lib.IsControlUnit(v) && p.Timeout(vd))
            {
                return;
            }

            // get devices
            List <Device> devices     = Computer.GetModuleDevices(v);
            int           deviceCount = 0;

            // direct control
            if (script_index == 0)
            {
                // draw section title and desc
                p.AddSection
                (
                    Localizer.Format("#KERBALISM_UI_devices"),
                    Description(),
                    () => p.Prev(ref script_index, (int)ScriptType.last),
                    () => p.Next(ref script_index, (int)ScriptType.last),
                    false
                );

                bool hasVesselDeviceSection = false;
                bool hasModuleDeviceSection = false;

                // for each device
                for (int i = devices.Count - 1; i >= 0; i--)
                {
                    Device dev = devices[i];

                    dev.OnUpdate();
                    if (!dev.IsVisible)
                    {
                        continue;
                    }

                    // create vessel device section if necessary
                    if (dev is VesselDevice)
                    {
                        if (!hasVesselDeviceSection)
                        {
                            p.AddSection("VESSEL DEVICES");
                            hasVesselDeviceSection = true;
                        }
                    }
                    // create module device section if necessary
                    else
                    {
                        if (!hasModuleDeviceSection)
                        {
                            p.AddSection("MODULE DEVICES");
                            hasModuleDeviceSection = true;
                        }
                    }

                    if (dev.PartId != 0u)
                    {
                        p.AddContent(dev.DisplayName, dev.Status, dev.Tooltip, dev.Toggle, () => Highlighter.Set(dev.PartId, Color.cyan));
                    }
                    else
                    {
                        p.AddContent(dev.DisplayName, dev.Status, dev.Tooltip, dev.Toggle);
                    }

                    if (dev.Icon != null)
                    {
                        p.SetLeftIcon(dev.Icon.texture, dev.Icon.tooltip, dev.Icon.onClick);
                    }

                    deviceCount++;
                }
            }
            // script editor
            else
            {
                // get script
                ScriptType script_type = (ScriptType)script_index;
                string     script_name = script_type.ToString().Replace('_', ' ').ToUpper();
                Script     script      = v.KerbalismData().computer.Get(script_type);

                // draw section title and desc
                p.AddSection
                (
                    script_name,
                    Description(),
                    () => p.Prev(ref script_index, (int)ScriptType.last),
                    () => p.Next(ref script_index, (int)ScriptType.last)
                );

                bool hasVesselDeviceSection = false;
                bool hasModuleDeviceSection = false;

                // for each device
                for (int i = devices.Count - 1; i >= 0; i--)
                {
                    Device dev = devices[i];

                    dev.OnUpdate();
                    if (!dev.IsVisible)
                    {
                        continue;
                    }

                    // determine tribool state
                    int state = !script.states.ContainsKey(dev.Id)
                                          ? -1
                                          : !script.states[dev.Id]
                                          ? 0
                                          : 1;

                    // create vessel device section if necessary
                    if (dev is VesselDevice)
                    {
                        if (!hasVesselDeviceSection)
                        {
                            p.AddSection("VESSEL DEVICES");
                            hasVesselDeviceSection = true;
                        }
                    }
                    // create module device section if necessary
                    else
                    {
                        if (!hasModuleDeviceSection)
                        {
                            p.AddSection("MODULE DEVICES");
                            hasModuleDeviceSection = true;
                        }
                    }

                    // render device entry
                    p.AddContent
                    (
                        dev.DisplayName,
                        state == -1 ? Lib.Color(Localizer.Format("#KERBALISM_UI_dontcare"), Lib.Kolor.DarkGrey) : Lib.Color(state == 0, Localizer.Format("#KERBALISM_Generic_OFF"), Lib.Kolor.Yellow, Localizer.Format("#KERBALISM_Generic_ON"), Lib.Kolor.Green),
                        string.Empty,
                        () =>
                    {
                        switch (state)
                        {
                        case -1: script.Set(dev, true); break;

                        case 0: script.Set(dev, null); break;

                        case 1: script.Set(dev, false); break;
                        }
                    },
                        () => Highlighter.Set(dev.PartId, Color.cyan)
                    );
                    deviceCount++;
                }
            }

            // no devices case
            if (deviceCount == 0)
            {
                p.AddContent("<i>no devices</i>");
            }
        }
        public static void DevMan(this Panel p, Vessel v)
        {
            // avoid corner-case when this is called in a lambda after scene changes
            v = FlightGlobals.FindVessel(v.id);

            // if vessel doesn't exist anymore, leave the panel empty
            if (v == null)
            {
                return;
            }

            // get info from the cache
            Vessel_Info vi = Cache.VesselInfo(v);

            // if not a valid vessel, leave the panel empty
            if (!vi.is_valid)
            {
                return;
            }

            // set metadata
            p.Title(Lib.BuildString(Lib.Ellipsis(v.vesselName, 24), " <color=#cccccc>DEV MANAGER</color>"));

            // time-out simulation
            if (p.Timeout(vi))
            {
                return;
            }

            // get devices
            Dictionary <uint, Device> devices = Computer.Boot(v);

            // direct control
            if (script_index == 0)
            {
                // draw section title and desc
                p.SetSection
                (
                    "DEVICES",
                    Description(),
                    () => p.Prev(ref script_index, (int)ScriptType.last),
                    () => p.Next(ref script_index, (int)ScriptType.last)
                );

                // for each device
                foreach (var pair in devices)
                {
                    // render device entry
                    Device dev = pair.Value;
                    p.SetContent(dev.Name(), dev.Info(), string.Empty, dev.Toggle, () => Highlighter.Set(dev.Part(), Color.cyan));
                }
            }
            // script editor
            else
            {
                // get script
                ScriptType script_type = (ScriptType)script_index;
                string     script_name = script_type.ToString().Replace('_', ' ').ToUpper();
                Script     script      = DB.Vessel(v).computer.Get(script_type);

                // draw section title and desc
                p.SetSection
                (
                    script_name,
                    Description(),
                    () => p.Prev(ref script_index, (int)ScriptType.last),
                    () => p.Next(ref script_index, (int)ScriptType.last)
                );

                // for each device
                foreach (var pair in devices)
                {
                    // determine tribool state
                    int state = !script.states.ContainsKey(pair.Key)
            ? -1
            : !script.states[pair.Key]
            ? 0
            : 1;

                    // render device entry
                    Device dev = pair.Value;
                    p.SetContent
                    (
                        dev.Name(),
                        state == -1 ? "<color=#999999>don't care</color>" : state == 0 ? "<color=red>off</color>" : "<color=cyan>on</color>",
                        string.Empty,
                        () =>
                    {
                        switch (state)
                        {
                        case -1: script.Set(dev, true);  break;

                        case  0: script.Set(dev, null);  break;

                        case  1: script.Set(dev, false); break;
                        }
                    },
                        () => Highlighter.Set(dev.Part(), Color.cyan)
                    );
                }
            }

            // no devices case
            if (devices.Count == 0)
            {
                p.SetContent("<i>no devices</i>");
            }
        }
        public static void NetMan(this Panel p, Vessel v)
        {
            // avoid corner-case when this is called in a lambda after scene changes
            v = FlightGlobals.FindVessel(v.id);

            // if vessel doesn't exist anymore, leave the panel empty
            if (v == null)
            {
                return;
            }

            // get info from the cache
            Vessel_Info vi = Cache.VesselInfo(v);

            // if not a valid vessel, leave the panel empty
            if (!vi.is_valid)
            {
                return;
            }

            // set metadata
            p.Title(Lib.BuildString(Lib.Ellipsis(v.vesselName, 20), " <color=#cccccc>NETWORK INFO</color>"));

            // time-out simulation
#if !DEBUG
            if (p.Timeout(vi))
            {
                return;
            }
#endif

            p.SetSection("ADAPTORS");
            p.Set_IsFreqSelector(true);

            // store all devices
            var devices = new Dictionary <uint, NetDevice>();

            // store device being added
            NetDevice adap;

            // loaded vessel
            if (v.loaded)
            {
                foreach (NetworkAdaptor m in Lib.FindModules <NetworkAdaptor>(v))
                {
                    adap = new NetAdaptorDevice(m);

                    // add the device
                    // - multiple same-type components in the same part will have the same id, and are ignored
                    if (!devices.ContainsKey(adap.Id()))
                    {
                        devices.Add(adap.Id(), adap);
                    }
                }
            }
            else
            {
                // store data required to support multiple modules of same type in a part
                var PD = new Dictionary <string, Lib.module_prefab_data>();

                // for each part
                foreach (ProtoPartSnapshot proto in v.protoVessel.protoPartSnapshots)
                {
                    // get part prefab (required for module properties)
                    Part part_prefab = PartLoader.getPartInfoByName(proto.partName).partPrefab;

                    // get all module prefabs
                    var module_prefabs = part_prefab.FindModulesImplementing <PartModule>();

                    // clear module indexes
                    PD.Clear();

                    // for each module
                    foreach (ProtoPartModuleSnapshot m in proto.modules)
                    {
                        // get the module prefab
                        // if the prefab doesn't contain this module, skip it
                        PartModule module_prefab = Lib.ModulePrefab(module_prefabs, m.moduleName, PD);
                        if (!module_prefab)
                        {
                            continue;
                        }

                        // if the module is disabled, skip it
                        // note: this must be done after ModulePrefab is called, so that indexes are right
                        if (!Lib.Proto.GetBool(m, "isEnabled"))
                        {
                            continue;
                        }

                        if (m.moduleName == "NetworkAdaptor")
                        {
                            adap = new ProtoNetAdaptorDevice(m, proto.flightID, v);

                            // add the device
                            // - multiple same-type components in the same part will have the same id, and are ignored
                            if (!devices.ContainsKey(adap.Id()))
                            {
                                devices.Add(adap.Id(), adap);
                            }
                        }
                    }
                }
            }

            // dict order by device name
            // for each device
            foreach (var pair in devices.OrderBy(x => x.Value.Name()))
            {
                // render device entry
                NetDevice dev = pair.Value;
                // Get how many antennas share the same freq
                AntennasByFrequency x = null;
                if (vi.antenna.antennasByFreq.ContainsKey(dev.InfoFreq()))
                {
                    x = vi.antenna.antennasByFreq[dev.InfoFreq()];
                }

                p.SetContent(dev.Name(), dev.InfoRate(), string.Empty, null, () => Highlighter.Set(dev.Part(), Color.cyan), dev.InfoFreq());
                p.SetIcon(Icons.left_freq, "Decrease", () =>
                {
                    if (dev.InfoFreq() > 0) // && x != null
                    {
                        //if (x.antCount == 1 && x.countConnections > 0)
                        //{
                        //  Lib.Popup(
                        //    "Warning!",
                        //    Lib.BuildString("This is the last antenna on '", dev.InfoFreq().ToString(),
                        //                    "' frequency.\nYou will lost connection in this frequency.\nDo you really want to remove this frequency from this vessel?"),
                        //    new DialogGUIButton("Remove", () => dev.ChangeFreq(-1)),
                        //    new DialogGUIButton("Keep it", () => { }));
                        //}
                        //else
                        dev.ChangeFreq(-1);
                    }
                });
                p.SetIcon(Icons.right_freq, "Increase", () =>
                {
                    if (dev.InfoFreq() < 99) // && x != null
                    {
                        //if (x.antCount == 1 && x.countConnections > 0)
                        //{
                        //  Lib.Popup(
                        //    "Warning!",
                        //    Lib.BuildString("This is the last antenna on '", dev.InfoFreq().ToString(),
                        //                    "' frequency.\nYou will lost connection in this frequency.\nDo you really want to remove this frequency from this vessel?"),
                        //    new DialogGUIButton("Remove", () => dev.ChangeFreq(+1)),
                        //    new DialogGUIButton("Keep it", () => { }));
                        //}
                        //else
                        dev.ChangeFreq(+1);
                    }
                });
            }

            p.SetSection("FREQUENCY(S) DETAIL");
            foreach (short key in vi.antenna.antennasByFreq.Keys)
            {
                double range = vi.antenna.antennasByFreq[key].antennaPower;
                double rate  = vi.antenna.antennasByFreq[key].antennaRate;

                Render_ConnectionDetail(p, range, rate, key);
            }
        }