Esempio n. 1
0
        /// <summary>
        /// Add user interface event handler callbacks for (possibly invisible) controls
        /// </summary>
        private void SetUserInterfaceCallbacks()
        {
            // Add data entry callbacks to all editable controls. When the user changes an image's attribute using a particular control,
            // the callback updates the matching field for that image in the database.
            DataEntryNote     date     = null;
            DataEntryDateTime dateTime = null;
            DataEntryNote     time     = null;

            foreach (KeyValuePair <string, DataEntryControl> pair in this.DataEntryControls.ControlsByDataLabel)
            {
                string controlType = this.DataHandler.FileDatabase.FileTableColumnsByDataLabel[pair.Key].ControlType;
                switch (controlType)
                {
                case Constant.Control.Counter:
                    DataEntryCounter counter = (DataEntryCounter)pair.Value;
                    counter.ContentControl.PreviewMouseDown += this.ContentControl_MouseDown;
                    counter.ContentControl.PreviewKeyDown   += this.ContentCtl_PreviewKeyDown;
                    counter.Container.MouseEnter            += this.CounterControl_MouseEnter;
                    counter.Container.MouseLeave            += this.CounterControl_MouseLeave;
                    counter.LabelControl.Click += this.CounterControl_Click;
                    break;

                case Constant.Control.Flag:
                case Constant.DatabaseColumn.DeleteFlag:
                    DataEntryFlag flag = (DataEntryFlag)pair.Value;
                    flag.ContentControl.PreviewMouseDown += this.ContentControl_MouseDown;
                    flag.ContentControl.PreviewKeyDown   += this.ContentCtl_PreviewKeyDown;
                    break;

                case Constant.Control.FixedChoice:
                case Constant.DatabaseColumn.ImageQuality:
                    DataEntryChoice choice = (DataEntryChoice)pair.Value;
                    choice.ContentControl.PreviewMouseDown += this.ContentControl_MouseDown;
                    choice.ContentControl.PreviewKeyDown   += this.ContentCtl_PreviewKeyDown;
                    break;

                case Constant.Control.Note:
                case Constant.DatabaseColumn.Date:
                case Constant.DatabaseColumn.File:
                case Constant.DatabaseColumn.Folder:
                case Constant.DatabaseColumn.RelativePath:
                case Constant.DatabaseColumn.Time:
                    DataEntryNote note = (DataEntryNote)pair.Value;
                    note.ContentControl.PreviewMouseDown += this.ContentControl_MouseDown;
                    note.ContentControl.PreviewKeyDown   += this.ContentCtl_PreviewKeyDown;
                    if (controlType == Constant.DatabaseColumn.Date)
                    {
                        date = note;
                    }
                    if (controlType == Constant.DatabaseColumn.Time)
                    {
                        time = note;
                    }
                    break;

                case Constant.DatabaseColumn.DateTime:
                    dateTime = (DataEntryDateTime)pair.Value;
                    dateTime.ContentControl.PreviewMouseDown += this.ContentControl_MouseDown;
                    dateTime.ContentControl.PreviewKeyDown   += this.ContentCtl_PreviewKeyDown;
                    break;

                case Constant.DatabaseColumn.UtcOffset:
                    DataEntryUtcOffset utcOffset = (DataEntryUtcOffset)pair.Value;
                    utcOffset.ContentControl.PreviewMouseDown += this.ContentControl_MouseDown;
                    utcOffset.ContentControl.PreviewKeyDown   += this.ContentCtl_PreviewKeyDown;
                    break;

                default:
                    TracePrint.PrintMessage(String.Format("Unhandled control type '{0}' in SetUserInterfaceCallbacks.", controlType));
                    break;
                }
            }

            // if needed, link date and time controls to datetime control
            if (dateTime != null && date != null)
            {
                dateTime.DateControl = date;
            }
            if (dateTime != null && time != null)
            {
                dateTime.TimeControl = time;
            }
        }
        public void CreateControls(FileDatabase database, DataEntryHandler dataEntryPropagator)
        {
            // Depending on how the user interacts with the file import process image set loading can be aborted after controls are generated and then
            // another image set loaded.  Any existing controls therefore need to be cleared.
            this.ControlGrid.Children.Clear();
            this.Controls.Clear();
            this.ControlsByDataLabel.Clear();

            DataEntryDateTime dateTimeControl = null;
            DataEntryUtcOffset utcOffsetControl = null;
            List<DataEntryControl> visibleControls = new List<DataEntryControl>();
            foreach (ControlRow control in database.Controls)
            {
                // no point in generating a control if it doesn't render in the UX
                if (control.Visible == false)
                {
                    continue;
                }

                if (control.Type == Constant.DatabaseColumn.DateTime)
                {
                    dateTimeControl = new DataEntryDateTime(control, this);
                    visibleControls.Add(dateTimeControl);
                }
                else if (control.Type == Constant.DatabaseColumn.File ||
                         control.Type == Constant.DatabaseColumn.RelativePath ||
                         control.Type == Constant.Control.Note)
                {
                    // standard controls rendering as notes aren't editable by the user
                    List<string> autocompletions = null;
                    bool readOnly = control.Type != Constant.Control.Note;
                    if (readOnly == false)
                    {
                        autocompletions = new List<string>(database.GetDistinctValuesInFileDataColumn(control.DataLabel));
                    }
                    DataEntryNote noteControl = new DataEntryNote(control, autocompletions, this);
                    noteControl.ContentReadOnly = readOnly;
                    visibleControls.Add(noteControl);
                }
                else if (control.Type == Constant.Control.Flag || control.Type == Constant.DatabaseColumn.DeleteFlag)
                {
                    DataEntryFlag flagControl = new DataEntryFlag(control, this);
                    visibleControls.Add(flagControl);
                }
                else if (control.Type == Constant.Control.Counter)
                {
                    DataEntryCounter counterControl = new DataEntryCounter(control, this);
                    visibleControls.Add(counterControl);
                }
                else if (control.Type == Constant.Control.FixedChoice || control.Type == Constant.DatabaseColumn.ImageQuality)
                {
                    DataEntryChoice choiceControl = new DataEntryChoice(control, this);
                    visibleControls.Add(choiceControl);
                }
                else if (control.Type == Constant.DatabaseColumn.UtcOffset)
                {
                    utcOffsetControl = new DataEntryUtcOffset(control, this);
                    visibleControls.Add(utcOffsetControl);
                }
                else
                {
                    Debug.Fail(String.Format("Unhandled control type {0}.", control.Type));
                    continue;
                }
            }

            if ((dateTimeControl != null) && (utcOffsetControl != null))
            {
                dateTimeControl.ShowUtcOffset();
                visibleControls.Remove(utcOffsetControl);
            }

            foreach (DataEntryControl control in visibleControls)
            {
                this.ControlGrid.Children.Add(control.Container);
                this.Controls.Add(control);
                this.ControlsByDataLabel.Add(control.DataLabel, control);
            }

            dataEntryPropagator.SetDataEntryCallbacks(this.ControlsByDataLabel);
        }
        // Show the image / video file for the specified row, but only if its different from what is currently being displayed.
        private void FileShow(int fileIndex, bool isInSliderNavigation, bool forceUpdate)
        {
            // If there is no image set open, or if there is no image to show, then show an image indicating the empty image set.
            if (this.IsFileDatabaseAvailable() == false || this.DataHandler.FileDatabase.CountAllCurrentlySelectedFiles < 1)
            {
                this.MarkableCanvas.SetNewImage(Constant.ImageValues.NoFilesAvailable.Value, null);
                this.markersOnCurrentFile = null;
                this.MarkableCanvas_UpdateMarkers();
                this.MarkableCanvas.SwitchToImageView();

                // We could invalidate the cache here, but it will be reset anyways when images are loaded.
                if (this.DataHandler != null)
                {
                    this.DataHandler.IsProgrammaticControlUpdate = false;
                }

                // We also need to do a bit of cleanup of UI elements that make no sense when there are no images to show.
                this.QuickPasteWindowHide();
                return;
            }

            // If we are already showing the desired file, and if we are not forcing an update,
            // then abort as there is no need to redisplay the image.
            if (this.DataHandler.ImageCache.CurrentRow == fileIndex && forceUpdate == false)
            {
                return;
            }

            this.DataEntryControls.AutocompletionUpdateWithCurrentRowValues();
            // for the bitmap caching logic below to work this should be the only place where code in TimelapseWindow moves the image enumerator
            if (this.DataHandler.ImageCache.TryMoveToFile(fileIndex, forceUpdate, out bool newFileToDisplay) == false)
            {
                if (this.DataHandler != null)
                {
                    this.DataHandler.IsProgrammaticControlUpdate = false;
                }
                // We used to throw a new exception, but lets see what happens if we just return instead.
                // i.e., lets just abort.
                // throw new Exception(String.Format("in FileShow: possible problem with fileIndex value is {0}, where its not a valid row index in the image table.", fileIndex));
                System.Diagnostics.Debug.Print(String.Format("in FileShow: possible problem with fileIndex (value is {0}, where its not a valid row index in the image table.", fileIndex));
                return;
            }

            // Reset the ThumbnailGrid to the current image
            // SAULXX: COULD SET FOLDER PATH AND FILEDATABASE ON LOAD, BUT MAY BE BETTER TO JUST KEEP ON DOING IT HERE
            // SAULXX: Note that this used to be before the above if statement. Not sure if it would be a problem having it here (in case of failur)
            this.MarkableCanvas.ThumbnailGrid.FolderPath          = this.FolderPath;
            this.MarkableCanvas.ThumbnailGrid.FileTableStartIndex = fileIndex;
            this.MarkableCanvas.ThumbnailGrid.FileTable           = this.DataHandler.FileDatabase.FileTable;

            // Update each control with the data for the now current image
            // This is always done as it's assumed either the image changed or that a control refresh is required due to database changes
            // the call to TryMoveToImage() above refreshes the data stored under this.dataHandler.ImageCache.Current.
            this.DataHandler.IsProgrammaticControlUpdate = true;
            foreach (KeyValuePair <string, DataEntryControl> control in this.DataEntryControls.ControlsByDataLabel)
            {
                // update value
                string controlType = this.DataHandler.FileDatabase.FileTableColumnsByDataLabel[control.Key].ControlType;
                control.Value.SetContentAndTooltip(this.DataHandler.ImageCache.Current.GetValueDisplayString(control.Value.DataLabel));

                // for note controls, update the autocomplete list if an edit occurred
                if (controlType == Constant.Control.Note)
                {
                    DataEntryNote noteControl = (DataEntryNote)control.Value;
                    if (noteControl.ContentChanged)
                    {
                        noteControl.ContentChanged = false;
                    }
                }
            }
            this.DataHandler.IsProgrammaticControlUpdate = false;

            // update the status bar to show which image we are on out of the total displayed under the current selection
            // the total is always refreshed as it's not known if FileShow() is being called due to a change in the selection
            this.StatusBar.SetCurrentFile(fileIndex + 1); // Add one because indexes are 0-based
            this.StatusBar.SetCount(this.DataHandler.FileDatabase.CountAllCurrentlySelectedFiles);
            this.StatusBar.ClearMessage();

            this.FileNavigatorSlider.Value = fileIndex + 1;

            // Get the bounding boxes and markers (if any) for the current image;
            BoundingBoxes bboxes = this.GetBoundingBoxesForCurrentFile(this.DataHandler.ImageCache.Current.ID);

            this.markersOnCurrentFile = this.DataHandler.FileDatabase.MarkersGetMarkersForCurrentFile(this.DataHandler.ImageCache.Current.ID);
            List <Marker> displayMarkers = this.GetDisplayMarkers();

            // Display new file if the file changed
            // This avoids unnecessary image reloads and refreshes in cases where FileShow() is just being called to refresh controls
            if (newFileToDisplay)
            {
                if (this.DataHandler.ImageCache.Current.IsVideo)
                {
                    this.MarkableCanvas.SetNewVideo(this.DataHandler.ImageCache.Current.GetFileInfo(this.DataHandler.FileDatabase.FolderPath), displayMarkers);
                    this.EnableImageManipulationMenus(false);
                }
                else
                {
                    this.MarkableCanvas.SetNewImage(this.DataHandler.ImageCache.GetCurrentImage, displayMarkers);
                    // Draw markers for this file
                    this.MarkableCanvas_UpdateMarkers();
                    this.MarkableCanvas.BoundingBoxes = bboxes;
                    this.EnableImageManipulationMenus(true);
                }
            }
            else if (this.IsDisplayingSingleImage())
            {
                if (this.DataHandler.ImageCache.Current.IsVideo)
                {
                    this.MarkableCanvas.SwitchToVideoView();
                }
                else
                {
                    this.MarkableCanvas.SwitchToImageView();
                    this.MarkableCanvas_UpdateMarkers();
                }
            }

            this.DataGridSelectionsTimer_Reset();

            // Set the file player status
            if (this.DataHandler.ImageCache.CurrentRow == 0)
            {
                this.FilePlayer.BackwardsControlsEnabled(false);
            }
            else
            {
                this.FilePlayer.BackwardsControlsEnabled(true);
            }

            if (this.DataHandler.ImageCache.CurrentRow == this.DataHandler.FileDatabase.CountAllCurrentlySelectedFiles - 1)
            {
                this.FilePlayer.ForwardsControlsEnabled(false);
            }
            else
            {
                this.FilePlayer.ForwardsControlsEnabled(true);
            }

            // Refresh the Magnifier if needed
            if (this.IsDisplayingSingleImage())
            {
                if (this.DataHandler.ImageCache.Current.IsVideo)
                {
                    this.MarkableCanvas.SetMagnifiersAccordingToCurrentState(false, true);
                }
                else
                {
                    this.MarkableCanvas.SetMagnifiersAccordingToCurrentState(true, false);
                }
            }


            // Refresh the CopyPreviousButton and its Previews as needed
            this.CopyPreviousValuesSetEnableStatePreviewsAndGlowsAsNeeded();

            // Refresh the QuickPasteEntry previews if needed
            if (this.IsDisplayingSingleImage() && this.quickPasteWindow != null)
            {
                this.quickPasteWindow.RefreshQuickPasteWindowPreviewAsNeeded();
            }

            // Refresh the markable canvas if needed
            this.MarkableCanvas.RefreshIfMultipleImagesAreDisplayed(isInSliderNavigation);

            // Display the episode and duplicate text as needed
            this.DisplayEpisodeTextInImageIfWarranted(fileIndex);
            this.DuplicateDisplayIndicatorInImageIfWarranted();
        }