public void AddFromFile(string subfolder)
        {
            string foldername = EnsureShipFolderExists(subfolder);

            ShipSelectorWindow dialog = new ShipSelectorWindow(foldername, _world);
            dialog.WindowStartupLocation = WindowStartupLocation.CenterScreen;

            bool? dialogResult = dialog.ShowDialog();

            if (dialogResult == null || !dialogResult.Value)
            {
                return;
            }

            List<Tuple<List<string>, string[]>> missingParts = new List<Tuple<List<string>, string[]>>();

            // Add the selected items
            foreach (ShipDNA dna in dialog.SelectedItems)
            {
                // Make sure this name is unique - it's ok to modify the dna directly, it came from a file, and the dialog is about to go away
                dna.ShipName = GetUniqueName(dna.ShipName);

                #region Detect missing parts

                string[] missing = FindMissingParts(dna);
                if (missing != null && missing.Length > 0)
                {
                    var existing = missingParts.Where(o => o.Item2.Union(missing).Count() == missing.Length).FirstOrDefault();
                    if (existing == null)
                    {
                        missingParts.Add(Tuple.Create(new string[] { dna.ShipName }.ToList(), missing));
                    }
                    else
                    {
                        existing.Item1.Add(dna.ShipName);
                    }
                }

                #endregion

                AddIconVisual(dna.ShipName, dna, _world);
                _options.NewBeanList.Add(dna.ShipName, dna);
            }

            SetButtonEnabled();

            #region Report Missing

            if (missingParts.Count > 0)
            {
                bool isSingular = missingParts.Count == 1 && missingParts[0].Item1.Count == 1;

                StringBuilder report = new StringBuilder();
                if (isSingular)
                {
                    report.Append("This ship doesn't");
                }
                else
                {
                    report.Append("These ships don't");
                }
                report.AppendLine(" have enough parts to function properly:");

                foreach (var set in missingParts)
                {
                    report.AppendLine();
                    report.Append(string.Join(", ", set.Item1));
                    report.AppendLine(":");
                    report.AppendLine(string.Join(", ", set.Item2));
                }

                MessageBox.Show(report.ToString(), MSGBOXCAPTION, MessageBoxButton.OK, MessageBoxImage.Warning);
            }

            #endregion
        }
        private void btnLoadShipFromFile_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                string foldername = System.IO.Path.Combine(UtilityCore.GetOptionsFolder(), ShipEditorWindow.SHIPFOLDER);

                ShipSelectorWindow dialog = new ShipSelectorWindow(foldername, _world);
                dialog.WindowStartupLocation = WindowStartupLocation.CenterScreen;

                bool? dialogResult = dialog.ShowDialog();

                if (dialogResult == null || !dialogResult.Value)
                {
                    return;
                }

                foreach (ShipDNA dna in dialog.SelectedItems)
                {
                    Inventory inventory = new Inventory(dna, 1);

                    _station.StationInventory.Add(inventory);
                    AddStationShipGraphic(inventory);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), TITLE, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
        private void btnAddDefault_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                lock (_options.Lock)
                {
                    // Get the items in default that aren't currently available
                    string[] names = _options.DefaultBeanList.Keys.Where(o => !_options.NewBeanList.ContainsKey(o)).ToArray();

                    if (names.Length == 0)
                    {
                        MessageBox.Show("All of the default beans are already in use", MSGBOXCAPTION, MessageBoxButton.OK, MessageBoxImage.Warning);
                        return;
                    }

                    // Ask the user to choose
                    ShipDNA[] choices = names.Select(o => _options.DefaultBeanList[o]).ToArray();

                    if (choices.Length > 1)
                    {
                        ShipSelectorWindow dialog = new ShipSelectorWindow(choices, _world);
                        dialog.Width = 300;
                        dialog.Height = 418;
                        dialog.WindowStartupLocation = WindowStartupLocation.CenterScreen;
                        bool? dialogResult = dialog.ShowDialog();

                        if (dialogResult == null || !dialogResult.Value)
                        {
                            return;
                        }

                        choices = dialog.SelectedItems;
                    }

                    // Add the selected items
                    foreach (ShipDNA dna in choices)
                    {
                        AddIconVisual(dna.ShipName, dna, _world);
                        _options.NewBeanList.Add(dna.ShipName, dna);
                    }
                }

                SetButtonEnabled();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), MSGBOXCAPTION, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }