From 518c9192e4445d82f192edcccb2ffb64ffc88a65 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Wed, 23 Dec 2020 00:24:11 +0200 Subject: ColorSpace per stop implemented on PPC. Synchronization only when values change. Volume open for all. RGB to closest catalog item... --- .../Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs | 161 ++++++++--------- .../Tango.PPC.Jobs/ViewModels/JobsViewVM.cs | 10 +- .../PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml | 83 ++++----- .../Printing/DefaultPrintingManager.cs | 9 + .../Visual_Studio/PPC/Tango.PPC.UI/app.manifest | 2 +- .../Tango.BL/Builders/CatalogsCollectionBuilder.cs | 31 ++++ .../Visual_Studio/Tango.BL/Entities/BrushStop.cs | 71 ++++++-- .../Tango.BL/Entities/ColorCatalog.cs | 20 +++ .../Tango.BL/Entities/ColorCatalogsGroup.cs | 8 + .../ColorCatalogItemsExtensions.cs | 23 +++ Software/Visual_Studio/Tango.BL/Tango.BL.csproj | 3 +- .../Tango.Integration/Operation/MachineOperator.cs | 193 +++++++++++---------- .../Tango.Touch/Controls/TouchAutoComplete.xaml | 2 +- .../Tango.Touch/Controls/TouchNumericTextBox.cs | 17 +- 14 files changed, 383 insertions(+), 250 deletions(-) create mode 100644 Software/Visual_Studio/Tango.BL/ExtensionMethods/ColorCatalogItemsExtensions.cs (limited to 'Software/Visual_Studio') diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs index 5e90d3b5b..e8af7c957 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs @@ -37,6 +37,7 @@ using Tango.PPC.Storage; using System.IO; using Tango.ColorConversion; using Tango.Integration.Operation; +using Tango.BL.Enumerations; namespace Tango.PPC.Jobs.ViewModels { @@ -188,39 +189,16 @@ namespace Tango.PPC.Jobs.ViewModels set { _isJobDetailsExpanded = value; RaisePropertyChangedAuto(); } } - private List _catalogItems; - /// - /// Gets or sets the twine catalog items. - /// - public List CatalogItems - { - get { return _catalogItems; } - set { _catalogItems = value; RaisePropertyChangedAuto(); } - } - - private ColorCatalogsItem _selectedCatalogItem; - /// - /// Gets or sets the selected catalog item. - /// - public ColorCatalogsItem SelectedCatalogItem - { - get { return _selectedCatalogItem; } - set { _selectedCatalogItem = value; RaisePropertyChangedAuto(); } - } - /// /// Gets or sets the twine catalog automatic complete provider. /// public IAutoCompleteProvider CatalogAutoCompleteProvider { get; set; } - private ColorCatalog _selectedCatalog; - /// - /// Gets or sets the selected catalog. - /// - public ColorCatalog SelectedCatalog + private List _availableCatalogs; + public List AvailableCatalogs { - get { return _selectedCatalog; } - set { _selectedCatalog = value; RaisePropertyChangedAuto(); } + get { return _availableCatalogs; } + set { _availableCatalogs = value; RaisePropertyChangedAuto(); } } #endregion @@ -362,7 +340,6 @@ namespace Tango.PPC.Jobs.ViewModels FineTuneItems = new ObservableCollection(); ApprovalFineTuneItems = new ObservableCollection(); - CatalogItems = new List(); CustomersAutoCompleteProvider = new AutoCompleteProvider((customer, filter) => { @@ -471,33 +448,17 @@ namespace Tango.PPC.Jobs.ViewModels LogManager.Log("Loading RMLS..."); Rmls = (await new RmlsCollectionBuilder(_db).SetAll().WithActiveParametersGroup().WithCAT(Job.MachineGuid).WithCCT().WithLiquidFactors().WithSpools().ForHeadType(MachineProvider.Machine.MachineHeadType).ForSite(MachineProvider.Machine.SiteGuid).BuildAsync()).ToList(); LogManager.Log("Loading Color Spaces..."); - ColorSpaces = await _db.ColorSpaces.ToListAsync(); + ColorSpaces = await _db.ColorSpaces.Where(x => x.Code != (int)BL.Enumerations.ColorSpaces.CMYK).ToListAsync(); LogManager.Log("Loading Spool Types..."); SpoolTypes = await _db.SpoolTypes.ToListAsync(); LogManager.Log("Loading Customers..."); Customers = await _db.Customers.Where(x => x.OrganizationGuid == MachineProvider.Machine.OrganizationGuid).ToListAsync(); - if (Job.ColorSpace.Space == BL.Enumerations.ColorSpaces.Catalog) - { - SelectedCatalog = await new CatalogBuilder(_db).Set(Job.ColorCatalogGuid).WithGroups().WithItems().BuildAsync(); - - if (SelectedCatalog != null) - { - CatalogItems = SelectedCatalog.ColorCatalogsGroups.SelectMany(x => x.ColorCatalogsItems).OrderBy(x => x.ItemIndex).ToList(); - } - else - { - await NotificationProvider.ShowError("The selected color catalog for this job could not be found.\nCannot load job."); - Job = null; - _can_navigate_back = true; - await NavigationManager.NavigateBack(); - return; - } - } + AvailableCatalogs = await new CatalogsCollectionBuilder(_db).SetAll().WithGroups().WithItems().ForSite(MachineProvider.Machine.SiteGuid).BuildListAsync(); foreach (var segment in Job.Segments) { - SetSegmentLiquidVolumesIfVolume(segment); + SetSegmentLiquidVolumes(segment); } if (!_check_gamut_thread.IsAlive) @@ -540,6 +501,8 @@ namespace Tango.PPC.Jobs.ViewModels ValidateBrushStops(); + CoerceBrushStopsColorSpaceChange(); + DyeCommand.RaiseCanExecuteChanged(); StartSampleDyeCommand.RaiseCanExecuteChanged(); StartFineTuningCommand.RaiseCanExecuteChanged(); @@ -718,7 +681,8 @@ namespace Tango.PPC.Jobs.ViewModels { LogManager.Log("Adding new solid segment..."); var s = Job.AddSolidSegment(Settings.DefaultSegmentLength > 0 ? Settings.DefaultSegmentLength : 10); - SetSegmentLiquidVolumesIfVolume(s); + SetSegmentLiquidVolumes(s); + CoerceBrushStopsColorSpaceChange(); return s; } catch (Exception ex) @@ -738,7 +702,8 @@ namespace Tango.PPC.Jobs.ViewModels { LogManager.Log("Adding new gradient segment..."); var s = Job.AddGradientSegment(Settings.DefaultSegmentLength > 0 ? Settings.DefaultSegmentLength : 10); - SetSegmentLiquidVolumesIfVolume(s); + SetSegmentLiquidVolumes(s); + CoerceBrushStopsColorSpaceChange(); return s; } catch (Exception ex) @@ -811,19 +776,16 @@ namespace Tango.PPC.Jobs.ViewModels /// Sets the segment liquid volumes. /// /// The segment. - private void SetSegmentLiquidVolumesIfVolume(Segment segment) + private void SetSegmentLiquidVolumes(Segment segment) { - if (Job.ColorSpace.Code == BL.Enumerations.ColorSpaces.Volume.ToInt32()) + foreach (var stop in segment.BrushStops) { - foreach (var stop in segment.BrushStops) - { - stop.SetLiquidVolumes(Job.Machine.Configuration, Job.Rml, Job.Rml.GetActiveProcessGroup().ProcessParametersTables.FirstOrDefault()); + stop.SetLiquidVolumes(Job.Machine.Configuration, Job.Rml, Job.Rml.GetActiveProcessGroup().ProcessParametersTables.FirstOrDefault()); - var lub = stop.LiquidVolumes.FirstOrDefault(x => x.IdsPack.LiquidType.Code == (int)BL.Enumerations.LiquidTypes.Lubricant); - if (lub != null) - { - lub.Volume = 100; - } + var lub = stop.LiquidVolumes.FirstOrDefault(x => x.IdsPack.LiquidType.Code == (int)BL.Enumerations.LiquidTypes.Lubricant); + if (lub != null) + { + lub.Volume = 100; } } } @@ -844,6 +806,24 @@ namespace Tango.PPC.Jobs.ViewModels #region Brush Stops Management + private void CoerceBrushStopsColorSpaceChange() + { + if (Job != null) + { + foreach (var stop in Job.Segments.SelectMany(x => x.BrushStops).ToList()) + { + stop.ColorSpaceChanged -= Stop_ColorSpaceChanged; + stop.ColorSpaceChanged += Stop_ColorSpaceChanged; + } + } + } + + private void Stop_ColorSpaceChanged(object sender, ColorSpace e) + { + BrushStop stop = sender as BrushStop; + stop.Segment.BrushStops.Where(x => x != stop).ToList().ForEach(x => x.ColorSpace = stop.ColorSpace); + } + /// /// Adds a new brush stop to the specified segment. /// @@ -852,7 +832,8 @@ namespace Tango.PPC.Jobs.ViewModels { LogManager.Log($"Adding new brush stop to segment {segment.SegmentIndex}."); segment.AddBrushStop(); - SetSegmentLiquidVolumesIfVolume(segment); + SetSegmentLiquidVolumes(segment); + CoerceBrushStopsColorSpaceChange(); } /// @@ -987,34 +968,56 @@ namespace Tango.PPC.Jobs.ViewModels { if (stop != null && stop.ColorSpace != null) { - stop.Corrected = false; - stop.OutOfGamutChecked = false; + if (stop.BrushColorSpace == BL.Enumerations.ColorSpaces.Catalog) return; - if (stop.BrushColorSpace == BL.Enumerations.ColorSpaces.Volume) + _volumeConversionTimer.ResetReplace(() => { - _volumeConversionTimer.ResetReplace(() => + + try { - try - { - var output = _converter.Convert(stop, false); + var output = _converter.Convert(stop, false); + if (stop.BrushColorSpace == BL.Enumerations.ColorSpaces.Volume) + { stop.Red = output.SingleCoordinates.Red; stop.Green = output.SingleCoordinates.Green; stop.Blue = output.SingleCoordinates.Blue; + stop.L = output.SingleCoordinates.L; + stop.A = output.SingleCoordinates.A; + stop.B = output.SingleCoordinates.B; stop.Corrected = true; stop.IsOutOfGamut = false; - - InvokeUI(() => - { - DyeCommand.RaiseCanExecuteChanged(); - }); } - catch (Exception ex) + else if (stop.BrushColorSpace == BL.Enumerations.ColorSpaces.LAB) { - LogManager.Log(ex, "An error occurred while trying to get volume => RGB from conversion engine."); + output.ApplyOnBrushStopVolumesOnly(stop); + stop.Corrected = false; + stop.OutOfGamutChecked = false; } - }); - } + else if (stop.BrushColorSpace == BL.Enumerations.ColorSpaces.RGB) + { + output.ApplyOnBrushStopVolumesOnly(stop); + stop.Corrected = false; + stop.OutOfGamutChecked = false; + } + + try + { + var closestItem = AvailableCatalogs.SelectMany(x => x.AllItemsOrdered).GetClosestItem(stop.Color); + stop.ColorCatalog = closestItem.ColorCatalogsGroup.ColorCatalog; + stop.ColorCatalogsItem = closestItem; + } + catch { } + + InvokeUI(() => DyeCommand.RaiseCanExecuteChanged()); + } + catch (Exception ex) + { + LogManager.Log(ex, "An error occurred while trying to get volume => RGB from conversion engine."); + } + + }); + } } @@ -1027,7 +1030,7 @@ namespace Tango.PPC.Jobs.ViewModels var catalogItem = await NavigationManager.NavigateForResult(new TwineCatalogNavigationObject() { SelectedItem = stop.ColorCatalogsItem, - Catalog = SelectedCatalog + Catalog = stop.ColorCatalog }, true); if (catalogItem != null) @@ -1298,9 +1301,9 @@ namespace Tango.PPC.Jobs.ViewModels { Thread.Sleep(500); - if (Job != null && Job.Rml.Cct != null && IsVisible && (Job.ColorSpace != null && (Job.ColorSpace.Code == BL.Enumerations.ColorSpaces.RGB.ToInt32() || Job.ColorSpace.Code == BL.Enumerations.ColorSpaces.LAB.ToInt32()))) + if (Job != null && Job.Rml.Cct != null && IsVisible) { - var brushStops = Job.Segments.SelectMany(x => x.BrushStops).Where(x => !x.Corrected && !x.OutOfGamutChecked).ToList(); + var brushStops = Job.Segments.SelectMany(x => x.BrushStops).Where(x => (x.BrushColorSpace == BL.Enumerations.ColorSpaces.LAB || x.BrushColorSpace == BL.Enumerations.ColorSpaces.RGB) && !x.Corrected && !x.OutOfGamutChecked).ToList(); foreach (var stop in brushStops) { diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs index 64931cbe3..23e381206 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs @@ -314,11 +314,11 @@ namespace Tango.PPC.Jobs.ViewModels /// The job. public async void SelectJob(Job job, bool directlyToEdit = false) { - if (!ApplicationManager.IsInTechnicianMode && job.ColorSpace != null && job.ColorSpace.Code == ColorSpaces.Volume.ToInt32()) - { - await NotificationProvider.ShowError("The selected job is supported only in technician mode."); - return; - } + //if (!ApplicationManager.IsInTechnicianMode && job.ColorSpace != null && job.ColorSpace.Code == ColorSpaces.Volume.ToInt32()) + //{ + // await NotificationProvider.ShowError("The selected job is supported only in technician mode."); + // return; + //} LogManager.Log($"Job '{job.Name}' selected."); diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml index 6a94034db..467c3f72b 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml @@ -65,33 +65,34 @@ - - - + + + - - - - + + + + - - - + + + - + + - + @@ -149,32 +150,21 @@ - + - + - + - + - + - - - - - - Transparent - - - - - @@ -215,9 +205,6 @@ - @@ -303,8 +290,12 @@ - - + + + + + + @@ -380,7 +360,7 @@ - + @@ -507,8 +487,7 @@ Job Details - , - + diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Printing/DefaultPrintingManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/Printing/DefaultPrintingManager.cs index 1f2895f26..b3fcd1208 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Printing/DefaultPrintingManager.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Printing/DefaultPrintingManager.cs @@ -58,14 +58,23 @@ namespace Tango.PPC.UI.Printing #else try { + _notificationProvider.SetGlobalBusyMessage("Processing job..."); handler = await _machineProvider.MachineOperator.Print(job); + _notificationProvider.ReleaseGlobalBusyMessage(); } catch (InsufficientLiquidQuantityException ex) { + _notificationProvider.ReleaseGlobalBusyMessage(); LogManager.Log(ex); await _notificationProvider.ShowDialog(new InsufficientLiquidQuantityViewVM(ex)); throw ex; } + catch (Exception ex) + { + _notificationProvider.ReleaseGlobalBusyMessage(); + LogManager.Log(ex); + throw ex; + } #endif handler.Completed += async (x, e) => diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/app.manifest b/Software/Visual_Studio/PPC/Tango.PPC.UI/app.manifest index d72e75011..efc5f8179 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/app.manifest +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/app.manifest @@ -16,7 +16,7 @@ Remove this element if your application requires this virtualization for backwards compatibility. --> - + diff --git a/Software/Visual_Studio/Tango.BL/Builders/CatalogsCollectionBuilder.cs b/Software/Visual_Studio/Tango.BL/Builders/CatalogsCollectionBuilder.cs index fb690eb99..dd9e9a54c 100644 --- a/Software/Visual_Studio/Tango.BL/Builders/CatalogsCollectionBuilder.cs +++ b/Software/Visual_Studio/Tango.BL/Builders/CatalogsCollectionBuilder.cs @@ -37,5 +37,36 @@ namespace Tango.BL.Builders } }); } + + public virtual CatalogsCollectionBuilder WithGroups() + { + return AddQueryStep(2, (query) => + { + return query.Include(x => x.ColorCatalogsGroups); + }); + } + + public virtual CatalogsCollectionBuilder WithItems() + { + return AddQueryStep(3, (query) => + { + return query.Include(x => x.ColorCatalogsGroups.Select(y => y.ColorCatalogsItems)); + }); + } + + public virtual CatalogsCollectionBuilder WithRecipes(Rml rml = null) + { + return AddQueryStep(4, (query) => + { + if (rml != null) + { + return query.Include(x => x.ColorCatalogsGroups.Select(y => y.ColorCatalogsItems.Select(z => z.ColorCatalogsItemsRecipes.Where(r => r.RmlGuid == rml.Guid)))); + } + else + { + return query.Include(x => x.ColorCatalogsGroups.Select(y => y.ColorCatalogsItems.Select(z => z.ColorCatalogsItemsRecipes))); + } + }); + } } } diff --git a/Software/Visual_Studio/Tango.BL/Entities/BrushStop.cs b/Software/Visual_Studio/Tango.BL/Entities/BrushStop.cs index 4ad21d4cd..9f47aca05 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/BrushStop.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/BrushStop.cs @@ -164,7 +164,24 @@ namespace Tango.BL.Entities [JsonIgnore] public Color Color { - get { return Color.FromRgb((byte)_red, (byte)_green, (byte)_blue); } + get + { + if (ColorSpace != null && BrushColorSpace == ColorSpaces.Catalog) + { + if (ColorCatalogsItem != null) + { + return Color.FromRgb((byte)ColorCatalogsItem.Red, (byte)ColorCatalogsItem.Green, (byte)ColorCatalogsItem.Blue); + } + else + { + return Colors.White; + } + } + else + { + return Color.FromRgb((byte)_red, (byte)_green, (byte)_blue); + } + } set { Rgb rgb = new Rgb(value.R, value.G, value.B); @@ -555,12 +572,6 @@ namespace Tango.BL.Entities Rgb rgb = new Rgb(Red, Green, Blue); Cmyk cmyk = new Cmyk(Cyan, Magenta, Yellow, Black); Lab lab = new Lab(L, A, B); - Rgb rgb_catalog = new Rgb(255, 255, 255); - - if (ColorCatalogsItem != null) - { - rgb_catalog = new Rgb(ColorCatalogsItem.Red, ColorCatalogsItem.Green, ColorCatalogsItem.Blue); - } switch ((ColorSpaces)ColorSpace.Code) { @@ -577,9 +588,35 @@ namespace Tango.BL.Entities cmyk = lab.To(); break; case ColorSpaces.Catalog: - cmyk = rgb_catalog.To(); - lab = rgb_catalog.To(); - rgb = rgb_catalog; + + if (ColorCatalogsItem != null) + { + rgb = new Rgb(ColorCatalogsItem.Red, ColorCatalogsItem.Green, ColorCatalogsItem.Blue); + lab = new Lab(ColorCatalogsItem.L, ColorCatalogsItem.A, ColorCatalogsItem.B); + cmyk = new Cmyk(ColorCatalogsItem.Cyan, ColorCatalogsItem.Magenta, ColorCatalogsItem.Yellow, ColorCatalogsItem.Black); + + try + { + if (LiquidVolumes != null) + { + var cyan = LiquidVolumes.FirstOrDefault(x => x.LiquidType == LiquidTypes.Cyan); + if (cyan != null) cyan.Volume = ColorCatalogsItem.Cyan; + + var magenta = LiquidVolumes.FirstOrDefault(x => x.LiquidType == LiquidTypes.Magenta); + if (magenta != null) magenta.Volume = ColorCatalogsItem.Magenta; + + var yellow = LiquidVolumes.FirstOrDefault(x => x.LiquidType == LiquidTypes.Yellow); + if (yellow != null) yellow.Volume = ColorCatalogsItem.Yellow; + + var black = LiquidVolumes.FirstOrDefault(x => x.LiquidType == LiquidTypes.Black); + if (black != null) black.Volume = ColorCatalogsItem.Black; + } + } + catch (Exception ex) + { + Debug.WriteLine(ex); + } + } Validate(null); break; } @@ -722,6 +759,12 @@ namespace Tango.BL.Entities Corrected = false; IsOutOfGamut = false; } + + _ignorePropChanged = true; + RaisePropertyChanged(nameof(Color)); + RaisePropertyChanged(nameof(Brush)); + Segment?.RaiseSegmentBrushChanged(); + _ignorePropChanged = false; } #endregion @@ -770,10 +813,10 @@ namespace Tango.BL.Entities { base.OnValidating(context); - if (BrushColorSpace == ColorSpaces.Catalog && ColorCatalogsItem == null) - { - InsertError(nameof(ColorCatalogsItem), "Please specify a color code."); - } + //if (BrushColorSpace == ColorSpaces.Catalog && ColorCatalogsItem == null) + //{ + // InsertError(nameof(ColorCatalogsItem), "Please specify a color code."); + //} } #endregion diff --git a/Software/Visual_Studio/Tango.BL/Entities/ColorCatalog.cs b/Software/Visual_Studio/Tango.BL/Entities/ColorCatalog.cs index 82b88f156..9972a0c2d 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/ColorCatalog.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/ColorCatalog.cs @@ -34,5 +34,25 @@ namespace Tango.BL.Entities { get { return ColorCatalogsGroups.OrderBy(x => x.GroupIndex).ToObservableCollection(); } } + + [JsonIgnore] + [NotMapped] + public List AllItemsOrdered + { + get { return ColorCatalogsGroupsOrdered.SelectMany(x => x.ColorCatalogsItemsOrdered).ToList(); } + } + + public ColorCatalogsItem GetClosestItem(Color color) + { + var minDiff = AllItemsOrdered.Select(x => x.Color).Select(n => ColorDiff(n, color)).Min(n => n); + return AllItemsOrdered.FirstOrDefault(n => ColorDiff(n.Color, color) == minDiff); + } + + private int ColorDiff(Color c1, Color c2) + { + return (int)Math.Sqrt((c1.R - c2.R) * (c1.R - c2.R) + + (c1.G - c2.G) * (c1.G - c2.G) + + (c1.B - c2.B) * (c1.B - c2.B)); + } } } diff --git a/Software/Visual_Studio/Tango.BL/Entities/ColorCatalogsGroup.cs b/Software/Visual_Studio/Tango.BL/Entities/ColorCatalogsGroup.cs index 17f6115d1..86d82c634 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/ColorCatalogsGroup.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/ColorCatalogsGroup.cs @@ -1,6 +1,7 @@ using Newtonsoft.Json; using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Text; @@ -31,6 +32,13 @@ namespace Tango.BL.Entities } } + [JsonIgnore] + [NotMapped] + public ObservableCollection ColorCatalogsItemsOrdered + { + get { return ColorCatalogsItems.OrderBy(x => x.ItemIndex).ToObservableCollection(); } + } + public override void Delete(ObservablesContext context) { base.Delete(context); diff --git a/Software/Visual_Studio/Tango.BL/ExtensionMethods/ColorCatalogItemsExtensions.cs b/Software/Visual_Studio/Tango.BL/ExtensionMethods/ColorCatalogItemsExtensions.cs new file mode 100644 index 000000000..2a548371e --- /dev/null +++ b/Software/Visual_Studio/Tango.BL/ExtensionMethods/ColorCatalogItemsExtensions.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media; +using Tango.BL.Entities; + +public static class ColorCatalogItemsExtensions +{ + public static ColorCatalogsItem GetClosestItem(this IEnumerable items, Color color) + { + var minDiff = items.Select(x => x.Color).Select(n => ColorDiff(n, color)).Min(n => n); + return items.FirstOrDefault(n => ColorDiff(n.Color, color) == minDiff); + } + + private static int ColorDiff(Color c1, Color c2) + { + return (int)Math.Sqrt((c1.R - c2.R) * (c1.R - c2.R) + + (c1.G - c2.G) * (c1.G - c2.G) + + (c1.B - c2.B) * (c1.B - c2.B)); + } +} diff --git a/Software/Visual_Studio/Tango.BL/Tango.BL.csproj b/Software/Visual_Studio/Tango.BL/Tango.BL.csproj index dc817af6e..0fbf6c5ab 100644 --- a/Software/Visual_Studio/Tango.BL/Tango.BL.csproj +++ b/Software/Visual_Studio/Tango.BL/Tango.BL.csproj @@ -427,6 +427,7 @@ + @@ -645,7 +646,7 @@ - + \ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs index bce386bfe..ada7a4b73 100644 --- a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs +++ b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs @@ -2408,150 +2408,153 @@ namespace Tango.Integration.Operation /// /// The job. /// - public Task Print(Job job) + public async Task Print(Job job) { - IColorConverter converter = new DefaultColorConverter(); - - var jobSegments = job.OrderedSegments; + ProcessParametersTable processParameters = null; - if (job.Rml == null) + await Task.Factory.StartNew(() => { - throw new NullReferenceException("Job RML is null"); - } + IColorConverter converter = new DefaultColorConverter(); - var processGroup = job.Rml.ProcessParametersTablesGroups.FirstOrDefault(x => x.Active); + var jobSegments = job.OrderedSegments; - if (processGroup == null) - { - throw new NullReferenceException("Could not locate an active process parameters tables group for RML " + job.Rml.Name); - } + if (job.Rml == null) + { + throw new NullReferenceException("Job RML is null"); + } - ProcessParametersTable processParameters = null; + var processGroup = job.Rml.ProcessParametersTablesGroups.FirstOrDefault(x => x.Active); - try - { - processParameters = converter.GetRecommendedProcessParameters(job); - } - catch (Exception ex) - { - throw LogManager.Log(new InvalidOperationException($"An error occurred while trying to resolve the recommended process parameters.\n{ex.Message}")); - } + if (processGroup == null) + { + throw new NullReferenceException("Could not locate an active process parameters tables group for RML " + job.Rml.Name); + } - if (processParameters == null) - { - throw new NullReferenceException("Could not locate any process parameters table in group " + processGroup.Name + " for RML " + job.Rml.Name); - } + try + { + processParameters = converter.GetRecommendedProcessParameters(job); + } + catch (Exception ex) + { + throw LogManager.Log(new InvalidOperationException($"An error occurred while trying to resolve the recommended process parameters.\n{ex.Message}")); + } - //Perform color correction - foreach (var stop in jobSegments.SelectMany(x => x.BrushStops)) - { - //if (stop.LiquidVolumes == null || stop.BrushColorSpace == ColorSpaces.Volume) - //{ - if (stop.BrushColorSpace == ColorSpaces.RGB || stop.BrushColorSpace == ColorSpaces.LAB) + if (processParameters == null) { - var output = converter.Convert(stop, false); + throw new NullReferenceException("Could not locate any process parameters table in group " + processGroup.Name + " for RML " + job.Rml.Name); + } - //TODO: Restore this when Mirta conversion is working as expected. - //if (suggestions.OutOfGamut) + //Perform color correction + foreach (var stop in jobSegments.SelectMany(x => x.BrushStops)) + { + //if (stop.LiquidVolumes == null || stop.BrushColorSpace == ColorSpaces.Volume) //{ - // throw new InvalidOperationException("Cannot print a brush stop which is out of gamut."); - //} - - stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); - - foreach (var outputLiquid in output.SingleCoordinates.OutputLiquids) + if (stop.BrushColorSpace == ColorSpaces.RGB || stop.BrushColorSpace == ColorSpaces.LAB) { - var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack.LiquidType.Code == outputLiquid.LiquidType.ToInt32()); + var output = converter.Convert(stop, false); - if (liquidVolume == null) - { - throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + outputLiquid.LiquidType + "'."); - } + //TODO: Restore this when Mirta conversion is working as expected. + //if (suggestions.OutOfGamut) + //{ + // throw new InvalidOperationException("Cannot print a brush stop which is out of gamut."); + //} - liquidVolume.Volume = outputLiquid.Volume; - } - } - else if (stop.BrushColorSpace == ColorSpaces.Catalog) - { - if (stop.ColorCatalogsItem != null) - { stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); + foreach (var outputLiquid in output.SingleCoordinates.OutputLiquids) { - var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.LiquidType == LiquidTypes.Cyan); + var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack.LiquidType.Code == outputLiquid.LiquidType.ToInt32()); if (liquidVolume == null) { - throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Cyan + "'."); + throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + outputLiquid.LiquidType + "'."); } - liquidVolume.Volume = stop.ColorCatalogsItem.Cyan; + liquidVolume.Volume = outputLiquid.Volume; } - + } + else if (stop.BrushColorSpace == ColorSpaces.Catalog) + { + if (stop.ColorCatalogsItem != null) { - var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.LiquidType == LiquidTypes.Magenta); + stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); - if (liquidVolume == null) { - throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Magenta + "'."); - } + var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.LiquidType == LiquidTypes.Cyan); - liquidVolume.Volume = stop.ColorCatalogsItem.Magenta; - } + if (liquidVolume == null) + { + throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Cyan + "'."); + } - { - var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.LiquidType == LiquidTypes.Yellow); + liquidVolume.Volume = stop.ColorCatalogsItem.Cyan; + } - if (liquidVolume == null) { - throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Yellow + "'."); - } + var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.LiquidType == LiquidTypes.Magenta); - liquidVolume.Volume = stop.ColorCatalogsItem.Yellow; - } + if (liquidVolume == null) + { + throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Magenta + "'."); + } - { - var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.LiquidType == LiquidTypes.Black); + liquidVolume.Volume = stop.ColorCatalogsItem.Magenta; + } - if (liquidVolume == null) { - throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Black + "'."); + var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.LiquidType == LiquidTypes.Yellow); + + if (liquidVolume == null) + { + throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Yellow + "'."); + } + + liquidVolume.Volume = stop.ColorCatalogsItem.Yellow; } - liquidVolume.Volume = stop.ColorCatalogsItem.Black; + { + var liquidVolume = stop.LiquidVolumes.SingleOrDefault(x => x.LiquidType == LiquidTypes.Black); + + if (liquidVolume == null) + { + throw new NullReferenceException("Liquid volume not found for color conversion output liquid '" + LiquidTypes.Black + "'."); + } + + liquidVolume.Volume = stop.ColorCatalogsItem.Black; + } + } + else if (!stop.IsTransparent) + { + throw new InvalidOperationException($"No catalog item specified for segment color."); + } + else + { + stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); } } - else if (!stop.IsTransparent) + else if (stop.BrushColorSpace == ColorSpaces.Volume) { - throw new InvalidOperationException($"No catalog item specified for segment color."); + stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); } else { - stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); + throw new InvalidOperationException($"Unsupported color space {stop.BrushColorSpace}."); } - } - else if (stop.BrushColorSpace == ColorSpaces.Volume) - { - stop.SetLiquidVolumes(job.Machine.Configuration, job.Rml, processParameters); - } - else - { - throw new InvalidOperationException($"Unsupported color space {stop.BrushColorSpace}."); - } - //} - - if (job.EnableLubrication) - { - var lubricantVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack != null && x.IdsPack.LiquidType != null && x.LiquidType == LiquidTypes.Lubricant); + //} - if (lubricantVolume != null) + if (job.EnableLubrication) { - lubricantVolume.Volume = 100; + var lubricantVolume = stop.LiquidVolumes.SingleOrDefault(x => x.IdsPack != null && x.IdsPack.LiquidType != null && x.LiquidType == LiquidTypes.Lubricant); + + if (lubricantVolume != null) + { + lubricantVolume.Volume = 100; + } } } - } + }); - return Print(job, processParameters); + return await Print(job, processParameters); } /// diff --git a/Software/Visual_Studio/Tango.Touch/Controls/TouchAutoComplete.xaml b/Software/Visual_Studio/Tango.Touch/Controls/TouchAutoComplete.xaml index da8580488..b0b78c177 100644 --- a/Software/Visual_Studio/Tango.Touch/Controls/TouchAutoComplete.xaml +++ b/Software/Visual_Studio/Tango.Touch/Controls/TouchAutoComplete.xaml @@ -138,7 +138,7 @@ - + - - - + + + + @@ -66,11 +68,8 @@ - - - - + @@ -81,7 +80,7 @@ - + @@ -104,7 +103,7 @@ - + @@ -114,7 +113,7 @@ - + diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Controls/JobSummeryViewer.xaml.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Controls/JobSummeryViewer.xaml.cs index 1c0b90f91..c977e71d0 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Controls/JobSummeryViewer.xaml.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Controls/JobSummeryViewer.xaml.cs @@ -23,6 +23,18 @@ namespace Tango.PPC.Jobs.Controls /// public partial class JobSummeryViewer : UserControl { + + /// + /// Gets or sets the job. + /// + public Job Job + { + get { return (Job)GetValue(JobProperty); } + set { SetValue(JobProperty, value); } + } + public static readonly DependencyProperty JobProperty = + DependencyProperty.Register("Job", typeof(Job), typeof(JobSummeryViewer), new PropertyMetadata(null)); + /// /// Maybe not necessary! /// diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs index e8af7c957..cfac759dd 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs @@ -422,6 +422,14 @@ namespace Tango.PPC.Jobs.ViewModels if (_db != null) { + if (Job != null) + { + foreach (var stop in Job.Segments.SelectMany(x => x.BrushStops).ToList()) + { + stop.ColorSpaceChanged -= Stop_ColorSpaceChanged; + } + } + Rmls.ForEach(x => x.Cct = null); Rmls = null; _db.Dispose(); diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobSummeryView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobSummeryView.xaml index 4785805a6..ddda98df9 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobSummeryView.xaml +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobSummeryView.xaml @@ -92,7 +92,7 @@ - + diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml index 467c3f72b..c1472793a 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml @@ -51,7 +51,7 @@ - + @@ -118,11 +118,11 @@ - - - - - - - - - - - - - - - - - - - + - - - - - - - - Segment # - - - + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + - + - + - - - - - + + + + + + + - - - - - - + + + + - + + - - - - - - + + + + + + + + - ADD COLOR + ADD COLOR + + - - + + - - - + + + @@ -465,11 +466,6 @@ - - - - - @@ -706,7 +702,11 @@ - + + + + + diff --git a/Software/Visual_Studio/Tango.SharedUI/Components/LazyBinding.cs b/Software/Visual_Studio/Tango.SharedUI/Components/LazyBinding.cs new file mode 100644 index 000000000..e8e22d182 --- /dev/null +++ b/Software/Visual_Studio/Tango.SharedUI/Components/LazyBinding.cs @@ -0,0 +1,160 @@ +using System; +using System.ComponentModel; +using System.Globalization; +using System.Windows; +using System.Windows.Data; +using System.Windows.Markup; + +namespace Tango.SharedUI.Components +{ + [MarkupExtensionReturnType(typeof(object))] + public class LazyBindingExtension : MarkupExtension + { + public LazyBindingExtension() + { } + + public LazyBindingExtension(PropertyPath path) : this() + { + Path = path; + } + + #region Properties + + public IValueConverter Converter { get; set; } + [TypeConverter(typeof(CultureInfoIetfLanguageTagConverter))] + public CultureInfo ConverterCulture { get; set; } + public object ConverterParamter { get; set; } + public string ElementName { get; set; } + [ConstructorArgument("path")] + public PropertyPath Path { get; set; } + public RelativeSource RelativeSource { get; set; } + public object Source { get; set; } + public UpdateSourceTrigger UpdateSourceTrigger { get; set; } + public bool ValidatesOnDataErrors { get; set; } + public bool ValidatesOnExceptions { get; set; } + public bool ValidatesOnNotifyDataErrors { get; set; } + + private Binding binding; + private UIElement bindingTarget; + private DependencyProperty bindingTargetProperty; + + #endregion + + #region Init + + public override object ProvideValue(IServiceProvider serviceProvider) + { + var valueProvider = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; + if (valueProvider != null) + { + bindingTarget = valueProvider.TargetObject as UIElement; + + if (bindingTarget == null) + { + throw new NotSupportedException($"Target '{valueProvider.TargetObject}' is not valid for a LazyBinding. The LazyBinding target must be a UIElement."); + } + + bindingTargetProperty = valueProvider.TargetProperty as DependencyProperty; + + if (bindingTargetProperty == null) + { + throw new NotSupportedException($"The property '{valueProvider.TargetProperty}' is not valid for a LazyBinding. The LazyBinding target property must be a DependencyProperty."); + } + + binding = new Binding + { + Path = Path, + Converter = Converter, + ConverterCulture = ConverterCulture, + ConverterParameter = ConverterParamter + }; + + if (ElementName != null) + { + binding.ElementName = ElementName; + } + + if (RelativeSource != null) + { + binding.RelativeSource = RelativeSource; + } + + if (Source != null) + { + binding.Source = Source; + } + + binding.UpdateSourceTrigger = UpdateSourceTrigger; + binding.ValidatesOnDataErrors = ValidatesOnDataErrors; + binding.ValidatesOnExceptions = ValidatesOnExceptions; + binding.ValidatesOnNotifyDataErrors = ValidatesOnNotifyDataErrors; + + return SetBinding(); + } + + return null; + } + + public object SetBinding() + { + bindingTarget.IsVisibleChanged += UiElement_IsVisibleChanged; + + updateBinding(); + + return bindingTarget.GetValue(bindingTargetProperty); + } + + #endregion + + #region Event Handlers + + private void UiElement_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) + { + updateBinding(); + } + + #endregion + + #region Update Binding + + private void updateBinding() + { + if (bindingTarget.IsVisible) + { + ConsolidateBinding(); + } + else + { + ClearBinding(); + } + } + + private bool _isBind; + + private void ConsolidateBinding() + { + if (_isBind) + { + return; + } + + _isBind = true; + + BindingOperations.SetBinding(bindingTarget, bindingTargetProperty, binding); + } + + private void ClearBinding() + { + if (!_isBind) + { + return; + } + + BindingOperations.ClearBinding(bindingTarget, bindingTargetProperty); + + _isBind = false; + } + + #endregion + } +} diff --git a/Software/Visual_Studio/Tango.SharedUI/Controls/FastTextBlock.cs b/Software/Visual_Studio/Tango.SharedUI/Controls/FastTextBlock.cs index 141fa6e27..07005a0f4 100644 --- a/Software/Visual_Studio/Tango.SharedUI/Controls/FastTextBlock.cs +++ b/Software/Visual_Studio/Tango.SharedUI/Controls/FastTextBlock.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Globalization; using System.Linq; using System.Text; @@ -30,6 +31,23 @@ namespace Tango.SharedUI.Controls public FastTextBlock() { Loaded += FastTextBlock_Loaded; + + DependencyPropertyDescriptor fontFamilyPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(FastTextBlock.FontFamilyProperty, typeof(FastTextBlock)); + fontFamilyPropertyDescriptor.AddValueChanged(this, OnPropertyChangedInit); + + DependencyPropertyDescriptor fontSizePropertyDescriptor = DependencyPropertyDescriptor.FromProperty(FastTextBlock.FontSizeProperty, typeof(FastTextBlock)); + fontSizePropertyDescriptor.AddValueChanged(this, OnPropertyChangedInit); + + DependencyPropertyDescriptor fontWeightPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(FastTextBlock.FontWeightProperty, typeof(FastTextBlock)); + fontWeightPropertyDescriptor.AddValueChanged(this, OnPropertyChangedInit); + + DependencyPropertyDescriptor ForegroundPropertyDescriptor = DependencyPropertyDescriptor.FromProperty(FastTextBlock.ForegroundProperty, typeof(FastTextBlock)); + ForegroundPropertyDescriptor.AddValueChanged(this, OnPropertyChangedInit); + } + + private void OnPropertyChangedInit(object sender, EventArgs e) + { + Init(); } private void FastTextBlock_Loaded(object sender, RoutedEventArgs e) diff --git a/Software/Visual_Studio/Tango.SharedUI/Tango.SharedUI.csproj b/Software/Visual_Studio/Tango.SharedUI/Tango.SharedUI.csproj index e4dc72746..5d9592a26 100644 --- a/Software/Visual_Studio/Tango.SharedUI/Tango.SharedUI.csproj +++ b/Software/Visual_Studio/Tango.SharedUI/Tango.SharedUI.csproj @@ -67,6 +67,7 @@ + @@ -261,7 +262,7 @@ - + \ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Touch/Controls/LightTouchScrollViewer.xaml b/Software/Visual_Studio/Tango.Touch/Controls/LightTouchScrollViewer.xaml index 7cc38666e..e0e8f485c 100644 --- a/Software/Visual_Studio/Tango.Touch/Controls/LightTouchScrollViewer.xaml +++ b/Software/Visual_Studio/Tango.Touch/Controls/LightTouchScrollViewer.xaml @@ -25,9 +25,9 @@ - + diff --git a/Software/Visual_Studio/Tango.Touch/Controls/TouchComboBox.xaml b/Software/Visual_Studio/Tango.Touch/Controls/TouchComboBox.xaml index 738fe6a3c..83163fcd8 100644 --- a/Software/Visual_Studio/Tango.Touch/Controls/TouchComboBox.xaml +++ b/Software/Visual_Studio/Tango.Touch/Controls/TouchComboBox.xaml @@ -31,7 +31,7 @@ - diff --git a/Software/Visual_Studio/Tango.Touch/Controls/TouchVirtualizedContentReplaceControl.cs b/Software/Visual_Studio/Tango.Touch/Controls/TouchVirtualizedContentReplaceControl.cs new file mode 100644 index 000000000..802d3f538 --- /dev/null +++ b/Software/Visual_Studio/Tango.Touch/Controls/TouchVirtualizedContentReplaceControl.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Markup; +using System.Windows.Shapes; +using System.Windows.Threading; +using Tango.Core.Threading; + +namespace Tango.Touch.Controls +{ + [ContentProperty(nameof(Content))] + public class TouchVirtualizedContentReplaceControl : Control + { + private LightTouchScrollViewer _scrollViewer; + private Border _innerBorder; + private ActionTimer _updateTimer; + private Point _location; + private bool _loaded; + private Image _replaceContent; + private FrameworkElement _element; + private INameScopeDictionary _parentNameScope; + + public DataTemplate Content + { + get { return (DataTemplate)GetValue(ContentProperty); } + set { SetValue(ContentProperty, value); } + } + public static readonly DependencyProperty ContentProperty = + DependencyProperty.Register("Content", typeof(DataTemplate), typeof(TouchVirtualizedContentReplaceControl), new PropertyMetadata(null)); + + public bool CanMovePosition + { + get { return (bool)GetValue(CanMovePositionProperty); } + set { SetValue(CanMovePositionProperty, value); } + } + public static readonly DependencyProperty CanMovePositionProperty = + DependencyProperty.Register("CanMovePosition", typeof(bool), typeof(TouchVirtualizedContentReplaceControl), new PropertyMetadata(false)); + + public LightTouchDataGrid DataGrid + { + get { return (LightTouchDataGrid)GetValue(DataGridProperty); } + set { SetValue(DataGridProperty, value); } + } + public static readonly DependencyProperty DataGridProperty = + DependencyProperty.Register("DataGrid", typeof(LightTouchDataGrid), typeof(TouchVirtualizedContentReplaceControl), new PropertyMetadata(null)); + + public bool Disconnect + { + get { return (bool)GetValue(DisconnectProperty); } + set { SetValue(DisconnectProperty, value); } + } + public static readonly DependencyProperty DisconnectProperty = + DependencyProperty.Register("Disconnect", typeof(bool), typeof(TouchVirtualizedContentReplaceControl), new PropertyMetadata(true)); + + static TouchVirtualizedContentReplaceControl() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(TouchVirtualizedContentReplaceControl), new FrameworkPropertyMetadata(typeof(TouchVirtualizedContentReplaceControl))); + } + + public TouchVirtualizedContentReplaceControl() + { + _replaceContent = new Image(); + _updateTimer = new ActionTimer(TimeSpan.FromMilliseconds(100)); + Loaded += TouchVirtualizedContentControl_Loaded; + } + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + _innerBorder = GetTemplateChild("PART_innerBorder") as Border; + _innerBorder.Child = _replaceContent; + } + + private void TouchVirtualizedContentControl_Loaded(object sender, System.Windows.RoutedEventArgs e) + { + _scrollViewer = this.FindAncestor(); + _scrollViewer.Scrolling += _scrollViewer_Scrolling; + + _parentNameScope = NameScope.GetNameScope(this.FindAncestor()) as INameScopeDictionary; + + if (DataGrid != null) + { + DataGrid.SortingChanged += DataGrid_SortingChanged; + DataGrid.FilterChanged += DataGrid_FilterChanged; + } + + _location = this.TranslatePoint(new Point(0, 0), _scrollViewer.GetContentGrid()); + + _scrollViewer.GetContentGrid().SizeChanged += TouchVirtualizedContentControl_SizeChanged; + + ApplyVirtualization(); + _loaded = true; + } + + private void DataGrid_FilterChanged(object sender, EventArgs e) + { + InvalidateVirtualization(); + } + + private void DataGrid_SortingChanged(object sender, EventArgs e) + { + InvalidateVirtualization(); + } + + private void TouchVirtualizedContentControl_SizeChanged(object sender, SizeChangedEventArgs e) + { + InvalidateVirtualization(); + } + + private void _scrollViewer_Scrolling(object sender, DoubleValueChangedEventArgs e) + { + if (_loaded) + { + ApplyVirtualization(); + } + } + + private void InvalidateVirtualization() + { + _updateTimer.ResetReplace(() => + { + Dispatcher.Invoke(new Action(() => + { + _location = this.TranslatePoint(new Point(0, 0), _scrollViewer.GetContentGrid()); + ApplyVirtualization(); + })); + }); + } + + private void ApplyVirtualization() + { + if (!Disconnect && _element != null) + { + _updateTimer.Dispose(); + return; + } + + var _border_viewport = _scrollViewer.GetViewportBorder(); + + if (CanMovePosition) + { + _location = this.TranslatePoint(new Point(0, 0), _scrollViewer.GetContentGrid()); + } + + Rect bounds = new Rect(_location.X, _location.Y, ActualWidth, ActualHeight); + Rect rect = new Rect(0.0, _scrollViewer.GetScrollPosition(), _border_viewport.ActualWidth, _border_viewport.ActualHeight); + + if (_innerBorder != null) + { + if (bounds.IntersectsWith(rect)) + { + if (Disconnect || _element == null) + { + if (_innerBorder.Child == _replaceContent || _element == null) + { + _element = Content.LoadContent() as FrameworkElement; + + if (_parentNameScope != null) + { + NameScope.SetNameScope(_element, _parentNameScope); + } + + _innerBorder.Child = _element; + _innerBorder.Height = double.NaN; + } + } + } + else + { + if (Disconnect) + { + if (_innerBorder.Child == _element) + { + double height = _element != null ? _element.ActualHeight : MinHeight; + _innerBorder.Child = _replaceContent; + _innerBorder.Height = height; + } + } + } + } + } + } +} diff --git a/Software/Visual_Studio/Tango.Touch/Controls/TouchVirtualizedContentReplaceControl.xaml b/Software/Visual_Studio/Tango.Touch/Controls/TouchVirtualizedContentReplaceControl.xaml new file mode 100644 index 000000000..c7fe39b76 --- /dev/null +++ b/Software/Visual_Studio/Tango.Touch/Controls/TouchVirtualizedContentReplaceControl.xaml @@ -0,0 +1,15 @@ + + + + + \ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Touch/Tango.Touch.csproj b/Software/Visual_Studio/Tango.Touch/Tango.Touch.csproj index 7dd560a48..8575548c4 100644 --- a/Software/Visual_Studio/Tango.Touch/Tango.Touch.csproj +++ b/Software/Visual_Studio/Tango.Touch/Tango.Touch.csproj @@ -101,6 +101,7 @@ + @@ -277,6 +278,10 @@ Designer MSBuild:Compile + + MSBuild:Compile + Designer + Designer MSBuild:Compile @@ -422,7 +427,7 @@ - + \ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Touch/Themes/Generic.xaml b/Software/Visual_Studio/Tango.Touch/Themes/Generic.xaml index ed0f289b0..47403f56b 100644 --- a/Software/Visual_Studio/Tango.Touch/Themes/Generic.xaml +++ b/Software/Visual_Studio/Tango.Touch/Themes/Generic.xaml @@ -46,6 +46,7 @@ + -- cgit v1.3.1