/// <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);
            }
        }
        /// <inheritdoc/>
        public override void AwakeFromNib()
        {
            base.AwakeFromNib();
            View.Controller = this;

            var nsArray = NSArray.FromNSObjects(View.ViewModel.Programs.ToArray());

            var origValue = RomsArrayController.SelectsInsertedObjects;

            RomsArrayController.SelectsInsertedObjects = false;
            RomsArrayController.AddObjects(nsArray);
            RomsArrayController.RearrangeObjects();
            RomsArrayController.SelectsInsertedObjects = origValue;

            var table = View.FindChild <ROMsTableView>();

            table.Controller = this;
            DataSource       = new RomListDataSource(RomsArrayController);
            table.DataSource = DataSource;
            var tableDelegate = new RomListTableViewDelegate(RomsArrayController, View.ViewModel);

            table.Delegate = tableDelegate;
            TheDelegate    = tableDelegate;
            var programs = RomsArrayController.ArrangedObjects();

            for (int i = 0; i < (int)nsArray.Count; ++i)
            {
                var program     = programs[i] as ProgramDescriptionViewModel;
                var featuresTip = program.FeaturesTip;
            }

            View.ViewModel.Programs.CollectionChanged         += HandleProgramsChanged;
            View.ViewModel.CurrentSelection.CollectionChanged += HandleRomListSelectionChanged;
            HandleRomListSelectionChanged(null, null);

            INTV.Shared.Properties.Settings.Default.PropertyChanged += HandlePreferenceChanged;
            HandlePreferenceChanged(null, new System.ComponentModel.PropertyChangedEventArgs(RomListSettingsPageViewModel.ShowRomDetailsPropertyName));

            View.RegisterForDraggedTypes(new string[] { NSPasteboard.NSFilenamesType });
            INTV.Core.Model.Device.Peripheral.PeripheralAttached += HandlePeripheralArrivalOrDeparture;
            INTV.Core.Model.Device.Peripheral.PeripheralDetached += HandlePeripheralArrivalOrDeparture;
        }
        private void HandleProgramsChangedCore(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            DebugItemChange("ROMS COLLECTION CHANGED");
            switch (e.Action)
            {
            case NotifyCollectionChangedAction.Add:
                AddObjectsToArrayController(e.NewItems.OfType <NSObject>());
                break;

            case NotifyCollectionChangedAction.Remove:
                RemoveObjectsFromArrayController(e.OldItems.OfType <NSObject>());
                break;

            case NotifyCollectionChangedAction.Reset:
                var itemsToDelete = NSIndexSet.FromNSRange(new NSRange(0, RomsArrayController.ArrangedObjects().Length));
                RomsArrayController.Remove(itemsToDelete);
                HandleRomListSelectionChanged(null, null);     // ensure we show 'drop stuff here' text
                break;
            }
        }
        private void HandlePreferenceChangedCore(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
            case RomListSettingsPageViewModel.ShowRomDetailsPropertyName:
                var showColumns   = INTV.Shared.Properties.Settings.Default.ShowRomDetails;
                var columnsToHide = (new[]
                {
                    RomListColumn.Vendor,
                    RomListColumn.Year,
                    RomListColumn.Features,
                    RomListColumn.ManualFile
                }).Select(c => c.ToString().ToLower());
                var table = View.FindChild <NSTableView>();
                foreach (var column in table.TableColumns())
                {
                    if (columnsToHide.Contains(column.Identifier.ToLower()))
                    {
                        column.Hidden = !showColumns;
                    }
                }
                break;

            case RomListSettingsPageViewModel.DisplayRomFileNameForTitlePropertyName:
                var programs = RomsArrayController.ArrangedObjects();
                foreach (var programObject in programs)
                {
                    var program = programObject as ProgramDescriptionViewModel;
                    program.RaiseChangeValueForKey("Name");
                }
                break;

            default:
                break;
            }
        }
        private void RemoveObjectsFromArrayController(IEnumerable <NSObject> objectsToRemove)
        {
            foreach (var item in objectsToRemove)
            {
                DebugItemChange("removed " + item + " of type " + item.GetType().FullName);
                RomsArrayController.RemoveObject(item);
            }
            var selectedItemsToRemove = objectsToRemove.Intersect(View.ViewModel.CurrentSelection.OfType <NSObject>());

            if (selectedItemsToRemove.Any())
            {
                foreach (var item in selectedItemsToRemove.ToList())
                {
                    View.ViewModel.CurrentSelection.Remove(item as ProgramDescriptionViewModel);
                }
                var selectedObjects = RomsArrayController.SelectionIndexes.Select(i => RomsArrayController.ArrangedObjects()[i]);
                var itemsToAdd      = selectedObjects.Except(View.ViewModel.CurrentSelection);
                foreach (var item in itemsToAdd)
                {
                    View.ViewModel.CurrentSelection.Add((ProgramDescriptionViewModel)item);
                }
            }
        }
        /// <summary>
        /// Gets the ViewModel of the ROM at a specific row in the ROMs table.
        /// </summary>
        /// <param name="row">The row number for which to get the viewmodel object.</param>
        /// <returns>The program viewmodel at the given row.</returns>
        internal ProgramDescriptionViewModel GetObjectAtRow(int row)
        {
            var programViewModel = RomsArrayController.ArrangedObjects().ToList()[row] as ProgramDescriptionViewModel;

            return(programViewModel);
        }