/// <summary>
        /// Gets the feature tooltip.
        /// </summary>
        /// <param name="viewModel">View model whose feature tooltip is desired.</param>
        /// <param name="x">The x coordinate within the cell.</param>
        /// <param name="y">The y coordinate within the cell.</param>
        /// <returns>The feature tooltip corresponding to the icon at the given coordinate, or <c>string.Empty</c> if none.</returns>
        public static string GetFeatureTooltip(ProgramDescriptionViewModel viewModel, int x, int y)
        {
            var tooltip      = string.Empty;
            var features     = viewModel.Features;
            var featureX     = 0;
            var featureIndex = -1;
            var i            = 0;

            foreach (var f in features)
            {
                if ((x >= featureX) && (x <= (featureX + f.Image.Size.Width + (Padding / 2))))
                {
                    featureIndex = i;
                    break;
                }
                else
                {
                    featureX += f.Image.Size.Width + Padding;
                    ++i;
                }
            }
            if (featureIndex >= 0)
            {
                tooltip = features[featureIndex].ToolTip;
            }
            return(tooltip);
        }
        /// <summary>
        /// Given a ProgramDescriptionViewModel, produce a single Gdk.Pixbuf that includes all of the program's feature icons.
        /// </summary>
        /// <param name="viewModel">View model of the program whose feature icons are to be rendered as a pixbuf.</param>
        /// <returns>A pixbuf containing the features.</returns>
        public static Gdk.Pixbuf ConvertToPixbuf(ProgramDescriptionViewModel viewModel)
        {
            // TODO: cache these so they don't need to be recreated all the time.
            Gdk.Pixbuf pixbuf    = null;
            var        features  = viewModel.Features;
            var        totWidth  = System.Math.Max(0, Padding * (features.Count - 1));
            var        totHeight = 0;

            foreach (var f in features)
            {
                totWidth += f.Image.Size.Width;
                totHeight = System.Math.Max(totHeight, f.Image.Size.Height);
            }
            if (totWidth > 0)
            {
                Gdk.Pixbuf image = features[0].Image;
                pixbuf = new Gdk.Pixbuf(image.Colorspace, image.HasAlpha, image.BitsPerSample, totWidth, totHeight);
                pixbuf.Fill(0xFFFFFF00); // fill with transparent white (??)
                var x = 0;
                foreach (var f in features)
                {
                    var imageSize = f.Image.Size;
                    ((Gdk.Pixbuf)f.Image).CopyArea(0, 0, f.Image.Size.Width, f.Image.Size.Height, pixbuf, x, 0);
                    x += Padding + f.Image.Size.Width;
                }
            }
            return(pixbuf);
        }
        /// <summary>
        /// Create the dialog from configuring ROM features.
        /// </summary>
        /// <param name="program">The program whose features are being edited.</param>
        /// <returns>THe dialog for editing ROM features.</returns>
        public static ProgramFeaturesEditorDialog Create(ProgramDescriptionViewModel program)
        {
            var editor    = new ProgramFeaturesEditorDialog();
            var viewModel = editor.ViewModel;

            viewModel.Initialize(program.Model, editor);
            editor.Owner = INTV.Shared.Utility.SingleInstanceApplication.Instance.MainWindow;
            return(editor);
        }
        /// <summary>
        /// Start editing a program description.
        /// </summary>
        /// <param name="program">The program description to be edited.</param>
        internal void EditProgramDescription(ProgramDescriptionViewModel program)
        {
            var table           = View.FindChild <NSTableView>();
            var itemToEditIndex = RomsArrayController.ArrangedObjects().ToList().IndexOf(program);
            var column          = table.TableColumns()[(int)RomListColumn.Title];

            if ((itemToEditIndex >= 0) && table.Delegate.ShouldEditTableColumn(table, column, itemToEditIndex))
            {
                table.EditColumn((int)RomListColumn.Title, itemToEditIndex);
            }
        }
        /// <summary>
        /// Create the dialog from configuring ROM features.
        /// </summary>
        /// <param name="program">The program whose features are being edited.</param>
        /// <returns>THe dialog for editing ROM features.</returns>
        public static RomFeaturesConfiguration Create(ProgramDescriptionViewModel program)
        {
            var controller = new RomFeaturesConfigurationController();
            var viewModel  = controller.DataContext as RomFeaturesConfigurationViewModel;

            viewModel.Initialize(program.Model, controller);
            var editor = controller.Window;

            editor.Controller = controller;
            editor.Title      = string.Format(Resources.Strings.RomFeaturesEditor_TitleFormat, program.Name);
            return(editor);
        }
        /// <summary>
        /// Converts feature flags into an image containing glyphs.
        /// </summary>
        /// <param name="viewModel">The view model.</param>
        /// <returns>An image that represents feature flags.</returns>
        public static NSImage TransformToImage(ProgramDescriptionViewModel viewModel)
        {
            var features  = viewModel.Features;
            var totWidth  = System.Math.Max(0.0f, Padding * (features.Count - 1));
            var totHeight = 0.0f;

            foreach (var f in features)
            {
                totWidth += (float)f.Image.Size.Width;
                totHeight = System.Math.Max(totHeight, (float)f.Image.Size.Height);
            }
            var image = new NSImage(new CGSize(totWidth, totHeight));

            image.LockFocus();
            var x = 0.0f;

            foreach (var f in features)
            {
                f.Image.Draw(new CGPoint(x, 0), CGRect.Empty, NSCompositingOperation.Copy, 1);
                x += (float)Padding + (float)f.Image.Size.Width;
            }
            image.UnlockFocus();
            return(image);
        }
 /// <summary>
 /// Initializes a new instance of the ProgramInformationPasteboardWriting type.
 /// </summary>
 /// <param name="programDescription">The program being dragged.</param>
 public ProgramInformationPasteboardWriting(ProgramDescriptionViewModel programDescription)
 {
     ProgramDescription = programDescription;
 }