private void PanelFile_SessionChanged(object sender, EventArgs e)
        {
            try
            {
                //NOTE: This method has many statements, and isn't very threadsafe, but even if there were several threads hitting these options there shouldn't
                //be any damage with the panels being momentarily out of sync

                // Kill all current
                if (_selectedBean != null && _selectedBean.Viewer != null)
                {
                    _selectedBean.Viewer.Close();
                }

                _selectedBean = null;
                foreach (Bean bean in _beans.ToArray())		// using toarray, because DisposeBean removes from the list
                {
                    DisposeBean(bean);
                }
                foreach (ExplodingBean explosion in _explosions.ToArray())
                {
                    DisposeExplosion(explosion);
                }

                // Get the new session
                _session = _panelFile.Session;
                _options = _panelFile.Options;
                _itemOptions = _panelFile.ItemOptions;

                #region Refresh options panels

                if (_panelBeanTypes != null)
                {
                    _panelBeanTypes.Options = _options;
                }

                if (_panelBeanProps != null)
                {
                    _panelBeanProps.Options = _options;
                    _panelBeanProps.ItemOptions = _itemOptions;
                }

                if (_panelMutation != null)
                {
                    _panelMutation.Options = _options;
                }

                if (_panelTracking != null)
                {
                    _panelTracking.Options = _options;
                }

                if (_panelSimulation != null)
                {
                    _panelSimulation.Options = _options;
                }

                #endregion

                // Refresh winner manager
                if (_winnerManager != null)
                {
                    _winnerManager.Live = _options.WinnersLive;
                    _winnerManager.Candidates = _options.WinnerCandidates;
                    _winnerManager.Final = _options.WinnersFinal;
                }

                RefreshStats();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
        private void DisposeExplosion(ExplodingBean explosion)
        {
            if (_selectedBean != null && _selectedBean.Bean == explosion.Bean)
            {
                //TODO: Remove any other selection visuals (leave the popup though)

                if (_selectedBean.Viewer != null)
                {
                    //TODO: This will get very annoying
                    _selectedBean.Viewer.Close();
                }

                _selectedBean = null;
            }

            _explosions.Remove(explosion);

            explosion.Dispose();

            //_winnerManager.ShipDied(explosion.Bean);		// this was done when creating the explosion
            _map.RemoveItem(explosion.Bean, true);
            //_beans.Remove(explosion.Bean);		// this was done when creating the explosion

            explosion.Bean.Dispose();
        }
        private void DisposeBean(Bean bean)
        {
            //NOTE: This method should be called for an instant kill of a bean, not called by explosion

            if (_selectedBean != null && _selectedBean.Bean == bean)
            {
                if (_selectedBean.Viewer != null)
                {
                    //TODO: This will get very annoying
                    _selectedBean.Viewer.Close();
                }

                _selectedBean = null;
            }

            _map.RemoveItem(bean, true);
            _beans.Remove(bean);
            bean.Dispose();
        }
        private void grdViewPort_MouseDown(object sender, MouseButtonEventArgs e)
        {
            try
            {
                if (e.ChangedButton != MouseButton.Left)
                {
                    // All the special logic in this method is for the left button
                    return;
                }

                #region Tab Buttons

                if (_pressedButton != null)
                {
                    // Hide the currently showing options panel
                    pnlSettings.Children.Clear();
                    _pressedButton = null;
                    ColorPanelButtons();
                }

                #endregion
                #region Select Bean

                var clickedBean = GetMouseOverBean(e);

                if (_selectedBean != null && clickedBean != null && _selectedBean.Bean.Equals(clickedBean.Item1))
                {
                    // This is already selected, don't do anything
                }
                else
                {
                    // Close any existing viewer
                    if (_selectedBean != null && _selectedBean.Viewer != null)
                    {
                        _selectedBean.Viewer.Close();
                    }
                    _selectedBean = null;

                    // Make the camera follow this bean
                    //TODO: Place a 2D graphic behind the selected ship
                    //TODO: Zoom in on the bean
                    if (clickedBean != null)
                    {
                        #region Show Viewer

                        ShipViewerWindow viewer = new ShipViewerWindow(clickedBean.Item1);
                        viewer.Owner = this;		// the other settings like topmost, showintaskbar, etc are already set in the window's xaml
                        viewer.PopupBorder = new SolidColorBrush(UtilityWPF.ColorFromHex("60000000"));
                        viewer.PopupBackground = new SolidColorBrush(UtilityWPF.ColorFromHex("30000000"));
                        viewer.ViewportBorder = new SolidColorBrush(UtilityWPF.ColorFromHex("E0000000"));

                        LinearGradientBrush brush = new LinearGradientBrush();
                        brush.StartPoint = new Point(0, 0);
                        brush.EndPoint = new Point(1, 1);

                        GradientStopCollection gradients = new GradientStopCollection();
                        gradients.Add(new GradientStop(UtilityWPF.ColorFromHex("E0EBEDE4"), 0d));
                        gradients.Add(new GradientStop(UtilityWPF.ColorFromHex("E0DFE0DA"), .1d));
                        gradients.Add(new GradientStop(UtilityWPF.ColorFromHex("E0E0E0E0"), .6d));
                        gradients.Add(new GradientStop(UtilityWPF.ColorFromHex("E0DADBD5"), .9d));
                        gradients.Add(new GradientStop(UtilityWPF.ColorFromHex("E0D7DBCC"), 1d));
                        brush.GradientStops = gradients;

                        viewer.ViewportBackground = brush;

                        viewer.PanelBorder = new SolidColorBrush(UtilityWPF.ColorFromHex("8068736B"));
                        viewer.PanelBackground = new SolidColorBrush(UtilityWPF.ColorFromHex("80424F45"));
                        viewer.Foreground = new SolidColorBrush(UtilityWPF.ColorFromHex("F0F0F0"));

                        Point windowClickPoint = UtilityWPF.TransformToScreen(clickedBean.Item3, grdViewPort);
                        Point popupPoint = new Point(windowClickPoint.X + 50, windowClickPoint.Y - (viewer.Height / 3d));
                        popupPoint = UtilityWPF.EnsureWindowIsOnScreen(popupPoint, new Size(viewer.Width, viewer.Height));		// don't let the popup straddle monitors
                        viewer.Left = popupPoint.X;
                        viewer.Top = popupPoint.Y;

                        viewer.Show();

                        #endregion

                        _selectedBean = new SelectedBean(clickedBean.Item1, viewer, _camera.Position - clickedBean.Item1.PositionWorld);
                    }
                }

                #endregion
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }