private void BackgroundInit()
        {
            StarScan.LoadBodyDesignationMap();
            MaterialCommodityDB.SetUpInitialTable();

            if (!EDDOptions.Instance.NoSystemsLoad)
            {
                downloadMapsTask = FGEImage.DownloadMaps(this, () => PendingClose, LogLine, LogLineHighlight);
                CheckSystems(() => PendingClose, (p, s) => ReportProgress(p, s));
            }

            SystemNoteClass.GetAllSystemNotes();                                // fill up memory with notes, bookmarks, galactic mapping
            BookmarkClass.GetAllBookmarks();

            ReportProgress(-1, "");
            InvokeAsyncOnUiThread(() => OnInitialSyncComplete?.Invoke());

            if (PendingClose)
            {
                return;
            }

            if (EliteDangerousCore.EDDN.EDDNClass.CheckforEDMC()) // EDMC is running
            {
                if (EDCommander.Current.SyncToEddn)               // Both EDD and EDMC should not sync to EDDN.
                {
                    LogLineHighlight("EDDiscovery and EDMarketConnector should not both sync to EDDN. Stop EDMC or uncheck 'send to EDDN' in settings tab!");
                }
            }

            if (PendingClose)
            {
                return;
            }
            LogLine("Reading travel history");

            if (!EDDOptions.Instance.NoLoad)
            {
                DoRefreshHistory(new RefreshWorkerArgs {
                    CurrentCommander = EDCommander.CurrentCmdrID
                });
            }

            if (PendingClose)
            {
                return;
            }

            if (syncstate.performeddbsync || syncstate.performedsmsync)
            {
                string databases = (syncstate.performedsmsync && syncstate.performeddbsync) ? "EDSM and EDDB" : ((syncstate.performedsmsync) ? "EDSM" : "EDDB");

                LogLine("ED Discovery will now synchronise to the " + databases + " databases to obtain star information." + Environment.NewLine +
                        "This will take a while, up to 15 minutes, please be patient." + Environment.NewLine +
                        "Please continue running ED Discovery until refresh is complete.");
            }
            InvokeAsyncOnUiThread(() => OnInitialisationComplete?.Invoke());
        }
Exemple #2
0
        private void buttonExt1_Click(object sender, EventArgs e)
        {
            System.IO.StreamReader filejr = new System.IO.StreamReader(textBoxFile.Text);
            string   line;
            string   system = "";
            StarScan ss     = new StarScan();

            Dictionary <string, string> items = new Dictionary <string, string>();

            while ((line = filejr.ReadLine()) != null)
            {
                if (line.Equals("END"))
                {
                    break;
                }
                //System.Diagnostics.Trace.WriteLine(line);

                if (line.Length > 0)
                {
                    JObject jo = (JObject)JObject.Parse(line);

                    //JSONPrettyPrint jpp = new JSONPrettyPrint(EliteDangerous.JournalFieldNaming.StandardConverters(), "event;timestamp", "_Localised", (string)jo["event"]);
                    //string s = jpp.PrettyPrintStr(line, 80);
                    //System.Diagnostics.Trace.WriteLine(s);

                    EliteDangerousCore.JournalEntry je = EliteDangerousCore.JournalEntry.CreateJournalEntry(line);
                    //System.Diagnostics.Trace.WriteLine(je.EventTypeStr);

                    if (je.EventTypeID == EliteDangerousCore.JournalTypeEnum.Location)
                    {
                        EliteDangerousCore.JournalEvents.JournalLocOrJump jl = je as EliteDangerousCore.JournalEvents.JournalLocOrJump;
                        system = jl.StarSystem;
                    }
                    else if (je.EventTypeID == EliteDangerousCore.JournalTypeEnum.FSDJump)
                    {
                        EliteDangerousCore.JournalEvents.JournalFSDJump jfsd = je as EliteDangerousCore.JournalEvents.JournalFSDJump;
                        system = jfsd.StarSystem;
                    }
                    else if (je.EventTypeID == EliteDangerousCore.JournalTypeEnum.Scan)
                    {
                        //ss.Process(je as EliteDangerousCore.JournalEvents.JournalScan, new EliteDangerousCore.SystemClass(system));
                    }
                }
            }
        }
Exemple #3
0
        public static void ReadCmdLineJournal(string file) //DEBUG ONLY FROM COMMAND LINE
        {
            System.IO.StreamReader filejr = new System.IO.StreamReader(file);
            string   line;
            string   system = "";
            StarScan ss     = new StarScan();

            Dictionary <string, string> items = new Dictionary <string, string>();

            while ((line = filejr.ReadLine()) != null)
            {
                if (line.Equals("END"))
                {
                    break;
                }
                //System.Diagnostics.Trace.WriteLine(line);

                if (line.Length > 0)
                {
                    JObject jo = (JObject)JObject.Parse(line);

                    //JSONPrettyPrint jpp = new JSONPrettyPrint(EliteDangerous.JournalFieldNaming.StandardConverters(), "event;timestamp", "_Localised", (string)jo["event"]);
                    //string s = jpp.PrettyPrintStr(line, 80);
                    //System.Diagnostics.Trace.WriteLine(s);

                    EliteDangerous.JournalEntry je = EliteDangerous.JournalEntry.CreateJournalEntry(line);
                    //System.Diagnostics.Trace.WriteLine(je.EventTypeStr);

                    if (je.EventTypeID == JournalTypeEnum.Location)
                    {
                        EDDiscovery.EliteDangerous.JournalEvents.JournalLocOrJump jl = je as EDDiscovery.EliteDangerous.JournalEvents.JournalLocOrJump;
                        system = jl.StarSystem;
                    }
                    else if (je.EventTypeID == JournalTypeEnum.FSDJump)
                    {
                        EDDiscovery.EliteDangerous.JournalEvents.JournalFSDJump jfsd = je as EDDiscovery.EliteDangerous.JournalEvents.JournalFSDJump;
                        system = jfsd.StarSystem;
                    }
                    else if (je.EventTypeID == JournalTypeEnum.Scan)
                    {
                        ss.Process(je as EliteDangerous.JournalEvents.JournalScan, new SystemClassDB(system));
                    }
                }
            }
        }
Exemple #4
0
        // Called from Background Thread Worker at Init()

        private void BackgroundInit()
        {
            StarScan.LoadBodyDesignationMap();

            SQLiteConnectionSystem.CreateSystemsTableIndexes();     // just make sure they are there..

            Debug.WriteLine(BaseUtils.AppTicks.TickCountLap() + " Check systems");
            ReportSyncProgress(-1, "");

            bool checkGithub = EDDOptions.Instance.CheckGithubFiles;

            if (checkGithub)      // not normall in debug, due to git hub chokeing
            {
                // Async load of maps in another thread
                DownloadMaps(() => PendingClose);

                // and Expedition data
                DownloadExpeditions(() => PendingClose);

                // and Exploration data
                DownloadExploration(() => PendingClose);
            }

            if (!EDDOptions.Instance.NoSystemsLoad)
            {
                // Former CheckSystems, reworked to accomodate new switches..
                // Check to see what sync refreshes we need

                // New Galmap load - it was not doing a refresh if EDSM sync kept on happening. Now has its own timer

                string   rwgalmaptime = SQLiteConnectionSystem.GetSettingString("EDSMGalMapLast", "2000-01-01 00:00:00"); // Latest time from RW file.
                DateTime galmaptime;
                if (!DateTime.TryParse(rwgalmaptime, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out galmaptime))
                {
                    galmaptime = new DateTime(2000, 1, 1);
                }

                if (DateTime.Now.Subtract(galmaptime).TotalDays > 14)  // Over 14 days do a sync from EDSM for galmap
                {
                    LogLine("Get galactic mapping from EDSM.".Tx(this, "EDSM"));
                    galacticMapping.DownloadFromEDSM();
                    SQLiteConnectionSystem.PutSettingString("EDSMGalMapLast", DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss"));
                }

                Debug.WriteLine(BaseUtils.AppTicks.TickCountLap() + " Check systems complete");
            }

            galacticMapping.ParseData();                            // at this point, gal map data has been uploaded - get it into memory
            SystemClassDB.AddToAutoComplete(galacticMapping.GetGMONames());
            SystemNoteClass.GetAllSystemNotes();

            LogLine("Loaded Notes, Bookmarks and Galactic mapping.".Tx(this, "LN"));

            if (PendingClose)
            {
                return;
            }

            if (EliteDangerousCore.EDDN.EDDNClass.CheckforEDMC()) // EDMC is running
            {
                if (EDCommander.Current.SyncToEddn)               // Both EDD and EDMC should not sync to EDDN.
                {
                    LogLineHighlight("EDDiscovery and EDMarketConnector should not both sync to EDDN. Stop EDMC or uncheck 'send to EDDN' in settings tab!".Tx(this, "EDMC"));
                }
            }

            if (!EDDOptions.Instance.NoLoad)        // here in this thread, we do a refresh of history.
            {
                LogLine("Reading travel history".Tx(this, "RTH"));
                DoRefreshHistory(new RefreshWorkerArgs {
                    CurrentCommander = EDCommander.CurrentCmdrID
                });                                                                                             // kick the background refresh worker thread into action
            }

            if (PendingClose)
            {
                return;
            }

            if (!EDDOptions.Instance.NoSystemsLoad && EDDConfig.Instance.EDSMEDDBDownload)        // if enabled
            {
                SystemClassEDSM.DetermineIfFullEDSMSyncRequired(syncstate);                       // ask EDSM and EDDB if they want to do a Full sync..
                EliteDangerousCore.EDDB.SystemClassEDDB.DetermineIfEDDBSyncRequired(syncstate);

                if (syncstate.perform_eddb_sync || syncstate.perform_edsm_fullsync)
                {
                    string databases = (syncstate.perform_edsm_fullsync && syncstate.perform_eddb_sync) ? "EDSM and EDDB" : ((syncstate.perform_edsm_fullsync) ? "EDSM" : "EDDB");

                    LogLine(string.Format("Full synchronisation to the {0} databases required." + Environment.NewLine +
                                          "This will take a while, up to 15 minutes, please be patient." + Environment.NewLine +
                                          "Please continue running ED Discovery until refresh is complete.".Tx(this, "SyncEDSM"), databases));
                }
            }
            else
            {
                LogLine("Synchronisation to EDSM and EDDB disabled. Use Settings panel to reenable".Tx(this, "SyncOff"));
            }
        }
Exemple #5
0
        public override bool ExecuteAction(ActionProgramRun ap)
        {
            string res;

            if (ap.functions.ExpandString(UserData, out res) != Conditions.ConditionFunctions.ExpandResult.Failed)
            {
                StringParser sp = new StringParser(res);

                string prefix  = "S_";
                string cmdname = sp.NextQuotedWord();

                if (cmdname != null && cmdname.Equals("PREFIX", StringComparison.InvariantCultureIgnoreCase))
                {
                    prefix = sp.NextWord();

                    if (prefix == null)
                    {
                        ap.ReportError("Missing name after Prefix in Scan");
                        return(true);
                    }

                    cmdname = sp.NextQuotedWord();
                }

                bool edsm = false;
                if (cmdname != null && cmdname.Equals("EDSM", StringComparison.InvariantCultureIgnoreCase))
                {
                    edsm    = true;
                    cmdname = sp.NextQuotedWord();
                }

                if (cmdname != null)
                {
                    StarScan scan = (ap.actioncontroller as ActionController).HistoryList.starscan;
                    ISystem  sc   = SystemClassDB.GetSystem(cmdname);

                    if (sc == null)
                    {
                        sc        = new SystemClass(cmdname);
                        sc.EDSMID = 0;
                    }

                    StarScan.SystemNode sn = scan.FindSystem(sc, edsm);

                    System.Globalization.CultureInfo ct = System.Globalization.CultureInfo.InvariantCulture;

                    if (sn != null)
                    {
                        int starno = 1;
                        ap[prefix + "Stars"] = sn.starnodes.Count.ToString(ct);

                        foreach (KeyValuePair <string, StarScan.ScanNode> scannode in sn.starnodes)
                        {
                            DumpInfo(ap, scannode, prefix + "Star_" + starno.ToString(ct), "_Planets");

                            int pcount = 1;

                            if (scannode.Value.children != null)
                            {
                                foreach (KeyValuePair <string, StarScan.ScanNode> planetnodes in scannode.Value.children)
                                {
                                    DumpInfo(ap, planetnodes, prefix + "Planet_" + starno.ToString(ct) + "_" + pcount.ToString(ct), "_Moons");

                                    if (planetnodes.Value.children != null)
                                    {
                                        int mcount = 1;
                                        foreach (KeyValuePair <string, StarScan.ScanNode> moonnodes in planetnodes.Value.children)
                                        {
                                            DumpInfo(ap, moonnodes, prefix + "Moon_" + starno.ToString(ct) + "_" + pcount.ToString(ct) + "_" + mcount.ToString(ct), "_Submoons");

                                            if (moonnodes.Value.children != null)
                                            {
                                                int smcount = 1;
                                                foreach (KeyValuePair <string, StarScan.ScanNode> submoonnodes in moonnodes.Value.children)
                                                {
                                                    DumpInfo(ap, submoonnodes, prefix + "SubMoon_" + starno.ToString(ct) + "_" + pcount.ToString(ct) + "_" + mcount.ToString(ct) + "_" + smcount.ToString(ct), null);
                                                    smcount++;
                                                }
                                            }

                                            mcount++;
                                        }
                                    }

                                    pcount++;
                                }
                            }

                            starno++;
                        }
                    }
                    else
                    {
                        ap[prefix + "Stars"] = "0";
                    }
                }
                else
                {
                    ap.ReportError("Missing starname in Scan");
                }
            }
            else
            {
                ap.ReportError(res);
            }

            return(true);
        }
Exemple #6
0
        private void Display(HistoryList hl)
        {
            pictureBox.ClearImageList();

            current_historylist = hl;

            if (hl != null && hl.Count > 0)                                                                   // just for safety
            {
                List <HistoryEntry> result = current_historylist.LastFirst;                                   // Standard filtering

                int ftotal;                                                                                   // event filter
                result = HistoryList.FilterByJournalEvent(result, SQLiteDBClass.GetSettingString(DbFilterSave, "All"), out ftotal);
                result = FilterHelpers.FilterHistory(result, fieldfilter, discoveryform.Globals, out ftotal); // and the field filter..

                RevertToNormalSize();                                                                         // ensure size is back to normal..
                scanpostextoffset = new Point(0, 0);                                                          // left/ top used by scan display

                Color textcolour = IsTransparent ? discoveryform.theme.SPanelColor : discoveryform.theme.LabelColor;
                Color backcolour = IsTransparent ? (Config(Configuration.showBlackBoxAroundText) ? Color.Black : Color.Transparent) : this.BackColor;

                bool drawnnootherstuff = DrawScanText(true, textcolour, backcolour); // go 1 for some of the scan positions

                if (!drawnnootherstuff)                                              // and it may indicate its overwriting all stuff, which is fine
                {
                    int rowpos    = scanpostextoffset.Y;
                    int rowheight = Config(Configuration.showIcon) ? 26 : 20;

                    if (Config(Configuration.showNothingWhenDocked) && (hl.IsCurrentlyDocked || hl.IsCurrentlyLanded))
                    {
                        AddColText(0, 0, rowpos, rowheight, (hl.IsCurrentlyDocked) ? "Docked" : "Landed", textcolour, backcolour, null);
                    }
                    else if ((uistate == UIState.GalMap && Config(Configuration.showNothingWhenGalmap)) || (uistate == UIState.SystemMap && Config(Configuration.showNothingWhenSysmap)))
                    {
                        AddColText(0, 0, rowpos, rowheight, (uistate == UIState.GalMap) ? "Galaxy Map" : "System Map", textcolour, backcolour, null);
                    }
                    else
                    {
                        string  name;
                        Point3D tpos;
                        bool    targetpresent = TargetClass.GetTargetPosition(out name, out tpos);

                        ISystem currentsystem = hl.CurrentSystem; // may be null

                        HistoryEntry last = hl.GetLast;

                        if (Config(Configuration.showSystemInformation) && last != null)
                        {
                            string allegiance, economy, gov, faction, factionstate, security;
                            hl.ReturnSystemInfo(last, out allegiance, out economy, out gov, out faction, out factionstate, out security);

                            string str = last.System.Name + " : " + BaseUtils.FieldBuilder.Build(
                                "", faction,
                                "", factionstate,
                                "", security,
                                "", allegiance,
                                "", economy,
                                "", gov
                                );


                            HistoryEntry lastfsd        = hl.GetLastHistoryEntry(x => x.journalEntry is EliteDangerousCore.JournalEvents.JournalFSDJump, last);
                            bool         firstdiscovery = (lastfsd != null && (lastfsd.journalEntry as EliteDangerousCore.JournalEvents.JournalFSDJump).EDSMFirstDiscover);

                            AddColText(0, 0, rowpos, rowheight, str, textcolour, backcolour, null, firstdiscovery ? EDDiscovery.Icons.Controls.firstdiscover : null, "Shows if EDSM indicates your it's first discoverer");

                            rowpos += rowheight;
                        }

                        if (Config(Configuration.showHabInformation) && last != null)
                        {
                            StarScan scan = hl.starscan;

                            StarScan.SystemNode sn = scan.FindSystem(last.System, true);    // EDSM look up here..

                            string res = null;

                            if (sn != null && sn.starnodes.Count > 0 && sn.starnodes.Values[0].ScanData != null)
                            {
                                JournalScan js = sn.starnodes.Values[0].ScanData;
                                res = js.HabZoneString().Replace("\r\n", " ");
                            }

                            if (res != null)
                            {
                                AddColText(0, 0, rowpos, rowheight, res, textcolour, backcolour, null);
                                rowpos += rowheight;
                            }
                        }

                        if (targetpresent && Config(Configuration.showTargetLine) && currentsystem != null)
                        {
                            string dist = (currentsystem.HasCoordinate) ? currentsystem.Distance(tpos.X, tpos.Y, tpos.Z).ToString("0.00") : "Unknown";
                            AddColText(0, 0, rowpos, rowheight, "Target: " + name + " @ " + dist + " ly", textcolour, backcolour, null);
                            rowpos += rowheight;
                        }

                        foreach (HistoryEntry rhe in result)
                        {
                            DrawHistoryEntry(rhe, rowpos, rowheight, tpos, textcolour, backcolour);
                            rowpos += rowheight;

                            if (rowpos > ClientRectangle.Height)                // stop when off of screen
                            {
                                break;
                            }
                        }
                    }
                }

                DrawScanText(false, textcolour, backcolour);     // go 2
            }

            pictureBox.Render();
        }
Exemple #7
0
        private void BackgroundWorkerThread()
        {
            // check first and download items

            StarScan.LoadBodyDesignationMap();

            Debug.WriteLine(BaseUtils.AppTicks.TickCountLap() + " Check systems");
            ReportSyncProgress("");

            bool checkGithub = EDDOptions.Instance.CheckGithubFiles;

            if (checkGithub)      // not normall in debug, due to git hub chokeing
            {
                // Async load of maps in another thread
                DownloadMaps(() => PendingClose);

                // and Expedition data
                DownloadExpeditions(() => PendingClose);

                // and Exploration data
                DownloadExploration(() => PendingClose);
            }

            if (!EDDOptions.Instance.NoSystemsLoad)
            {
                // New Galmap load - it was not doing a refresh if EDSM sync kept on happening. Now has its own timer

                DateTime galmaptime = SystemsDatabase.Instance.GetEDSMGalMapLast();                           // Latest time from RW file.

                if (DateTime.Now.Subtract(galmaptime).TotalDays > 14 || !galacticMapping.GalMapFilePresent()) // Over 14 days do a sync from EDSM for galmap
                {
                    LogLine("Get galactic mapping from EDSM.".T(EDTx.EDDiscoveryController_EDSM));
                    if (galacticMapping.DownloadFromEDSM())
                    {
                        SystemsDatabase.Instance.SetEDSMGalMapLast(DateTime.UtcNow);
                    }
                }

                Debug.WriteLine(BaseUtils.AppTicks.TickCountLap() + " Check systems complete");
            }

            galacticMapping.ParseData();                            // at this point, gal map data has been uploaded - get it into memory
            SystemCache.AddToAutoCompleteList(galacticMapping.GetGMONames());
            SystemNoteClass.GetAllSystemNotes();

            LogLine("Loaded Notes, Bookmarks and Galactic mapping.".T(EDTx.EDDiscoveryController_LN));

            if (EliteDangerousCore.EDDN.EDDNClass.CheckforEDMC()) // EDMC is running
            {
                if (EDCommander.Current.SyncToEddn)               // Both EDD and EDMC should not sync to EDDN.
                {
                    LogLineHighlight("EDDiscovery and EDMarketConnector should not both sync to EDDN. Stop EDMC or uncheck 'send to EDDN' in settings tab!".T(EDTx.EDDiscoveryController_EDMC));
                }
            }

            if (!EDDOptions.Instance.NoLoad)        // here in this thread, we do a refresh of history.
            {
                LogLine("Reading travel history".T(EDTx.EDDiscoveryController_RTH));

                if (EDDOptions.Instance.Commander != null)
                {
                    EDCommander switchto = EDCommander.GetCommander(EDDOptions.Instance.Commander);
                    if (switchto != null)
                    {
                        EDCommander.CurrentCmdrID = switchto.Nr;
                    }
                }

                DoRefreshHistory(new RefreshWorkerArgs {
                    CurrentCommander = EDCommander.CurrentCmdrID
                });                                                                                             // kick the background refresh worker thread into action
            }

            CheckForSync();     // see if any EDSM/EDDB sync is needed - this just sets some variables up

            System.Diagnostics.Debug.WriteLine("Background worker setting up refresh worker");

            backgroundRefreshWorker = new Thread(BackgroundHistoryRefreshWorkerThread)
            {
                Name = "Background Refresh Worker", IsBackground = true
            };
            backgroundRefreshWorker.Start();        // start the refresh worker, another thread which does subsequenct (not the primary one) refresh work in the background..

            try
            {
                if (!EDDOptions.Instance.NoSystemsLoad)
                {
                    SystemsDatabase.Instance.WithReadWrite(() => DoPerformSync());        // this is done after the initial history load..
                }

                SystemsDatabase.Instance.SetReadOnly();

                while (!PendingClose)
                {
                    int wh = WaitHandle.WaitAny(new WaitHandle[] { closeRequested, resyncRequestedEvent });

                    System.Diagnostics.Debug.WriteLine("Background worker kicked by " + wh);

                    if (PendingClose)
                    {
                        break;
                    }

                    if (wh == 1)
                    {
                        if (!EDDOptions.Instance.NoSystemsLoad && EDDConfig.Instance.EDSMEDDBDownload)      // if no system off, and EDSM download on
                        {
                            SystemsDatabase.Instance.WithReadWrite(() => DoPerformSync());
                        }
                    }
                }
            }
            catch (OperationCanceledException)
            {
            }

            backgroundRefreshWorker.Join();     // this should terminate due to closeRequested..

            System.Diagnostics.Debug.WriteLine("BW Refresh joined");

            // Now we have been ordered to close down, so go thru the process

            closeRequested.WaitOne();

            InvokeAsyncOnUiThread(() =>
            {
                System.Diagnostics.Debug.WriteLine("Final close");
                OnFinalClose?.Invoke();
            });
        }
Exemple #8
0
        private async void Display(HistoryList hl)
        {
            pictureBox.ClearImageList();

            current_historylist = hl;

            if (hl != null && hl.Count > 0)                                                                   // just for safety
            {
                List <HistoryEntry> result = current_historylist.LatestFirst();                               // Standard filtering

                int ftotal;                                                                                   // event filter
                result = HistoryList.FilterByJournalEvent(result, GetSetting(dbFilter, "All"), out ftotal);
                result = FilterHelpers.FilterHistory(result, fieldfilter, discoveryform.Globals, out ftotal); // and the field filter..

                RevertToNormalSize();                                                                         // ensure size is back to normal..
                scanpostextoffset = new Point(0, 0);                                                          // left/ top used by scan display

                Color textcolour = IsTransparent ? discoveryform.theme.SPanelColor : discoveryform.theme.LabelColor;
                Color backcolour = IsTransparent ? (Config(Configuration.showBlackBoxAroundText) ? Color.Black : Color.Transparent) : this.BackColor;

                bool drawnnootherstuff = DrawScanText(true, textcolour, backcolour); // go 1 for some of the scan positions

                if (!drawnnootherstuff)                                              // and it may indicate its overwriting all stuff, which is fine
                {
                    int rowpos    = scanpostextoffset.Y;
                    int rowmargin = displayfont.ScalePixels(4);

                    // Check if need to hide the UI
                    var ts = hl.CurrentTravelState();

                    if (Config(Configuration.showNothingWhenDocked) && (ts == HistoryEntryStatus.TravelStateType.Docked))
                    {
                        if (!Config(Configuration.showNoTitleWhenHidden))
                        {
                            AddColText(0, 0, rowpos, "<>", textcolour, backcolour, null);                                   // just show a marker
                        }
                    }
                    else if (uistate != EliteDangerousCore.UIEvents.UIGUIFocus.Focus.NoFocus && Config(Configuration.showNothingWhenPanel))
                    {
                        if (!Config(Configuration.showNoTitleWhenHidden))
                        {
                            AddColText(0, 0, rowpos, uistate.ToString().SplitCapsWord(),
                                       textcolour, backcolour, null);
                        }
                    }
                    else
                    {
                        string  name;
                        Point3D tpos;
                        bool    targetpresent = TargetClass.GetTargetPosition(out name, out tpos);

                        ISystem currentsystem = hl.CurrentSystem(); // may be null

                        HistoryEntry last = hl.GetLast;

                        // last = hl.FindByName("Myeia Thaa QY-H c23-0");

                        if (Config(Configuration.showSystemInformation) && last != null)
                        {
                            string allegiance, economy, gov, faction, factionstate, security;
                            hl.ReturnSystemInfo(last, out allegiance, out economy, out gov, out faction, out factionstate, out security);

                            string str = last.System.Name + " : " + BaseUtils.FieldBuilder.Build(
                                "", faction,
                                "", factionstate,
                                "", security,
                                "", allegiance,
                                "", economy,
                                "", gov
                                );


                            HistoryEntry lastfsd        = hl.GetLastHistoryEntry(x => x.journalEntry is EliteDangerousCore.JournalEvents.JournalFSDJump, last);
                            bool         firstdiscovery = (lastfsd != null && (lastfsd.journalEntry as EliteDangerousCore.JournalEvents.JournalFSDJump).EDSMFirstDiscover);

                            rowpos = rowmargin + AddColText(0, 0, rowpos, str, textcolour, backcolour, null, firstdiscovery ? EDDiscovery.Icons.Controls.firstdiscover : null, "Shows if EDSM indicates your it's first discoverer").Location.Bottom;
                        }

                        if (Config(Configuration.showHabInformation) && last != null)
                        {
                            StarScan scan = hl.StarScan;

                            StarScan.SystemNode sn = await scan.FindSystemAsync(last.System, true);    // EDSM look up here..

                            StringBuilder res = new StringBuilder();

                            if (sn != null && sn.StarNodes.Count > 0 && sn.StarNodes.Values[0].ScanData != null)
                            {
                                JournalScan js = sn.StarNodes.Values[0].ScanData;

                                if (showCircumstellarZonesToolStripMenuItem.Checked)
                                {
                                    string hz = js.CircumstellarZonesString(false, JournalScan.CZPrint.CZHab);
                                    res.AppendFormat(hz + Environment.NewLine);
                                }

                                if (showMetalRichPlanetsToolStripMenuItem.Checked)
                                {
                                    string hz = js.CircumstellarZonesString(false, JournalScan.CZPrint.CZMR);
                                    res.AppendFormat(hz + Environment.NewLine);
                                }

                                if (showWaterWorldsToolStripMenuItem.Checked)
                                {
                                    string hz = js.CircumstellarZonesString(false, JournalScan.CZPrint.CZWW);
                                    res.AppendFormat(hz + Environment.NewLine);
                                }

                                if (showEarthLikeToolStripMenuItem.Checked)
                                {
                                    string hz = js.CircumstellarZonesString(false, JournalScan.CZPrint.CZEL);
                                    res.AppendFormat(hz + Environment.NewLine);
                                }

                                if (showAmmoniaWorldsToolStripMenuItem.Checked)
                                {
                                    string hz = js.CircumstellarZonesString(false, JournalScan.CZPrint.CZAW);
                                    res.AppendFormat(hz + Environment.NewLine);
                                }

                                if (showIcyPlanetsToolStripMenuItem.Checked)
                                {
                                    string hz = js.CircumstellarZonesString(false, JournalScan.CZPrint.CZIP);
                                    res.AppendFormat(hz + Environment.NewLine);
                                }
                            }

                            if (res.ToString().HasChars())
                            {
                                rowpos = rowmargin + AddColText(0, 0, rowpos, res.ToString(), textcolour, backcolour, null).Location.Bottom;
                            }
                        }

                        if (targetpresent && Config(Configuration.showTargetLine) && currentsystem != null)
                        {
                            string dist = (currentsystem.HasCoordinate) ? currentsystem.Distance(tpos.X, tpos.Y, tpos.Z).ToString("0.00") : "Unknown".T(EDTx.Unknown);
                            rowpos = rowmargin + AddColText(0, 0, rowpos, "Target".T(EDTx.UserControlSpanel_Target) + ": " + name + " @ " + dist + " ly", textcolour, backcolour, null).Location.Bottom;
                        }

                        foreach (HistoryEntry rhe in result)
                        {
                            rowpos = rowmargin + DrawHistoryEntry(rhe, rowpos, tpos, textcolour, backcolour);

                            if (rowpos > ClientRectangle.Height)                // stop when off of screen
                            {
                                break;
                            }
                        }
                    }
                }

                DrawScanText(false, textcolour, backcolour);     // go 2
            }

            pictureBox.Render();
        }
        void DrawSystem(StarScan.SystemNode sn)
        {
            imagebox.Clear();
            HideInfo();

            last_sn = sn;                                                               // remember in case we need to draw

            SetControlText((sn == null) ? "No Scan" : sn.system.name);

            if (sn == null)
                return;

            Point curpos = new Point(leftmargin, topmargin);
            last_maxdisplayarea = curpos;

            List<PictureBoxHotspot.ImageElement> starcontrols = new List<PictureBoxHotspot.ImageElement>();

            //for( int i = 0; i < 1000; i +=100)  CreateStarPlanet(starcontrols, EDDiscovery.Properties.Resources.ImageStarDiscWhite, new Point(i, 0), new Size(24, 24), i.ToString(), "");

            foreach (StarScan.ScanNode starnode in sn.starnodes.Values)        // always has scan nodes
            {
                int offset = 0;
                Point maxstarpos = DrawNode(starcontrols, starnode,
                            (starnode.type == StarScan.ScanNodeType.barycentre ) ? EDDiscovery.Properties.Resources.Barycentre : JournalScan.GetStarImageNotScanned() ,
                            curpos , starsize, ref offset, false);

                Point maxitemspos = maxstarpos;

                curpos = new Point(maxitemspos.X + itemsepar.Width, curpos.Y);   // move to the right
                curpos.Y += starsize.Height / 2 - planetsize.Height * 3 / 4;     // slide down for planet vs star difference in size

                Point firstcolumn = curpos;

                if (starnode.children != null)
                {
                    foreach (StarScan.ScanNode planetnode in starnode.children.Values)
                    {
                        List<PictureBoxHotspot.ImageElement> pc = new List<PictureBoxHotspot.ImageElement>();

                        Point maxpos = CreatePlanetTree(pc, planetnode, curpos);

                        //System.Diagnostics.Debug.WriteLine("Planet " + planetnode.ownname + " " + curpos + " " + maxpos + " max " + (panelStars.Width - panelStars.ScrollBarWidth));

                        if ( maxpos.X > panelStars.Width - panelStars.ScrollBarWidth)          // uh oh too wide..
                        {
                            int xoffset = firstcolumn.X - curpos.X;
                            int yoffset = maxitemspos.Y - curpos.Y;

                            RepositionTree(pc, xoffset, yoffset);        // shift co-ords of all you've drawn

                            maxpos = new Point(maxpos.X + xoffset, maxpos.Y + yoffset);
                            curpos = new Point(maxpos.X, curpos.Y + yoffset);
                        }
                        else
                            curpos = new Point(maxpos.X, curpos.Y);

                        maxitemspos = new Point(Math.Max(maxitemspos.X, maxpos.X), Math.Max(maxitemspos.Y, maxpos.Y));

                        starcontrols.AddRange(pc.ToArray());
                    }
                }

                last_maxdisplayarea = new Point(Math.Max(last_maxdisplayarea.X, maxitemspos.X), Math.Max(last_maxdisplayarea.Y, maxitemspos.Y));
                curpos = new Point(leftmargin, maxitemspos.Y + itemsepar.Height);
            }

            imagebox.AddRange(starcontrols);
            imagebox.Render();
            //System.Diagnostics.Debug.WriteLine("Display area " + last_maxdisplayarea);
        }
        // return right bottom of area used from curpos
        Point DrawNode(List<PictureBoxHotspot.ImageElement> pc, StarScan.ScanNode sn, Image notscanned, Point curpos, 
            Size size, ref int offset, bool alignhorz)
        {
            string tip;
            Point endpoint = curpos;
            int hoff = size.Height / 4;
            int alignhoff = (alignhorz) ? hoff : 0;

            JournalScan sc = sn.scandata;

            if (sc != null)
            {
                tip = sc.DisplayString(true);

                if (sc.IsStar)
                {
                    endpoint = CreateImageLabel(pc, sc.GetStarTypeImage().Item1,
                                                new Point(curpos.X+offset, curpos.Y + alignhoff) ,
                                                size, sn.ownname, tip, alignhoff);

                    if ( sc.HasRings )
                    {
                        curpos = new Point(endpoint.X + itemsepar.Width, curpos.Y);

                        Point endbelt = curpos;

                        for (int i = 0; i < sc.Rings.Length; i++)
                        {
                            string name = sc.Rings[i].Name;
                            if (name.Length > sn.fullname.Length && name.Substring(0, sn.fullname.Length).Equals(sn.fullname))
                                name = name.Substring(sn.fullname.Length).Trim();

                            curpos.X += 4;      // a little spacing, image is tight

                            endbelt = CreateImageLabel(pc, EDDiscovery.Properties.Resources.Belt,
                                new Point( curpos.X, curpos.Y + alignhoff ), new Size(size.Width/2,size.Height), name,
                                                                sc.RingInformationMoons(i), alignhoff);

                            curpos = new Point(endbelt.X + itemsepar.Width, curpos.Y);
                        }

                        endpoint = new Point(curpos.X, endpoint.Y);
                    }

                    offset += size.Width / 2;       // return the middle used was this..
                }
                else
                {
                    bool indicatematerials = sc.HasMaterials && !checkBoxMaterials.Checked;

                    Image nodeimage = sc.GetPlanetClassImage();

                    if (sc.IsLandable || sc.HasRings || indicatematerials)
                    {
                        Bitmap bmp = new Bitmap(size.Width * 2, hoff * 6);

                        using (Graphics g = Graphics.FromImage(bmp))
                        {
                            g.DrawImage(nodeimage, size.Width / 2, hoff, size.Width, size.Height);

                            if (sc.IsLandable)
                                g.DrawImage(EDDiscovery.Properties.Resources.planet_landing, new Rectangle(hoff, 0, hoff * 6, hoff * 6));

                            if (sc.HasRings)
                                g.DrawImage(sc.Rings.Count() > 1 ? EDDiscovery.Properties.Resources.RingGap512 : EDDiscovery.Properties.Resources.Ring_Only_512,
                                                new Rectangle(-2, hoff, size.Width * 2, size.Height));

                            if (indicatematerials)
                            {
                                Image mm = EDDiscovery.Properties.Resources.materiamoreindicator;
                                g.DrawImage(mm, new Rectangle(bmp.Width - mm.Width, bmp.Height - mm.Height, mm.Width, mm.Height));
                            }
                        }

                        endpoint = CreateImageLabel(pc, bmp, curpos, new Size(bmp.Width, bmp.Height), sn.ownname, tip, 0);
                        offset = size.Width;                                        // return that the middle is now this
                    }
                    else
                    {
                        endpoint = CreateImageLabel(pc, nodeimage, new Point(curpos.X + offset, curpos.Y + alignhoff), size,
                                                    sn.ownname, tip, alignhoff);
                        offset += size.Width / 2;
                    }

                    if (sc.HasMaterials && checkBoxMaterials.Checked)
                    {
                        Point matpos = new Point(endpoint.X + 4, curpos.Y);
                        Point endmat = CreateMaterialNodes(pc, sc, matpos, materialsize);
                        endpoint = new Point(Math.Max(endpoint.X, endmat.X), Math.Max(endpoint.Y, endmat.Y)); // record new right point..
                    }
                }
            }
            else
            {
                if (sn.type == StarScan.ScanNodeType.barycentre)
                    tip = "Barycentre of " + sn.ownname;
                else
                    tip = sn.ownname + "\n\nNo scan data available";

                endpoint = CreateImageLabel(pc, notscanned, new Point(curpos.X + offset, curpos.Y + alignhoff), size, sn.ownname, tip , alignhoff);
                offset += size.Width / 2;       // return the middle used was this..
            }

            return endpoint;
        }
        // return right bottom of area used from curpos
        Point CreatePlanetTree(List<PictureBoxHotspot.ImageElement> pc, StarScan.ScanNode planetnode, Point curpos )
        {
            // PLANETWIDTH|PLANETWIDTH  (if drawing a full planet with rings/landing)
            // or
            // MOONWIDTH|MOONWIDTH      (if drawing a single width planet)
                                                                          // this offset, ONLY used if a single width planet, allows for two moons
            int offset = moonsize.Width - planetsize.Width / 2;           // centre is moon width, back off by planetwidth/2 to place the left edge of the planet

            Point maxtreepos = DrawNode(pc, planetnode, JournalScan.GetPlanetImageNotScanned(),
                                curpos, planetsize, ref offset , true);        // offset passes in the suggested offset, returns the centre offset

            if (planetnode.children != null && checkBoxMoons.Checked)
            {
                offset -= moonsize.Width;               // offset is centre of planet image, back off by a moon width to allow for 2 moon widths centred

                Point moonpos = new Point(curpos.X + offset, maxtreepos.Y + itemsepar.Height);    // moon pos

                foreach (StarScan.ScanNode moonnode in planetnode.children.Values)
                {
                    int offsetm = moonsize.Width / 2;                // pass in normal offset if not double width item (half moon from moonpos.x)

                    Point mmax = DrawNode(pc, moonnode, JournalScan.GetMoonImageNotScanned(), moonpos, moonsize, ref offsetm, false);

                    maxtreepos = new Point(Math.Max(maxtreepos.X, mmax.X), Math.Max(maxtreepos.Y, mmax.Y));

                    if (moonnode.children != null)
                    {
                        Point submoonpos;

                        if (mmax.X <= moonpos.X + moonsize.Width * 2)           // if we have nothing wider than the 2 moon widths, we can go with it right aligned
                            submoonpos = new Point(moonpos.X + moonsize.Width * 2 + itemsepar.Width, moonpos.Y);    // moon pos
                        else
                            submoonpos = new Point(moonpos.X + moonsize.Width * 2 + itemsepar.Width, mmax.Y + itemsepar.Height);    // moon pos below and right

                        foreach (StarScan.ScanNode submoonnode in moonnode.children.Values)
                        {
                            int offsetsm = moonsize.Width / 2;                // pass in normal offset if not double width item (half moon from moonpos.x)

                            Point sbmax = DrawNode(pc, submoonnode, JournalScan.GetMoonImageNotScanned(), submoonpos, moonsize, ref offsetsm, false);

                            maxtreepos = new Point(Math.Max(maxtreepos.X, sbmax.X), Math.Max(maxtreepos.Y, sbmax.Y));

                            submoonpos = new Point(submoonpos.X, maxtreepos.Y + itemsepar.Height);
                        }
                    }

                    moonpos = new Point(moonpos.X, maxtreepos.Y + itemsepar.Height);
                }
            }

            return maxtreepos;
        }
// I think we rework so we have a SyncBackgroundworker, and a refresh background worker.
// loading of history is done on refresh one..


        private void BackgroundWorkerThread()
        {
            readyForInitialLoad.WaitOne();      // wait for shown in form

            // check first and download items

            StarScan.LoadBodyDesignationMap();

            Debug.WriteLine(BaseUtils.AppTicks.TickCountLap() + " Check systems");
            ReportSyncProgress("");

            bool checkGithub = EDDOptions.Instance.CheckGithubFiles;

            if (checkGithub)      // not normall in debug, due to git hub chokeing
            {
                // Async load of maps in another thread
                DownloadMaps(() => PendingClose);

                // and Expedition data
                DownloadExpeditions(() => PendingClose);

                // and Exploration data
                DownloadExploration(() => PendingClose);
            }

            if (!EDDOptions.Instance.NoSystemsLoad)
            {
                // New Galmap load - it was not doing a refresh if EDSM sync kept on happening. Now has its own timer

                DateTime galmaptime = SQLiteConnectionSystem.GetSettingDate("EDSMGalMapLast", DateTime.MinValue); // Latest time from RW file.

                if (DateTime.Now.Subtract(galmaptime).TotalDays > 14 || !galacticMapping.GalMapFilePresent())     // Over 14 days do a sync from EDSM for galmap
                {
                    LogLine("Get galactic mapping from EDSM.".Tx(this, "EDSM"));
                    if (galacticMapping.DownloadFromEDSM())
                    {
                        SQLiteConnectionSystem.PutSettingDate("EDSMGalMapLast", DateTime.UtcNow);
                    }
                }

                Debug.WriteLine(BaseUtils.AppTicks.TickCountLap() + " Check systems complete");
            }

            galacticMapping.ParseData();                            // at this point, gal map data has been uploaded - get it into memory
            SystemCache.AddToAutoCompleteList(galacticMapping.GetGMONames());
            SystemNoteClass.GetAllSystemNotes();

            LogLine("Loaded Notes, Bookmarks and Galactic mapping.".Tx(this, "LN"));

            if (PendingClose)
            {
                return;
            }

            if (EliteDangerousCore.EDDN.EDDNClass.CheckforEDMC()) // EDMC is running
            {
                if (EDCommander.Current.SyncToEddn)               // Both EDD and EDMC should not sync to EDDN.
                {
                    LogLineHighlight("EDDiscovery and EDMarketConnector should not both sync to EDDN. Stop EDMC or uncheck 'send to EDDN' in settings tab!".Tx(this, "EDMC"));
                }
            }

            if (!EDDOptions.Instance.NoLoad)        // here in this thread, we do a refresh of history.
            {
                LogLine("Reading travel history".Tx(this, "RTH"));
                DoRefreshHistory(new RefreshWorkerArgs {
                    CurrentCommander = EDCommander.CurrentCmdrID
                });                                                                                             // kick the background refresh worker thread into action
            }

            if (PendingClose)
            {
                return;
            }

            CheckForSync();     // see if any EDSM/EDDB sync is needed

            if (PendingClose)
            {
                return;
            }

            // Now stay in loop services stuff

            backgroundRefreshWorker = new Thread(BackgroundHistoryRefreshWorkerThread)
            {
                Name = "Background Refresh Worker", IsBackground = true
            };
            backgroundRefreshWorker.Start();        // start the refresh worker, another thread which does subsequenct (not the primary one) refresh work in the background..

            try
            {
                if (!EDDOptions.Instance.NoSystemsLoad && EDDConfig.Instance.EDSMEDDBDownload) // if no system off, and EDSM download on
                {
                    DoPerformSync();                                                           // this is done after the initial history load..
                }
                while (!PendingClose)
                {
                    int wh = WaitHandle.WaitAny(new WaitHandle[] { closeRequested, resyncRequestedEvent });

                    if (PendingClose)
                    {
                        break;
                    }

                    switch (wh)
                    {
                    case 0:      // Close Requested
                        break;

                    case 1:                                                                            // Resync Requested
                        if (!EDDOptions.Instance.NoSystemsLoad && EDDConfig.Instance.EDSMEDDBDownload) // if no system off, and EDSM download on
                        {
                            DoPerformSync();
                        }
                        break;
                    }
                }
            }
            catch (OperationCanceledException)
            {
            }

            backgroundRefreshWorker.Join();

            // Now we have been ordered to close down, so go thru the process

            closeRequested.WaitOne();

            OnBgSafeClose?.Invoke();
            ReadyForFinalClose = true;
            InvokeAsyncOnUiThread(() =>
            {
                OnFinalClose?.Invoke();
            });
        }