// Return true if there is a non-empty value available public bool IsCopyFromLastNonEmptyValuePossible(DataEntryControl control) { // Check the arguments for null ThrowIf.IsNullArgument(control, nameof(control)); bool checkCounter = control is DataEntryCounter; bool checkFlag = control is DataEntryFlag; int nearestRowWithCopyableValue = -1; for (int fileIndex = this.ImageCache.CurrentRow - 1; fileIndex >= 0; fileIndex--) { // Search for the row with some value in it, starting from the previous row string valueToCopy = this.FileDatabase.FileTable[fileIndex].GetValueDatabaseString(control.DataLabel); if (String.IsNullOrWhiteSpace(valueToCopy) == false) { // for flags, we skip over falses // for counters, we skip over 0 // for all others, any value will work as long as its not null or white space if ((checkFlag && !valueToCopy.Equals("false")) || (checkCounter && !valueToCopy.Equals("0")) || (!checkCounter && !checkFlag)) { nearestRowWithCopyableValue = fileIndex; // We found a non-empty value break; } } } return(nearestRowWithCopyableValue >= 0); }
// Checks whether the image is completely black public static unsafe bool IsBlack(this WriteableBitmap image) { // Check the arguments for null ThrowIf.IsNullArgument(image, nameof(image)); // The RGB offsets from the beginning of the pixel (i.e., 0, 1 or 2) WriteableBitmapExtensions.GetColorOffsets(image, out int blueOffset, out int greenOffset, out int redOffset); // examine only a subset of pixels as otherwise this is an expensive operation // check pixels from last to first as most cameras put a non-black status bar or at least non-black text at the bottom of the frame, // so reverse order may be a little faster on average in cases of nighttime images with black skies // TODO Calculate pixelStride as a function of image size so future high res images will still be processed quickly. byte *currentPixel = (byte *)image.BackBuffer.ToPointer(); // the imageIndex will point to a particular byte in the pixel array int pixelStride = Constant.ImageValues.DarkPixelSampleStrideDefault; int totalPixels = image.PixelHeight * image.PixelWidth; // total number of pixels in the image for (int pixelIndex = totalPixels - 1; pixelIndex > 0; pixelIndex -= pixelStride) { // get next pixel of interest byte b = *(currentPixel + blueOffset); byte g = *(currentPixel + greenOffset); byte r = *(currentPixel + redOffset); if (r != 0 || b != 0 || g != 0) { return(false); } } return(true); }
public DateTimeSetTimeZone(FileDatabase fileDatabase, ImageRow imageToCorrect, Window owner) { // Check the arguments for null ThrowIf.IsNullArgument(fileDatabase, nameof(fileDatabase)); ThrowIf.IsNullArgument(imageToCorrect, nameof(imageToCorrect)); this.InitializeComponent(); this.displayingPreview = false; this.fileDatabase = fileDatabase; this.Owner = owner; // get the image's current time DateTimeOffset currentDateTime = imageToCorrect.DateTimeIncorporatingOffset; this.originalDate.Content = DateTimeHandler.ToStringDisplayDateTimeUtcOffset(currentDateTime); // get the image filename and display it this.FileName.Content = imageToCorrect.File; this.FileName.ToolTip = this.FileName.Content; // display the image this.image.Source = imageToCorrect.LoadBitmap(this.fileDatabase.FolderPath, out bool isCorruptOrMissing); // configure timezone picker TimeZoneInfo imageSetTimeZone = this.fileDatabase.ImageSet.GetSystemTimeZone(); this.TimeZones.SelectedItem = imageSetTimeZone.DisplayName; this.TimeZones.SelectionChanged += this.TimeZones_SelectionChanged; }
// Copy the current value of this control to all images protected virtual void MenuItemCopyCurrentValueToAll_Click(object sender, RoutedEventArgs e) { // Check the arguments for null ThrowIf.IsNullArgument(sender, nameof(sender)); // Get the chosen data entry control DataEntryControl control = (DataEntryControl)((MenuItem)sender).Tag; if (control == null) { return; } // Display a dialog box that explains what will happen. Arguments indicate how many files will be affected, and is tuned to the type of control bool checkForZero = control is DataEntryCounter; int filesAffected = this.FileDatabase.CountAllCurrentlySelectedFiles; if (Dialogs.DataEntryConfirmCopyCurrentValueToAllDialog(Application.Current.MainWindow, control.Content, filesAffected, checkForZero) != true) { return; } // Update all files to match the value of the control (identified by the data label) in the currently selected image row. Mouse.OverrideCursor = Cursors.Wait; ImageRow imageRow = (this.ThumbnailGrid.IsVisible == false) ? this.ImageCache.Current : this.FileDatabase.FileTable[this.ThumbnailGrid.GetSelected()[0]]; this.FileDatabase.UpdateFiles(imageRow, control.DataLabel); Mouse.OverrideCursor = null; }
public PopulateFieldWithEpisodeData(Window owner, FileDatabase fileDatabase) : base(owner) { ThrowIf.IsNullArgument(fileDatabase, nameof(fileDatabase)); this.dataLabelByLabel = new Dictionary <string, string>(); this.fileDatabase = fileDatabase; this.InitializeComponent(); }
public ChooseFileDatabaseFile(string[] fileDatabasePaths, string templateDatabasePath, Window owner) { // Check the arguments for null ThrowIf.IsNullArgument(fileDatabasePaths, nameof(fileDatabasePaths)); this.InitializeComponent(); this.Owner = owner; this.SelectedFile = String.Empty; // file_names contains an array of .ddb files. We add each to the listbox. // by default, the first item in the listbox is shown selected. int defaultDatabaseIndex = 0; string templateDatabaseNameWithoutExtension = Path.GetFileNameWithoutExtension(templateDatabasePath); for (int index = 0; index < fileDatabasePaths.Length; ++index) { string databaseName = Path.GetFileName(fileDatabasePaths[index]); string databaseNameWithoutExtension = Path.GetFileNameWithoutExtension(databaseName); if (String.Equals(databaseNameWithoutExtension, templateDatabaseNameWithoutExtension, StringComparison.OrdinalIgnoreCase)) { defaultDatabaseIndex = index; } this.FileDatabases.Items.Add(databaseName); } this.FileDatabases.SelectedIndex = defaultDatabaseIndex; }
// Return the index of this row in the dataTable public int GetIndex(DataTable dataTable) { // Check the arguments for null ThrowIf.IsNullArgument(dataTable, nameof(dataTable)); return(dataTable.Rows.IndexOf(this.Row)); }
// ColumnTuple: columnName = field public void SetWhere(ColumnTuple columnTuple, string field) { // Check the arguments for null ThrowIf.IsNullArgument(columnTuple, nameof(columnTuple)); this.Where = String.Format("{0} = {1}", columnTuple.Name, Sql.Quote(field)); }
// Paste the contents of the clipboard into the current or selected controls // Note that we don't do any checks against the control's type, as that would be handled by the menu enablement protected virtual void MenuItemPasteFromClipboard_Click(object sender, RoutedEventArgs e) { // Check the arguments for null ThrowIf.IsNullArgument(sender, nameof(sender)); // Get the chosen data entry control DataEntryControl control = (DataEntryControl)((MenuItem)sender).Tag; if (control == null) { return; } string newContent = Clipboard.GetText().Trim(); if (control is DataEntryCounter _) { // For counters, removing any leading 0's, but if this ends up with an empty string, then revert to 0 newContent = newContent.TrimStart(new Char[] { '0' }); if (string.IsNullOrEmpty(newContent)) { newContent = "0"; } } control.SetContentAndTooltip(newContent); this.UpdateRowsDependingOnThumbnailGridState(control.DataLabel, newContent); }
public void SetSortTerm(SortTerm sortTerm1, SortTerm sortTerm2) { // Check the arguments for null ThrowIf.IsNullArgument(sortTerm1, nameof(sortTerm1)); ThrowIf.IsNullArgument(sortTerm2, nameof(sortTerm2)); this.SortTerms = String.Join(",", sortTerm1.DataLabel, sortTerm1.DisplayLabel, sortTerm1.ControlType, sortTerm1.IsAscending, sortTerm2.DataLabel, sortTerm2.DisplayLabel, sortTerm2.ControlType, sortTerm2.IsAscending); }
// Create the interface public DateTimeLinearCorrection(Window owner, FileDatabase fileDatabase) : base(owner) { // Check the arguments for null ThrowIf.IsNullArgument(fileDatabase, nameof(fileDatabase)); this.InitializeComponent(); this.fileDatabase = fileDatabase; }
public BoundingBox(string coordinates, float confidence, string detectionCategory, string detectionLabel, List <KeyValuePair <string, string> > classifications) { // Check the arguments for null ThrowIf.IsNullArgument(coordinates, nameof(coordinates)); float[] coords = Array.ConvertAll(coordinates.Split(','), s => float.Parse(s, CultureInfo.InvariantCulture)); this.SetValues(coords[0], coords[1], coords[2], coords[3], confidence, detectionCategory, detectionLabel, classifications); }
// Delete the quickPasteEntry from the quickPasteEntries list public static List <QuickPasteEntry> DeleteQuickPasteEntry(List <QuickPasteEntry> quickPasteEntries, QuickPasteEntry quickPasteEntry) { // Check the arguments for null ThrowIf.IsNullArgument(quickPasteEntries, nameof(quickPasteEntries)); quickPasteEntries.RemoveAll(x => x.Equals(quickPasteEntry)); return(quickPasteEntries); }
/// <summary> /// Given a ControlRow (i.e., a template row definitions) construct a column for its data based on the /// - the control type (Note, Date, File etc) /// - its DataLabel /// </summary> /// <param name="control"></param> protected FileTableColumn(ControlRow control) { // Check the arguments for null ThrowIf.IsNullArgument(control, nameof(control)); this.ControlType = control.Type; this.DataLabel = control.DataLabel; }
public FileTableChoiceColumn(ControlRow control) : base(control) { // Check the arguments for null ThrowIf.IsNullArgument(control, nameof(control)); this.choices = control.GetChoices(false); this.defaultValue = control.DefaultValue; }
public DateTimeOffset GetDateTime(int dateTimeSearchTermIndex, TimeZoneInfo imageSetTimeZone) { // Check the arguments for null ThrowIf.IsNullArgument(imageSetTimeZone, nameof(imageSetTimeZone)); DateTime dateTime = this.SearchTerms[dateTimeSearchTermIndex].GetDateTime(); return(DateTimeHandler.FromDatabaseDateTimeIncorporatingOffset(dateTime, imageSetTimeZone.GetUtcOffset(dateTime))); }
public ImageRow NewRow(FileInfo file) { // Check the arguments for null ThrowIf.IsNullArgument(file, nameof(file)); DataRow row = this.DataTable.NewRow(); row[Constant.DatabaseColumn.File] = file.Name; return(FileTable.CreateRow(row)); }
public ExceptionShutdownDialog(Window owner, string programName, UnhandledExceptionEventArgs unhandledExceptionArgs) { // Check the arguments for null ThrowIf.IsNullArgument(unhandledExceptionArgs, nameof(unhandledExceptionArgs)); this.Owner = owner; this.ProgramName = programName; this.UnhandledExceptionArgs = unhandledExceptionArgs; InitializeComponent(); }
public DateTimeFixedCorrection(Window owner, FileDatabase fileDatabase, ImageRow imageToCorrect) : base(owner) { // Check the arguments for null ThrowIf.IsNullArgument(fileDatabase, nameof(fileDatabase)); ThrowIf.IsNullArgument(imageToCorrect, nameof(imageToCorrect)); this.InitializeComponent(); this.fileDatabase = fileDatabase; this.ImageToCorrect = imageToCorrect; }
public DateCorrectAmbiguous(Window owner, FileDatabase fileDatabase) : base(owner) { // Check the arguments for null ThrowIf.IsNullArgument(fileDatabase, nameof(fileDatabase)); this.InitializeComponent(); this.fileDatabase = fileDatabase; this.ambiguousDatesList = new List <AmbiguousDateRange>(); this.DateChangeFeedback.FolderPath = fileDatabase.FolderPath; }
public static DateTime GetDateTimeField(this DataRow row, string column) { // Check the arguments for null ThrowIf.IsNullArgument(row, nameof(row)); DateTime dateTime = (DateTime)row[column]; Debug.Assert(dateTime.Kind == DateTimeKind.Utc, String.Format("Unexpected kind {0} for date time {1}.", dateTime.Kind, dateTime)); return(dateTime); }
public static List <SortTerm> GetSortTerms(List <SearchTerm> searchTerms) { // Check the arguments for null ThrowIf.IsNullArgument(searchTerms, nameof(searchTerms)); List <SortTerm> sortTerms = new List <SortTerm>(); // Constraints. // - the SearchTerms list excludes Id, Date, Time and Folder. It also includes two DateTime copies of DateTime // - Add Id // - Exclude Date and Time (as we only use DateTime): although the UTC Offset is not calculated in. While limiting, we suspect that users will not care in practice. // - Exclude UTCOffset, as that would involve UTCOffset complication. // - Remove the 2nd DateTiime // - Add Id as it is missing bool firstDateTimeSeen = false; sortTerms.Add(new SortTerm(Constant.DatabaseColumn.ID, Constant.DatabaseColumn.ID, Sql.IntegerType, Constant.BooleanValue.True)); foreach (SearchTerm searchTerm in searchTerms) { // Necessary modifications: // - Exclude UtcOffset, RelativePath // - Exclude Date, Time, Folder (they shouldn't be in the SearchTerm list, but just in case) if (searchTerm.DataLabel == Constant.DatabaseColumn.Folder || searchTerm.DataLabel == Constant.DatabaseColumn.Date || searchTerm.DataLabel == Constant.DatabaseColumn.Time || searchTerm.DataLabel == Constant.DatabaseColumn.UtcOffset) { continue; } if (searchTerm.DataLabel == Constant.DatabaseColumn.File) { sortTerms.Add(new SortTerm(searchTerm.DataLabel, Constant.SortTermValues.FileDisplayLabel, searchTerm.ControlType, Constant.BooleanValue.True)); } else if (searchTerm.DataLabel == Constant.DatabaseColumn.DateTime) { // Skip the second DateTime if (firstDateTimeSeen == true) { continue; } firstDateTimeSeen = true; sortTerms.Add(new SortTerm(searchTerm.DataLabel, Constant.SortTermValues.DateDisplayLabel, searchTerm.ControlType, Constant.BooleanValue.True)); } if (searchTerm.DataLabel == Constant.DatabaseColumn.RelativePath) { sortTerms.Add(new SortTerm(searchTerm.DataLabel, Constant.SortTermValues.RelativePathDisplayLabel, searchTerm.ControlType, Constant.BooleanValue.True)); } else { sortTerms.Add(new SortTerm(searchTerm.DataLabel, searchTerm.Label, searchTerm.ControlType, Constant.BooleanValue.True)); } } return(sortTerms); }
/// <summary> /// Check if a synchronization between the given control row and this instance's control row is needed, /// which wojld occur if any field differs. /// Note: As a side effect it also re-orders this instance's ControlOrder and SpreadsheetOrder to the other's order if needed /// </summary> /// <param name="controlRowToMatch"></param> /// <returns></returns> public bool TryUpdateThisControlRowToMatch(ControlRow controlRowToMatch) { // Check the arguments for null ThrowIf.IsNullArgument(controlRowToMatch, nameof(controlRowToMatch)); bool synchronizationMadeChanges = false; if (this.Copyable != controlRowToMatch.Copyable) { this.Copyable = controlRowToMatch.Copyable; synchronizationMadeChanges = true; } if (this.ControlOrder != controlRowToMatch.ControlOrder) { this.ControlOrder = controlRowToMatch.ControlOrder; synchronizationMadeChanges = true; } if (this.DefaultValue != controlRowToMatch.DefaultValue) { this.DefaultValue = controlRowToMatch.DefaultValue; synchronizationMadeChanges = true; } if (this.Label != controlRowToMatch.Label) { this.Label = controlRowToMatch.Label; synchronizationMadeChanges = true; } if (this.List != controlRowToMatch.List) { this.List = controlRowToMatch.List; synchronizationMadeChanges = true; } if (this.SpreadsheetOrder != controlRowToMatch.SpreadsheetOrder) { this.SpreadsheetOrder = controlRowToMatch.SpreadsheetOrder; synchronizationMadeChanges = true; } if (this.Tooltip != controlRowToMatch.Tooltip) { this.Tooltip = controlRowToMatch.Tooltip; synchronizationMadeChanges = true; } if (this.Visible != controlRowToMatch.Visible) { this.Visible = controlRowToMatch.Visible; synchronizationMadeChanges = true; } if (this.Width != controlRowToMatch.Width) { this.Width = controlRowToMatch.Width; synchronizationMadeChanges = true; } return(synchronizationMadeChanges); }
public DateDaylightSavingsTimeCorrection(Window owner, FileDatabase database, FileTableEnumerator fileEnumerator) : base(owner) { // Check the arguments for null ThrowIf.IsNullArgument(database, nameof(database)); ThrowIf.IsNullArgument(fileEnumerator, nameof(fileEnumerator)); this.InitializeComponent(); this.fileDatabase = database; this.fileEnumerator = fileEnumerator; this.currentImageRow = fileEnumerator.CurrentRow; }
public ImageQuality(ImageRow image) { // Check the arguments for null ThrowIf.IsNullArgument(image, nameof(image)); this.Bitmap = null; this.DarkPixelRatioFound = 0; this.FileName = image.File; this.IsColor = false; this.OldImageQuality = image.ImageQuality; this.NewImageQuality = null; }
public DateTimeRereadFromFiles(Window owner, FileDatabase fileDatabase) : base(owner) { // Check the arguments for null ThrowIf.IsNullArgument(fileDatabase, nameof(fileDatabase)); this.InitializeComponent(); this.fileDatabase = fileDatabase; // Tracks whether any changes to the data or database are made this.IsAnyDataUpdated = false; }
// Given three images, return an image that highlights the differences in common betwen the main image and the first image // and the main image and a second image. public static unsafe WriteableBitmap CombinedDifference(this WriteableBitmap unaltered, WriteableBitmap previous, WriteableBitmap next, byte threshold) { // Check the arguments for null ThrowIf.IsNullArgument(unaltered, nameof(unaltered)); ThrowIf.IsNullArgument(previous, nameof(previous)); ThrowIf.IsNullArgument(next, nameof(next)); if (WriteableBitmapExtensions.BitmapsMismatched(unaltered, previous) || WriteableBitmapExtensions.BitmapsMismatched(unaltered, next)) { return(null); } WriteableBitmapExtensions.GetColorOffsets(unaltered, out int blueOffset, out int greenOffset, out int redOffset); int totalPixels = unaltered.PixelWidth * unaltered.PixelHeight; int pixelSizeInBytes = unaltered.Format.BitsPerPixel / 8; byte *unalteredIndex = (byte *)unaltered.BackBuffer.ToPointer(); byte *previousIndex = (byte *)previous.BackBuffer.ToPointer(); byte *nextIndex = (byte *)next.BackBuffer.ToPointer(); byte[] differencePixels = new byte[totalPixels * pixelSizeInBytes]; int differenceIndex = 0; for (int pixel = 0; pixel < totalPixels; ++pixel) { byte b1 = (byte)Math.Abs(*(unalteredIndex + blueOffset) - *(previousIndex + blueOffset)); byte g1 = (byte)Math.Abs(*(unalteredIndex + greenOffset) - *(previousIndex + greenOffset)); byte r1 = (byte)Math.Abs(*(unalteredIndex + redOffset) - *(previousIndex + redOffset)); byte b2 = (byte)Math.Abs(*(unalteredIndex + blueOffset) - *(nextIndex + blueOffset)); byte g2 = (byte)Math.Abs(*(unalteredIndex + greenOffset) - *(nextIndex + greenOffset)); byte r2 = (byte)Math.Abs(*(unalteredIndex + redOffset) - *(nextIndex + redOffset)); byte b = WriteableBitmapExtensions.DifferenceIfAboveThreshold(threshold, b1, b2); byte g = WriteableBitmapExtensions.DifferenceIfAboveThreshold(threshold, g1, g2); byte r = WriteableBitmapExtensions.DifferenceIfAboveThreshold(threshold, r1, r2); byte averageDifference = (byte)((b + g + r) / 3); differencePixels[differenceIndex + blueOffset] = averageDifference; differencePixels[differenceIndex + greenOffset] = averageDifference; differencePixels[differenceIndex + redOffset] = averageDifference; unalteredIndex += pixelSizeInBytes; previousIndex += pixelSizeInBytes; nextIndex += pixelSizeInBytes; differenceIndex += pixelSizeInBytes; } WriteableBitmap difference = new WriteableBitmap(BitmapSource.Create(unaltered.PixelWidth, unaltered.PixelHeight, unaltered.DpiX, unaltered.DpiY, unaltered.Format, unaltered.Palette, differencePixels, unaltered.BackBufferStride)); return(difference); }
public DateTimeRereadFromSelectedMetadataField(Window owner, FileDatabase fileDatabase, string filePath) : base(owner) { ThrowIf.IsNullArgument(fileDatabase, nameof(fileDatabase)); this.InitializeComponent(); this.fileDatabase = fileDatabase; this.filePath = filePath; // Store various states which will eventually be reset by the user this.metadataFieldName = String.Empty; this.metadataFieldSelected = false; this.noMetadataAvailable = true; }
public static void Configure(DateTimePicker dateTimePicker, Nullable <DateTime> defaultValue) { // Check the arguments for null ThrowIf.IsNullArgument(dateTimePicker, nameof(dateTimePicker)); dateTimePicker.AutoCloseCalendar = true; dateTimePicker.Format = DateTimeFormat.Custom; dateTimePicker.FormatString = Constant.Time.DateTimeDisplayFormat; dateTimePicker.TimeFormat = DateTimeFormat.Custom; dateTimePicker.TimeFormatString = Constant.Time.TimeFormat; dateTimePicker.CultureInfo = System.Globalization.CultureInfo.CreateSpecificCulture("en-US"); dateTimePicker.Value = defaultValue; }
// Copy the value of the current control to the clipboard protected virtual void MenuItemCopyToClipboard_Click(object sender, RoutedEventArgs e) { // Check the arguments for null ThrowIf.IsNullArgument(sender, nameof(sender)); // Get the chosen data entry control DataEntryControl control = (DataEntryControl)((MenuItem)sender).Tag; if (control == null) { return; } Clipboard.SetText(control.Content); }