aboutsummaryrefslogtreecommitdiffstats
path: root/Software
diff options
context:
space:
mode:
authorAvi Levkovich <avi@twine-s.com>2018-07-12 09:46:44 +0300
committerAvi Levkovich <avi@twine-s.com>2018-07-12 09:46:44 +0300
commitdec3cd03aec51dca67150e2f6ba76c7eda7f11a4 (patch)
tree97f8ee8efd166ab9578f1a4baf1b73c45961abb1 /Software
parent86b7dbca112046dea1d3dd7d2904440afc2acb7d (diff)
parent1fe6f6b50598fff4d52273138936031f3dee7866 (diff)
downloadTango-dec3cd03aec51dca67150e2f6ba76c7eda7f11a4.tar.gz
Tango-dec3cd03aec51dca67150e2f6ba76c7eda7f11a4.zip
Merge branch 'master' of https://twinetfs.visualstudio.com/_git/Tango
Diffstat (limited to 'Software')
-rw-r--r--Software/DB/Tango.mdfbin75497472 -> 75497472 bytes
-rw-r--r--Software/DB/Tango_log.ldfbin1572864 -> 1572864 bytes
-rw-r--r--Software/Embedded_SW/Embedded/Common/report/report.h2
-rw-r--r--Software/Embedded_SW/Embedded/Drivers/Uart_Comm/Uart.c8
-rw-r--r--Software/Embedded_SW/Embedded/Modules/AlarmHandling/Diagnostics.c2
-rw-r--r--Software/Embedded_SW/Embedded/Modules/Thread/Thread.h2
-rw-r--r--Software/Embedded_SW/Embedded/Modules/Thread/Thread_Winder.c82
-rw-r--r--Software/Embedded_SW/Embedded/Modules/Thread/Thread_init.c25
-rw-r--r--Software/Embedded_SW/Embedded/Modules/Thread/Thread_print.c49
-rw-r--r--Software/Embedded_SW/Embedded/StateMachines/Printing/JobSTM.c49
-rw-r--r--Software/Graphics/Mobile/sample-dye.pngbin0 -> 2120 bytes
-rw-r--r--Software/Graphics/Preloaders/preloader_rectangles.gifbin0 -> 11500 bytes
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorLab/ViewModels/MainViewVM.cs41
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorLab/Views/MainView.xaml73
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Resources/BuildDate.txt2
-rw-r--r--Software/Visual_Studio/Native/Tango.ColorLib/Utils/Interp.cpp10
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Controls/JobSummeryViewer.xaml9
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Controls/JobSummeryViewer.xaml.cs8
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/JobView/sample-dye.pngbin0 -> 2120 bytes
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Tango.PPC.Jobs.csproj3
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobProgressViewVM.cs19
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobSummeryViewVM.cs3
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs88
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs3
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobProgressView.xaml17
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobSummeryView.xaml2
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml83
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Navigation/INavigationBlocker.cs7
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/PPCViewModel.cs10
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Images/preloader_rectangles.gifbin0 -> 11500 bytes
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Navigation/DefaultNavigationManager.cs19
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs2
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj5
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LayoutView.xaml11
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LoginView.xaml5
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/AnimationCache.cs151
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifApplicationExtension.cs50
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifBlock.cs28
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifBlockKind.cs10
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifColor.cs25
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifCommentExtension.cs37
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifDecoderException.cs16
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifExtension.cs32
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifFile.cs86
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifFrame.cs47
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifGraphicControlExtension.cs52
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifHeader.cs38
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifHelpers.cs110
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifImageData.cs27
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifImageDescriptor.cs43
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifLogicalScreenDescriptor.cs43
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifPlainTextExtension.cs68
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifTrailer.cs21
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/ImageAnimationController.cs192
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/ImageBehavior.cs966
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Properties/AssemblyInfo.cs10
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Tango.AnimatedGif.csproj90
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/UserControl1.xaml12
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/UserControl1.xaml.cs28
-rw-r--r--Software/Visual_Studio/Tango.BL/ColorConversion/TangoColorConverter.cs5
-rw-r--r--Software/Visual_Studio/Tango.BL/Entities/HardwareMotor.cs6
-rw-r--r--Software/Visual_Studio/Tango.BL/Entities/Job.cs50
-rw-r--r--Software/Visual_Studio/Tango.BL/EntitiesExtensions/Job.cs16
-rw-r--r--Software/Visual_Studio/Tango.Core/ExtensionMethods/IEnumerableExtensions.cs12
-rw-r--r--Software/Visual_Studio/Tango.DAL.Remote/DB/JOB.cs1
-rw-r--r--Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx3
-rw-r--r--Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram134
-rw-r--r--Software/Visual_Studio/Tango.Integration/Operation/IMachineOperator.cs9
-rw-r--r--Software/Visual_Studio/Tango.Integration/Operation/JobHandler.cs6
-rw-r--r--Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs86
-rw-r--r--Software/Visual_Studio/Tango.Integration/Operation/RunningJobStatus.cs15
-rw-r--r--Software/Visual_Studio/Tango.Settings/SettingsManager.cs17
-rw-r--r--Software/Visual_Studio/Tango.Touch/Controls/TouchGifAnimation.cs58
-rw-r--r--Software/Visual_Studio/Tango.Touch/Controls/TouchGifAnimation.xaml21
-rw-r--r--Software/Visual_Studio/Tango.Touch/Controls/TouchNumericTextBox.cs4
-rw-r--r--Software/Visual_Studio/Tango.Touch/Controls/TouchToggleButton.cs31
-rw-r--r--Software/Visual_Studio/Tango.Touch/Tango.Touch.csproj9
-rw-r--r--Software/Visual_Studio/Tango.Touch/Themes/Generic.xaml3
-rw-r--r--Software/Visual_Studio/Tango.sln42
-rw-r--r--Software/Visual_Studio/Utilities/Tango.UITests/App.xaml8
-rw-r--r--Software/Visual_Studio/Utilities/Tango.UITests/MainWindow.xaml2
-rw-r--r--Software/Visual_Studio/Utilities/Tango.UITests/MainWindow.xaml.cs12
82 files changed, 3150 insertions, 221 deletions
diff --git a/Software/DB/Tango.mdf b/Software/DB/Tango.mdf
index 8f365ab17..44805a30c 100644
--- a/Software/DB/Tango.mdf
+++ b/Software/DB/Tango.mdf
Binary files differ
diff --git a/Software/DB/Tango_log.ldf b/Software/DB/Tango_log.ldf
index 37ac63858..6bd51c604 100644
--- a/Software/DB/Tango_log.ldf
+++ b/Software/DB/Tango_log.ldf
Binary files differ
diff --git a/Software/Embedded_SW/Embedded/Common/report/report.h b/Software/Embedded_SW/Embedded/Common/report/report.h
index b43ed4991..ffe8cbfd4 100644
--- a/Software/Embedded_SW/Embedded/Common/report/report.h
+++ b/Software/Embedded_SW/Embedded/Common/report/report.h
@@ -556,7 +556,7 @@ extern void ReportSeveritySet(ErrorSeverity level);
Report("ERROR :" msg,__FILE__,__LINE__,rc,RpWarning,0,0)
#define REPORT_MSG(rc,msg) \
- Report("ERROR :" msg,__FILE__,__LINE__,rc,RpWarning,0,0)
+ Report("MSG : " msg,__FILE__,__LINE__,rc,RpWarning,0,0)
#define ON_ERROR_LOG_ERROR(msg) if ( rc != 0 ) \
Report("ERROR :" msg,__FILE__,__LINE__,rc,RpError,0,0)
diff --git a/Software/Embedded_SW/Embedded/Drivers/Uart_Comm/Uart.c b/Software/Embedded_SW/Embedded/Drivers/Uart_Comm/Uart.c
index 9d6f50e51..6cd17e5ef 100644
--- a/Software/Embedded_SW/Embedded/Drivers/Uart_Comm/Uart.c
+++ b/Software/Embedded_SW/Embedded/Drivers/Uart_Comm/Uart.c
@@ -118,6 +118,8 @@ uint32_t Uart_rx_Counter = 0;
//
//*****************************************************************************
//void UART0IntHandler(void)
+uint32_t uDataLength[50] = {0};
+byte uindex = 0;
void UARTIntHandler(UArg arg0)
{
uint32_t ui32Status;
@@ -143,6 +145,9 @@ void UARTIntHandler(UArg arg0)
if (U0_size_bar == 4)
{
U0_expected_message_size = *(int *)size;
+ //uDataLength[uindex] = U0_expected_message_size;
+ //if (uindex++>=50)
+ // uindex = 0;
if (initArray( U0_expected_message_size) == 0)
U0_expected_message_size = 0;
U0_size_bar = 0;
@@ -200,6 +205,9 @@ uint32_t Uart_Tx(char *buffer,size_t length)
}
}
+ uDataLength[uindex] = length+4;
+ if (uindex++>=50)
+ uindex = 0;
// if (ret!=length)
// return 1;
diff --git a/Software/Embedded_SW/Embedded/Modules/AlarmHandling/Diagnostics.c b/Software/Embedded_SW/Embedded/Modules/AlarmHandling/Diagnostics.c
index 08ba6d2b4..94b49a8d9 100644
--- a/Software/Embedded_SW/Embedded/Modules/AlarmHandling/Diagnostics.c
+++ b/Software/Embedded_SW/Embedded/Modules/AlarmHandling/Diagnostics.c
@@ -276,6 +276,7 @@ uint32_t DiagnosticsStart()
DiagnosticsControlId = AddControlCallback(Diagnostics_ControlTrigger,DiagnosticLimit,DiagnosticsEmptyCBFunction,0,0,0);
}
}
+ return OK;
}
uint32_t DiagnosticsStop()
{
@@ -286,6 +287,7 @@ uint32_t DiagnosticsStop()
RemoveControlCallback(DiagnosticsControlId,Diagnostics_ControlTrigger);
DiagnosticsControlId = 0xFF;
}
+ return OK;
}
uint32_t StartDiagnosticsRequestFunc(MessageContainer* requestContainer)
{
diff --git a/Software/Embedded_SW/Embedded/Modules/Thread/Thread.h b/Software/Embedded_SW/Embedded/Modules/Thread/Thread.h
index dad7a1db6..7780287fb 100644
--- a/Software/Embedded_SW/Embedded/Modules/Thread/Thread.h
+++ b/Software/Embedded_SW/Embedded/Modules/Thread/Thread.h
@@ -48,7 +48,7 @@ extern HardwarePidControlType ThreadMotorIdToControlId[MAX_THREAD_MOTORS_NUM];
extern HardwareMotor MotorsCfg[NUM_OF_MOTORS];
extern HardwarePidControl MotorsControl[MAX_THREAD_MOTORS_NUM];
-extern InternalWinderConfigStruc InternalWinderCfg;
+//extern InternalWinderConfigStruc InternalWinderCfg;
extern HardwareDancer DancersCfg[MAX_SYSTEM_DANCERS];
#define MAX_CONTROL_SAMPLES 10
diff --git a/Software/Embedded_SW/Embedded/Modules/Thread/Thread_Winder.c b/Software/Embedded_SW/Embedded/Modules/Thread/Thread_Winder.c
index a119b0b16..33086b636 100644
--- a/Software/Embedded_SW/Embedded/Modules/Thread/Thread_Winder.c
+++ b/Software/Embedded_SW/Embedded/Modules/Thread/Thread_Winder.c
@@ -1,7 +1,7 @@
/*
* Thread_Winder.c
*
- * Created on: 25 áîøõ 2018
+ * Created on: 25 áîøõ 2018
* Author: shlomo
*/
#include"include.h"
@@ -11,6 +11,8 @@
#include "StateMachines/Printing/PrintingSTM.h"
#include "Modules/Control/Control.h"
+#include "Common/report/report.h"
+
#include "drivers/FPGA/FPGA.h"
#include "drivers/FPGA/FPGA_SPI_Comm.h"
@@ -27,10 +29,35 @@ uint32_t ScrewControlId = 0xFF;
uint32_t ScrewNumberOfSteps = 0; //holds the current number of steps for the next screw run - will be used to build the cone
uint32_t DirectionChangeCounter = 0; //holds the current number of runs of the screw - will be used to build the cone
+InternalWinderConfigStruc InternalWinderCfg = {0};
+
uint32_t Winder_Init(void)
{
return OK;
}
+
+
+uint32_t InternalWinderConfigMessage(HardwareWinder* request)
+{
+ uint32_t status = PASSED;
+
+ InternalWinderCfg.milimetersperrotation = request->millimeterperrotation;
+
+ return status;
+}
+uint32_t InternalWindingConfigMessage(JobSpool* request)
+{
+ uint32_t status = PASSED;
+
+ InternalWinderCfg.segmentoffsetpulses = request->segmentoffsetpulses;
+ InternalWinderCfg.spoolbackingrate = request->backingrate;
+ InternalWinderCfg.startoffsetpulses = request->startoffsetpulses;
+ InternalWinderCfg.SpoolBottomBackingRate = request->bottombackingrate;
+ InternalWinderCfg.NumberOfRotationPerPassage = request->rotationsperpassage;
+ InternalWinderCfg.diameter = request->diameter;
+
+ return status;
+}
/*
*uint32_t Winder_Prepare(void *JobDetails)
@@ -107,7 +134,56 @@ uint32_t ScrewControlId = 0xFF;
uint32_t ScrewNumberOfSteps = 0;
uint32_t DirectionChangeCounter = 0;
*/
+/*
+ InternalWinderCfg.segmentoffsetpulses = request->segmentoffsetpulses;
+ InternalWinderCfg.spoolbackingrate = request->backingrate;
+ InternalWinderCfg.startoffsetpulses = request->startoffsetpulses;
+ InternalWinderCfg.SpoolBottomBackingRate = request->bottombackingrate;
+ InternalWinderCfg.NumberOfRotationPerPassage = request->rotationsperpassage;
+ *
+Calculate the number of steps.
+Initial home position = ...
+Initial out movement = ScrewNumberOfSteps
+if DirectionChangeCounter %= backingrate : reduce one from the ScrewNumberOfSteps
+if DirectionChangeCounter %= bottombackingrate && direction was out: ADD one to the ScrewNumberOfSteps,
+// WRONG? if the flag is raised - lower it and reduce one from the ScrewNumberOfSteps
+30:100 - 70
+30:99 - 69
+30:98 - 68
+29:98 - 69
+29:97 -68
+InternalWinderCfg.segmentoffsetpulses
+ int32_t backingrate;
+ int32_t bottombackingrate;
+
+numOfSteps = InternalWinderCfg.startoffsetpulses*MotorsCfg[HARDWARE_MOTOR_TYPE__MOTO_SCREW].microstep;
+*/
+uint32_t CalculateNumberOfSteps (uint32_t Counter, bool direction)
+{
+ uint32_t NumberOfSteps = InternalWinderCfg.segmentoffsetpulses*MotorsCfg[HARDWARE_MOTOR_TYPE__MOTO_SCREW].microstep;
+ if (Counter)
+ {
+ if (Counter%InternalWinderCfg.spoolbackingrate == 0)
+ {
+ NumberOfSteps -= (Counter/InternalWinderCfg.spoolbackingrate);
+ REPORT_MSG(ScrewNumberOfSteps, "Head Backing");
+ ScrewNumberOfSteps--;
+ }
+ if ((Counter%InternalWinderCfg.SpoolBottomBackingRate == 0)||(Counter%InternalWinderCfg.SpoolBottomBackingRate == 0))
+ {
+ if (direction != MotorsCfg[HARDWARE_MOTOR_TYPE__MOTO_SCREW].directionthreadwize)
+ {
+ NumberOfSteps += (Counter/InternalWinderCfg.SpoolBottomBackingRate);
+ ScrewNumberOfSteps++;
+ REPORT_MSG(ScrewNumberOfSteps, "Bottom Backing");
+ }
+
+ }
+ }
+ return CalculateNumberOfSteps;
+
+}
uint32_t ScrewDirectionChange(uint32_t deviceID, uint32_t BusyFlag)
{
if (BusyfirstCall)
@@ -118,6 +194,7 @@ uint32_t ScrewDirectionChange(uint32_t deviceID, uint32_t BusyFlag)
//ScrewCurrentDirection: false moves out, true moves home
if (BusyFlag == NOTBUSY)
{
+ CalculateNumberOfSteps (DirectionChangeCounter++, ScrewCurrentDirection);
if (ScrewCurrentDirection == false)
{
ScrewCurrentDirection = true;
@@ -127,7 +204,6 @@ uint32_t ScrewDirectionChange(uint32_t deviceID, uint32_t BusyFlag)
ScrewCurrentDirection = false;
}
MotorMove (HARDWARE_MOTOR_TYPE__MOTO_SCREW,ScrewCurrentDirection,ScrewNumberOfSteps); //process: set point 0, set max speed, move to the specified length, return back.
- DirectionChangeCounter++;
}
/*
* calculate new ScrewSpeed and call MotorSetMaxSpeed (HARDWARE_MOTOR_TYPE__MOTO_SCREW,ScrewSpeed);
@@ -197,6 +273,7 @@ uint32_t Winder_End(void)
void Winder_ScrewHomeLimitSwitchInterrupt(void)
{
uint32_t status;
+ //handle glitch - send information to the next time that the motor stops
if (Winder_ScrewHoming)
{
MotorStop(HARDWARE_MOTOR_TYPE__MOTO_SCREW,Hard_Hiz); //stop ASAP
@@ -205,6 +282,7 @@ void Winder_ScrewHomeLimitSwitchInterrupt(void)
}
void Winder_ScrewOutLimitSwitchInterrupt(void)
{
+ //handle glitch - send information to the next time that the motor stops
uint32_t status;
status = MotorSetDirection(HARDWARE_MOTOR_TYPE__MOTO_SCREW,1-MotorsCfg[HARDWARE_MOTOR_TYPE__MOTO_SCREW].directionthreadwize);//make sure to move the cart out
}
diff --git a/Software/Embedded_SW/Embedded/Modules/Thread/Thread_init.c b/Software/Embedded_SW/Embedded/Modules/Thread/Thread_init.c
index 3c9adbc31..c5f45da78 100644
--- a/Software/Embedded_SW/Embedded/Modules/Thread/Thread_init.c
+++ b/Software/Embedded_SW/Embedded/Modules/Thread/Thread_init.c
@@ -18,35 +18,10 @@ int32_t MotorSamples[MAX_THREAD_MOTORS_NUM][MAX_CONTROL_SAMPLES] = {0};
int MotorSamplePointer[MAX_THREAD_MOTORS_NUM] = {0};
double NormalizedErrorCoEfficient[MAX_THREAD_MOTORS_NUM] = {0};
int DancerStopActivityLimit[MAX_THREAD_MOTORS_NUM] = {0};
-InternalWinderConfigStruc InternalWinderCfg = {0};
HardwareDancer DancersCfg[MAX_SYSTEM_DANCERS] = {0};
HardwarePidControlType ThreadMotorIdToControlId[MAX_THREAD_MOTORS_NUM] = {HARDWARE_PID_CONTROL_TYPE__MotorFeeder,HARDWARE_PID_CONTROL_TYPE__MotorDryer,HARDWARE_PID_CONTROL_TYPE__MotorPooler,HARDWARE_PID_CONTROL_TYPE__MotorWinder,0};
-
-
-uint32_t InternalWinderConfigMessage(HardwareWinder* request)
-{
- uint32_t status = PASSED;
-
- InternalWinderCfg.milimetersperrotation = request->millimeterperrotation;
-
- return status;
-}
-uint32_t InternalWindingConfigMessage(JobSpool* request)
-{
- uint32_t status = PASSED;
-
- InternalWinderCfg.segmentoffsetpulses = request->segmentoffsetpulses;
- InternalWinderCfg.spoolbackingrate = request->backingrate;
- InternalWinderCfg.startoffsetpulses = request->startoffsetpulses;
- InternalWinderCfg.SpoolBottomBackingRate = request->bottombackingrate;
- InternalWinderCfg.NumberOfRotationPerPassage = request->rotationsperpassage;
- InternalWinderCfg.diameter = request->diameter;
-
- return status;
-}
-
//********************************************************************************************************************
uint32_t MotorsConfigMessage(HardwareMotor * request)
{
diff --git a/Software/Embedded_SW/Embedded/Modules/Thread/Thread_print.c b/Software/Embedded_SW/Embedded/Modules/Thread/Thread_print.c
index 0701a2aac..d9aeb503a 100644
--- a/Software/Embedded_SW/Embedded/Modules/Thread/Thread_print.c
+++ b/Software/Embedded_SW/Embedded/Modules/Thread/Thread_print.c
@@ -70,6 +70,8 @@ ProcessedLengthFunc ProcessedLengthFuncPtr = NULL;
void ThreadSegmentEnded(void);
void ThreadInterSegmentEnded(void);
void ThreadDistanceToSpoolEnded(void);
+uint32_t ThreadControlCBFunction(uint32_t IfIndex, uint32_t ReadValue);
+void SetOriginMotorSpeed(float process_speed);
double KeepNormalizedError = 0;
bool ThreadControlActive = false;
@@ -248,12 +250,37 @@ uint32_t ThreadControlSpeedReadFunction(uint32_t IfIndex, uint32_t ReadValue)
}
return OK;
}
-double calculatedError[1000];
-int readValue[1000];
-int calculatedspeed[1000];
+/*double calculatedError[100];
+double eNormalizedError[100];
+int readValue[100];
+int TranslatedreadValue[100];
+int AveragereadValue[100];
+int calculatedspeed[100];
int controlIndex = 0;
int32_t KeepReadValue = 0;
-
+void testDancersControl()
+{
+ int mm20,mm10,mm5,mm2,mm1;
+ mm20 = (20*DancerStopActivityLimit[FEEDER_MOTOR])/(DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].maximalmovementmm*2);
+ mm2 = mm20/10;
+ mm5 = mm20/4;
+ mm10 = mm20/2;
+ mm1 = mm20/20;
+ ThreadControlActive = true;
+ SetOriginMotorSpeed(30.0);
+ ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint - mm20);
+ ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint - mm10);
+ ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint - mm5);
+ ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint - mm2);
+ ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint - mm1);
+ ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint);
+ ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint + mm1);
+ ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint + mm2);
+ ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint + mm5);
+ ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint + mm10);
+ ThreadControlCBFunction(IfTypeThread*0x100+FEEDER_MOTOR, DancersCfg[HARDWARE_DANCER_TYPE__RightDancer].zeropoint + mm20);
+ ThreadControlActive = false;
+}*/
uint32_t ThreadControlCBFunction(uint32_t IfIndex, uint32_t ReadValue)
{
//#define MAX_CONTROL_SAMPLES 6
@@ -270,6 +297,8 @@ uint32_t ThreadControlCBFunction(uint32_t IfIndex, uint32_t ReadValue)
double NormalizedError;
char Message[60];
+ if (ThreadControlActive == false)
+ return OK;
if (IfIndex>>8 != IfTypeThread)
{
LOG_ERROR (IfIndex, "Wrong Interface type");
@@ -339,18 +368,21 @@ uint32_t ThreadControlCBFunction(uint32_t IfIndex, uint32_t ReadValue)
//KeepNormalizedError = NormalizedError;
}
calculated_speed = (1-MotorControlConfig[index].m_calculatedError)*OriginalMotorSpd_2PPS[index];
- if (index == POOLER_MOTOR)
+ /*if (index == FEEDER_MOTOR)
{
if (KeepReadValue != TranslatedReadValue)
{
+ eNormalizedError[controlIndex] = NormalizedError;
calculatedError[controlIndex] = MotorControlConfig[index].m_calculatedError;
- readValue[controlIndex] = TranslatedReadValue;
+ readValue[controlIndex] = ReadValue;
+ TranslatedreadValue[controlIndex] = TranslatedReadValue;
+ AveragereadValue[controlIndex] = avreageSampleValue;
calculatedspeed[controlIndex] = calculated_speed;
controlIndex++;
- if (controlIndex >= 999) controlIndex = 0;
+ if (controlIndex >= 99) controlIndex = 0;
KeepReadValue = TranslatedReadValue;
}
- }
+ }*/
if (abs(calculated_speed-CurrentControlledSpeed[index])>5)
{
CurrentControlledSpeed[index] = calculated_speed;
@@ -482,6 +514,7 @@ bool InitialProcess = false;
// else if ((Motor_i == HARDWARE_MOTOR_TYPE__MOTO_WINDER)||(Motor_i == HARDWARE_MOTOR_TYPE__MOTO_LDRIVING)||(Motor_i == HARDWARE_MOTOR_TYPE__MOTO_RDRIVING))
// AddControlCallback(ThreadControlCBFunction, eOneMillisecond,Control_Read_Dancer_Position,(IfTypeThread*0x100+Motor_i),ThreadMotorIdToDancerId[Motor_i],Motor_i);
}
+ //testDancersControl();
PrepareReady(Module_Thread,ModuleDone);
//set 3 dancers to the profile positions
InitialProcess = true;
diff --git a/Software/Embedded_SW/Embedded/StateMachines/Printing/JobSTM.c b/Software/Embedded_SW/Embedded/StateMachines/Printing/JobSTM.c
index 56c1b7be7..3384965d7 100644
--- a/Software/Embedded_SW/Embedded/StateMachines/Printing/JobSTM.c
+++ b/Software/Embedded_SW/Embedded/StateMachines/Printing/JobSTM.c
@@ -28,6 +28,8 @@
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/task.h>
+#include "Common/report/report.h"
+
#include "PMR/Printing/JobSegment.pb-c.h"
#include "PMR/Printing/JobRequest.pb-c.h"
#include "PMR/Printing/JobResponse.pb-c.h"
@@ -359,7 +361,8 @@ void JobRequestFunc(MessageContainer* requestContainer)
jobStatus.progress = 0.0;
jobStatus.has_currentsegmentindex = false;
response.status = &jobStatus;
- response.has_canceled = false;
+ response.has_canceled = true;
+ response.canceled = true;
responseContainer = createContainer(MESSAGE_TYPE__JobResponse, JobToken, true, &response, &job_response__pack, &job_response__get_packed_size);
container_buffer = malloc(message_container__get_packed_size(&responseContainer));
responseContainer.has_error = true;
@@ -381,38 +384,46 @@ void SendJobProgress(double ProcessedLength, int SegmentId, bool done, char *Mes
uint32_t status = NOT_SUPPORTED;
MessageContainer responseContainer;
uint8_t* container_buffer;
+
+ char logmsg[100];
+ int len;
+ static msdid = 0;
+ len = usnprintf(logmsg, 100, "MSG: Job Progress Length %f, Seg %d Done %d %s",ProcessedLength, SegmentId, done, Message);
+
+ //REPORT_MSG(msdid++,logmsg);
+ Report(logmsg,__FILE__,__LINE__,msdid,RpWarning,SegmentId, done);
+
+
+ JobResponse response = JOB_RESPONSE__INIT;
+ JobStatus jobStatus = JOB_STATUS__INIT;
+
+
+ jobStatus.message = Message;
+
if (ProcessedLength == 0.0)
{
- ProcessedLength = previousJobLength;
+ //ProcessedLength = previousJobLength;
+ jobStatus.has_progress = false;
+ jobStatus.progress = 0;
+ jobStatus.has_currentsegmentindex = false;
}
else
{
- previousJobLength = ProcessedLength;
+ //previousJobLength = ProcessedLength;
+ jobStatus.has_progress = true;
+ jobStatus.progress = ProcessedLength;
+ jobStatus.has_currentsegmentindex = true;
+ jobStatus.currentsegmentindex = SegmentId;
}
+ response.status = &jobStatus;
-
- JobResponse response = JOB_RESPONSE__INIT;
- JobStatus jobStatus = JOB_STATUS__INIT;
if (done == true)
{
- jobStatus.message = Message;
- jobStatus.has_progress = true;
- jobStatus.progress = ProcessedLength;
- jobStatus.has_currentsegmentindex = false;
- response.status = &jobStatus;
- response.has_canceled = false;
responseContainer = createContainer(MESSAGE_TYPE__JobResponse, JobToken, true, &response, &job_response__pack, &job_response__get_packed_size);
container_buffer = malloc(message_container__get_packed_size(&responseContainer));
}
else
{
- jobStatus.message =Message;
- jobStatus.has_progress = true;
- jobStatus.progress = ProcessedLength;
- jobStatus.has_currentsegmentindex = true;
- jobStatus.currentsegmentindex = SegmentId;
- response.status = &jobStatus;
- response.has_canceled = false;
responseContainer = createContainer(MESSAGE_TYPE__JobResponse, JobToken, false, &response, &job_response__pack, &job_response__get_packed_size);
container_buffer = malloc(message_container__get_packed_size(&responseContainer));
}
diff --git a/Software/Graphics/Mobile/sample-dye.png b/Software/Graphics/Mobile/sample-dye.png
new file mode 100644
index 000000000..f8989e19a
--- /dev/null
+++ b/Software/Graphics/Mobile/sample-dye.png
Binary files differ
diff --git a/Software/Graphics/Preloaders/preloader_rectangles.gif b/Software/Graphics/Preloaders/preloader_rectangles.gif
new file mode 100644
index 000000000..5bb37cc50
--- /dev/null
+++ b/Software/Graphics/Preloaders/preloader_rectangles.gif
Binary files differ
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorLab/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorLab/ViewModels/MainViewVM.cs
index 48d16104a..0e9109b28 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorLab/ViewModels/MainViewVM.cs
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorLab/ViewModels/MainViewVM.cs
@@ -13,6 +13,7 @@ using System.Windows.Media;
using Tango.BL;
using Tango.BL.ColorConversion;
using Tango.BL.Entities;
+using Tango.BL.Enumerations;
using Tango.Core.Commands;
using Tango.MachineStudio.Common;
using Tango.MachineStudio.Common.Controls;
@@ -32,6 +33,33 @@ namespace Tango.MachineStudio.ColorLab.ViewModels
#region Properties
+ private bool _isVolumesOutOfRange;
+ /// <summary>
+ /// Gets or sets a value indicating whether the liquid volumes are out of range.
+ /// </summary>
+ public bool IsVolumesOutOfRange
+ {
+ get { return _isVolumesOutOfRange; }
+ set
+ {
+ if (_isVolumesOutOfRange != value)
+ {
+ _isVolumesOutOfRange = value;
+ RaisePropertyChangedAuto();
+ }
+ }
+ }
+
+ private bool _isOutOfGamut;
+ /// <summary>
+ /// Gets or sets a value indicating whether the source color is out of gamut.
+ /// </summary>
+ public bool IsOutOfGamut
+ {
+ get { return _isOutOfGamut; }
+ set { _isOutOfGamut = value; RaisePropertyChangedAuto(); }
+ }
+
private ObservableCollection<Machine> _machines;
/// <summary>
/// Gets or sets the machines.
@@ -280,6 +308,8 @@ namespace Tango.MachineStudio.ColorLab.ViewModels
var output = TangoColorConverter.GetSuggestions(input);
+ IsOutOfGamut = output.OutOfGamut;
+
HiveSuggestions = TangoColorConverter.CreateHiveSuggestions(output);
});
}
@@ -396,6 +426,17 @@ namespace Tango.MachineStudio.ColorLab.ViewModels
try
{
if (LiquidsCalibrationData == null) return;
+
+ //TODO: This is temporary because of out of range volumes.
+ if (LiquidVolumes.Where(x => x.IdsPack.IdsPackFormula.Code == IdsPackFormulas.StandardColor.ToInt32()).Sum(x => x.Volume) > 200)
+ {
+ IsVolumesOutOfRange = true;
+ return;
+ }
+ else
+ {
+ IsVolumesOutOfRange = false;
+ }
ConversionInput input = new ConversionInput();
input.ColorSpace = PMR.ColorLab.ColorSpace.Volume;
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorLab/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorLab/Views/MainView.xaml
index 8b62604d6..d8ef015be 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorLab/Views/MainView.xaml
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.ColorLab/Views/MainView.xaml
@@ -26,6 +26,7 @@
<converters:ColorToComponentsConverter x:Key="ColorToComponentsConverter" />
<converters:NullObjectToBooleanConverter x:Key="NullObjectToBooleanConverter" />
<converters:ObjectToObjectTypeConverter x:Key="ObjectToObjectTypeConverter" />
+ <converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</UserControl.Resources>
<Grid>
@@ -163,6 +164,12 @@
</Grid.RowDefinitions>
<StackPanel VerticalAlignment="Center" Grid.Row="1">
+ <StackPanel Height="20">
+ <StackPanel Orientation="Horizontal" Margin="0 0 0 5" Visibility="{Binding IsOutOfGamut,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <materialDesign:PackIcon Kind="Alert" Foreground="#FF6D6D" />
+ <TextBlock Margin="5 0 0 0" Foreground="#FF6D6D">Color is out of gamut</TextBlock>
+ </StackPanel>
+ </StackPanel>
<Border BorderThickness="1" BorderBrush="#545454" Margin="0" Padding="2 2 2 0">
<brushPicker:BrushPicker x:Name="picker" Color="{Binding SourceColor.Color,Mode=TwoWay}" Background="Transparent" BorderThickness="0" Height="150" BrushTypeVisibility="Collapsed"></brushPicker:BrushPicker>
</Border>
@@ -254,30 +261,39 @@
</Grid>
- <ItemsControl ItemsSource="{Binding LiquidVolumes}" VerticalAlignment="Center" MinWidth="420" Grid.Column="4" Grid.Row="3">
- <ItemsControl.ItemsPanel>
- <ItemsPanelTemplate>
- <StackPanel VerticalAlignment="Center" Orientation="Horizontal" IsItemsHost="True"></StackPanel>
- </ItemsPanelTemplate>
- </ItemsControl.ItemsPanel>
- <ItemsControl.ItemTemplate>
- <DataTemplate>
- <StackPanel>
- <TextBlock HorizontalAlignment="Center" TextAlignment="Center" Text="{Binding Name}" FontSize="10" Margin="0 0 0 5"></TextBlock>
- <ContentControl Focusable="False" Style="{StaticResource numberBorder}" Width="60" Height="60" Margin="10 0 0 0">
- <ContentControl.Foreground>
- <SolidColorBrush Color="{Binding Color,Converter={StaticResource ColorToIntegerConverter}}"></SolidColorBrush>
- </ContentControl.Foreground>
- <mahapps:NumericUpDown FontSize="16" FontFamily="{StaticResource digital-7}" HorizontalAlignment="Center" Value="{Binding Volume, Mode=TwoWay}" Background="Transparent" Width="40" StringFormat="0.00" HideUpDownButtons="True" Minimum="0" Maximum="1000" InterceptArrowKeys="True" BorderThickness="0" InterceptMouseWheel="True" HasDecimals="True" HorizontalContentAlignment="Center">
- <!--<mahapps:NumericUpDown.Resources>
+ <StackPanel Grid.Column="4" Grid.Row="3">
+ <StackPanel Height="25" Margin="25 0 0 0">
+ <StackPanel Orientation="Horizontal" Margin="0 0 0 0" Visibility="{Binding IsVolumesOutOfRange,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <materialDesign:PackIcon Kind="Alert" Foreground="#FF6D6D" />
+ <TextBlock Margin="5 0 0 0" Foreground="#FF6D6D">Liquid volumes exceeds the maximum range</TextBlock>
+ </StackPanel>
+ </StackPanel>
+
+ <ItemsControl ItemsSource="{Binding LiquidVolumes}" VerticalAlignment="Center" MinWidth="420">
+ <ItemsControl.ItemsPanel>
+ <ItemsPanelTemplate>
+ <StackPanel VerticalAlignment="Center" Orientation="Horizontal" IsItemsHost="True"></StackPanel>
+ </ItemsPanelTemplate>
+ </ItemsControl.ItemsPanel>
+ <ItemsControl.ItemTemplate>
+ <DataTemplate>
+ <StackPanel>
+ <TextBlock HorizontalAlignment="Center" TextAlignment="Center" Text="{Binding Name}" FontSize="10" Margin="0 0 0 5"></TextBlock>
+ <ContentControl Focusable="False" Style="{StaticResource numberBorder}" Width="60" Height="60" Margin="10 0 0 0">
+ <ContentControl.Foreground>
+ <SolidColorBrush Color="{Binding Color,Converter={StaticResource ColorToIntegerConverter}}"></SolidColorBrush>
+ </ContentControl.Foreground>
+ <mahapps:NumericUpDown FontSize="16" FontFamily="{StaticResource digital-7}" HorizontalAlignment="Center" Value="{Binding Volume, Mode=TwoWay}" Background="Transparent" Width="40" StringFormat="0.00" HideUpDownButtons="True" Minimum="0" Maximum="1000" InterceptArrowKeys="True" BorderThickness="0" InterceptMouseWheel="True" HasDecimals="True" HorizontalContentAlignment="Center">
+ <!--<mahapps:NumericUpDown.Resources>
<StaticResource ResourceKey="SelectAllTextBoxResource"></StaticResource>
</mahapps:NumericUpDown.Resources>-->
- </mahapps:NumericUpDown>
- </ContentControl>
- </StackPanel>
- </DataTemplate>
- </ItemsControl.ItemTemplate>
- </ItemsControl>
+ </mahapps:NumericUpDown>
+ </ContentControl>
+ </StackPanel>
+ </DataTemplate>
+ </ItemsControl.ItemTemplate>
+ </ItemsControl>
+ </StackPanel>
<Image Source="../Images/arrow-long-Left.png" Grid.Column="2" Grid.Row="3" Width="140" Opacity="0.8"></Image>
@@ -286,11 +302,14 @@
<Grid>
<DockPanel Width="80" HorizontalAlignment="Left">
<TextBlock DockPanel.Dock="Top" FontSize="9" TextAlignment="Center">COMPOSITE</TextBlock>
- <Ellipse Height="70" Margin="0 5 0 0" Stroke="#202020">
- <Ellipse.Fill>
- <SolidColorBrush Color="{Binding TargetColor.Color}"></SolidColorBrush>
- </Ellipse.Fill>
- </Ellipse>
+ <Grid>
+ <Ellipse Height="70" Margin="0 5 0 0" Stroke="#202020">
+ <Ellipse.Fill>
+ <SolidColorBrush Color="{Binding TargetColor.Color}"></SolidColorBrush>
+ </Ellipse.Fill>
+ </Ellipse>
+ <materialDesign:PackIcon Visibility="{Binding IsVolumesOutOfRange,Converter={StaticResource BooleanToVisibilityConverter}}" Kind="Alert" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" Width="24" Height="24" />
+ </Grid>
</DockPanel>
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal" Height="60">
diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Resources/BuildDate.txt b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Resources/BuildDate.txt
index 00990166f..60d433d99 100644
--- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Resources/BuildDate.txt
+++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Resources/BuildDate.txt
@@ -1 +1 @@
-Tue 07/10/2018 16:54:33.30
+Wed 07/11/2018 16:02:40.40
diff --git a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/Interp.cpp b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/Interp.cpp
index 7346a9898..68b7e0c93 100644
--- a/Software/Visual_Studio/Native/Tango.ColorLib/Utils/Interp.cpp
+++ b/Software/Visual_Studio/Native/Tango.ColorLib/Utils/Interp.cpp
@@ -5,6 +5,7 @@
#include <iostream>
#include <stdio.h>
+#define epsTol 0.05
Interp::Interp(void)
{
}
@@ -26,6 +27,15 @@ void Interp::Eval(double InValue, double &OutValue)
int errType = 0;
ind = -1;
+ //Check Bounds
+ if((InValue<m_xValues[0] - epsTol) || (InValue >m_xValues[m_length - 1] + epsTol))
+ throw std::exception("Value out of Bounds");
+ if ((InValue > m_xValues[0] - epsTol) && (InValue < m_xValues[0]))
+ InValue = m_xValues[0];
+
+ if ((InValue > m_xValues[m_length - 1] ) && (InValue < m_xValues[m_length - 1]+ epsTol))
+ InValue = m_xValues[m_length - 1];
+
for (m = 0; m < m_length - 1; ++m)
{
if (m_xValues[m] <= InValue && m_xValues[m + 1] >= InValue)
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Controls/JobSummeryViewer.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Controls/JobSummeryViewer.xaml
index 550accac3..c7f42f14d 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Controls/JobSummeryViewer.xaml
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Controls/JobSummeryViewer.xaml
@@ -101,9 +101,13 @@
<Style TargetType="Grid">
<Setter Property="Visibility" Value="Collapsed"></Setter>
<Style.Triggers>
- <DataTrigger Binding="{Binding JobType}" Value="{x:Static enumerations:JobTypes.Embroidery}">
+ <MultiDataTrigger>
+ <MultiDataTrigger.Conditions>
+ <Condition Binding="{Binding JobType}" Value="{x:Static enumerations:JobTypes.Embroidery}" />
+ <Condition Binding="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=IsActive}" Value="False" />
+ </MultiDataTrigger.Conditions>
<Setter Property="Visibility" Value="Visible"></Setter>
- </DataTrigger>
+ </MultiDataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
@@ -112,6 +116,5 @@
<Run Text="x"></Run><Run Text="{Binding NumberOfUnits}"></Run>
</TextBlock>
</Grid>
- <TextBlock></TextBlock>
</Grid>
</UserControl>
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 2b9d9c7a9..2c03ad452 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
@@ -20,7 +20,13 @@ namespace Tango.PPC.Jobs.Controls
/// </summary>
public partial class JobSummeryViewer : UserControl
{
-
+ public bool IsActive
+ {
+ get { return (bool)GetValue(IsActiveProperty); }
+ set { SetValue(IsActiveProperty, value); }
+ }
+ public static readonly DependencyProperty IsActiveProperty =
+ DependencyProperty.Register("IsActive", typeof(bool), typeof(JobSummeryViewer), new PropertyMetadata(false));
public bool DisplayMarkers
{
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/JobView/sample-dye.png b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/JobView/sample-dye.png
new file mode 100644
index 000000000..f8989e19a
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/JobView/sample-dye.png
Binary files differ
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Tango.PPC.Jobs.csproj b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Tango.PPC.Jobs.csproj
index 0163b77c2..aaf9fb453 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Tango.PPC.Jobs.csproj
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Tango.PPC.Jobs.csproj
@@ -311,5 +311,8 @@
<ItemGroup>
<Resource Include="Images\JobProgressView\clock.png" />
</ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\JobView\sample-dye.png" />
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobProgressViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobProgressViewVM.cs
index a111d3be2..6039dafb8 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobProgressViewVM.cs
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobProgressViewVM.cs
@@ -10,9 +10,10 @@ using Tango.PPC.Common.Navigation;
namespace Tango.PPC.Jobs.ViewModels
{
- public class JobProgressViewVM : PPCViewModel, INavigationResultProvider<Object, Job>
+ public class JobProgressViewVM : PPCViewModel
{
private Job _job;
+
public Job Job
{
get { return _job; }
@@ -32,21 +33,21 @@ namespace Tango.PPC.Jobs.ViewModels
}
- public void OnNavigationObjectReceived(Job job)
+ public override void OnApplicationStarted()
{
- Job = job;
- var jobHandler = ApplicationManager.ConnectedMachine.Print(Job, Adapter.ProcessParametersTables.First());
- jobHandler.StatusChanged += JobHandler_StatusChanged;
+ ApplicationManager.ConnectedMachineChanged += ApplicationManager_ConnectedMachineChanged;
}
- public object GetNavigationResult()
+ private void ApplicationManager_ConnectedMachineChanged(object sender, IMachineOperator e)
{
- return null;
+ e.PrintingStarted -= PrintingStarted;
+ e.PrintingStarted += PrintingStarted;
}
- public override void OnApplicationStarted()
+ private void PrintingStarted(object sender, JobHandler jobHandler)
{
-
+ Job = jobHandler.Job;
+ jobHandler.StatusChanged += JobHandler_StatusChanged;
}
private void JobHandler_StatusChanged(object sender, RunningJobStatus e)
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobSummeryViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobSummeryViewVM.cs
index a59b0fe27..19e28f6a9 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobSummeryViewVM.cs
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobSummeryViewVM.cs
@@ -47,7 +47,8 @@ namespace Tango.PPC.Jobs.ViewModels
private void StartJob()
{
- var result = NavigationManager.NavigateForResult<JobsModule, JobProgressView, Object, Job>(Job);
+ ApplicationManager.ConnectedMachine.Print(Job);
+ NavigationManager.NavigateTo<JobsModule>(nameof(JobProgressView));
}
public override void OnApplicationStarted()
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 6b25d323f..b23e8b8ed 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
@@ -39,7 +39,6 @@ namespace Tango.PPC.Jobs.ViewModels
#region Properties
private Job _job;
-
/// <summary>
/// Gets or sets the selected job.
/// </summary>
@@ -172,6 +171,21 @@ namespace Tango.PPC.Jobs.ViewModels
/// </summary>
public RelayCommand<BrushStop> TwineCatalogFieldTapCommand { get; set; }
+ /// <summary>
+ /// Gets or sets the increase decrease samples to dye command.
+ /// </summary>
+ public RelayCommand<String> IncreaseDecreaseSamplesToDyeCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the start sample dye command.
+ /// </summary>
+ public RelayCommand StartSampleDyeCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the dye command.
+ /// </summary>
+ public RelayCommand DyeCommand { get; set; }
+
#endregion
#region Constructors
@@ -205,9 +219,23 @@ namespace Tango.PPC.Jobs.ViewModels
SaveJobCommand = new RelayCommand(SaveJob);
ReplaceBrushStopCommand = new RelayCommand<BrushStop>(InvokeColorAdjustmentForBrushStop);
TwineCatalogFieldTapCommand = new RelayCommand<BrushStop>(InvokeTwineCatalogForBrushStop);
+ IncreaseDecreaseSamplesToDyeCommand = new RelayCommand<string>((x) =>
+ {
+ if (x == "+")
+ {
+ Job.SampleUnitsOrMeters++;
+ }
+ else
+ {
+ Job.SampleUnitsOrMeters--;
+ }
+ });
_check_gamut_thread = new Thread(CheckGamutThreadMethod);
_check_gamut_thread.IsBackground = true;
+
+ StartSampleDyeCommand = new RelayCommand(StartSampleDye);
+ DyeCommand = new RelayCommand(StartJob, CanStartJob);
}
#endregion
@@ -238,6 +266,19 @@ namespace Tango.PPC.Jobs.ViewModels
}
}
+ private void StartJob()
+ {
+ ApplicationManager.ConnectedMachine.Print(Job);
+ NavigationManager.NavigateTo<JobsModule>(nameof(JobProgressView));
+ }
+
+ private bool CanStartJob()
+ {
+ return
+ Job != null &&
+ !Job.Segments.SelectMany(x => x.BrushStops).ToList().Exists(x => x.IsOutOfGamut);
+ }
+
#endregion
#region Segments Management
@@ -390,6 +431,37 @@ namespace Tango.PPC.Jobs.ViewModels
#endregion
+ #region Sample Dye
+
+ /// <summary>
+ /// Starts a sample dye.
+ /// </summary>
+ private void StartSampleDye()
+ {
+ Job sampleDyeJob = Job.Clone();
+ sampleDyeJob.Name = Job.Name + " (sample)";
+
+ if (Job.JobType == BL.Enumerations.JobTypes.Embroidery)
+ {
+ sampleDyeJob.NumberOfUnits = Job.SampleUnitsOrMeters;
+ }
+ else
+ {
+ sampleDyeJob.NumberOfUnits = 1;
+
+ foreach (var segment in sampleDyeJob.Segments)
+ {
+ segment.Length = Job.SampleUnitsOrMeters;
+ }
+ }
+
+ ApplicationManager.ConnectedMachine.Print(sampleDyeJob);
+
+ NavigationManager.NavigateTo<JobsModule>(nameof(JobProgressView));
+ }
+
+ #endregion
+
#region Out Of Gamut Check Thread
private void CheckGamutThreadMethod()
@@ -407,6 +479,11 @@ namespace Tango.PPC.Jobs.ViewModels
stop.IsOutOfGamut = TangoColorConverter.IsOutOfGamut(stop);
stop.OutOfGamutChecked = true;
}
+
+ InvokeUI(() =>
+ {
+ DyeCommand.RaiseCanExecuteChanged();
+ });
}
}
}
@@ -428,6 +505,8 @@ namespace Tango.PPC.Jobs.ViewModels
/// </summary>
public async override void OnNavigatedTo()
{
+ if (_job_to_load == null) return;
+
NotificationProvider.SetGlobalBusyMessage("Loading job details...");
_can_navigate_back = false;
@@ -467,14 +546,17 @@ namespace Tango.PPC.Jobs.ViewModels
{
NotificationProvider.ReleaseGlobalBusyMessage();
});
+
+ _job_to_load = null;
}
+
/// <summary>
- /// Called before the navigation system navigates from this object.
+ /// Called before the navigation system navigates back from this object.
/// Return false to abort the navigation.
/// </summary>
/// <returns></returns>
- public async override Task<bool> OnNavigateOutRequest()
+ public async override Task<bool> OnNavigateBackRequest()
{
bool result = true;
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 39963201e..8f2ea355f 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
@@ -270,6 +270,9 @@ namespace Tango.PPC.Jobs.ViewModels
Job job = new Job();
job.Name = "untitled";
+ job.NumberOfHeads = 1;
+ job.NumberOfUnits = 1;
+ job.SampleUnitsOrMeters = 1;
job.CreationDate = DateTime.UtcNow;
job.JobStatus = JobStatuses.Draft;
job.JobType = vm.SelectedJobType.Value;
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobProgressView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobProgressView.xaml
index 3a4a895dc..28672a920 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobProgressView.xaml
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobProgressView.xaml
@@ -15,7 +15,7 @@
<UserControl.Resources>
<converters:JobProgressToPositionConverter x:Key="JobProgressToPositionConverter" />
</UserControl.Resources>
-
+
<Grid>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0 100 0 0">
<TextBlock FontSize="{StaticResource TangoHeaderFontSize}" HorizontalAlignment="Center" Text="{Binding Job.Name,FallbackValue='Job Name'}"></TextBlock>
@@ -54,18 +54,25 @@
<StackPanel>
<Canvas.Left>
<MultiBinding Converter="{StaticResource JobProgressToPositionConverter}">
- <Binding Path="RunningJobStatus.Progress" />
- <Binding Path="RunningJobStatus.TotalProgress" />
+ <Binding Path="RunningJobStatus.CurrentUnitProgress" />
+ <Binding Path="RunningJobStatus.CurrentUnitTotalProgress" />
<Binding RelativeSource="{RelativeSource AncestorType=Canvas}" Path="ActualWidth" />
</MultiBinding>
</Canvas.Left>
- <StackPanel Margin="-30 0 0 0">
+ <StackPanel Margin="-50 0 0 0">
<TextBlock HorizontalAlignment="Center" FontSize="{StaticResource TangoTitleFontSize}">now dying</TextBlock>
<touch:TouchIcon Margin="0 8 0 0" HorizontalAlignment="Center" Icon="Water" Angle="180" Foreground="{StaticResource TangoPrimaryAccentBrush}" Width="40" Height="40" />
</StackPanel>
</StackPanel>
</Canvas>
- <controls:JobSummeryViewer Height="30" Width="600" DisplayMarkers="False" DataContext="{Binding Job}" />
+
+ <Grid>
+ <controls:JobSummeryViewer Height="30" Width="600" DisplayMarkers="False" IsActive="True" DataContext="{Binding Job}" />
+
+ <TextBlock Margin="0 0 -40 0" VerticalAlignment="Center" FontSize="{StaticResource TangoTitleFontSize}" HorizontalAlignment="Right">
+ <Run Text="x"></Run><Run Text="{Binding RunningJobStatus.RemainingUnits}"></Run>
+ </TextBlock>
+ </Grid>
</StackPanel>
</Grid>
</StackPanel>
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 b956d7b6c..377348581 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
@@ -56,7 +56,7 @@
<TextBlock Margin="40 10 0 0" FontSize="{StaticResource TangoTitleFontSize}">Tap 'DYE' to start the dying process...</TextBlock>
</StackPanel>
- <controls:JobSummeryViewer Height="50" Margin="-6 0 -6 0" DataContext="{Binding Job}" VerticalAlignment="Bottom" />
+ <controls:JobSummeryViewer Height="50" DataContext="{Binding Job}" VerticalAlignment="Bottom" />
</Grid>
</DockPanel>
</Grid>
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 ce7f7b528..cf1c3fa37 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
@@ -538,7 +538,11 @@
</StackPanel>
</Border>
- <Border Style="{StaticResource TangoTouchBorder}" Margin="0 12 0 120" Padding="0 0 0 40">
+ <StackPanel HorizontalAlignment="Center" Margin="20 40 0 40" Orientation="Horizontal" VerticalAlignment="Center" Style="{StaticResource Level1Container}">
+ <TextBlock FontWeight="Medium" Margin="20 0 0 0" VerticalAlignment="Center" FontSize="{StaticResource TangoTitleFontSize}">Additional Tools</TextBlock>
+ </StackPanel>
+
+ <!--<Border Style="{StaticResource TangoTouchBorder}" Margin="0 12 0 0" Padding="0 0 0 40">
<StackPanel>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Style="{StaticResource Level1Container}">
<Image Source="../Images/JobView/additional-tools.png" Width="39" />
@@ -549,7 +553,7 @@
<DockPanel LastChildFill="False">
<TextBlock Text="Make a sample dye" VerticalAlignment="Center"></TextBlock>
- <touch:TouchToggleSlider DockPanel.Dock="Right" Width="75" Style="{StaticResource TouchToggleButtonCheck}" Margin="30 0 0 0" Height="38" HorizontalAlignment="Left" />
+ <touch:TouchToggleSlider x:Name="toggle_sample_dye" DockPanel.Dock="Right" Width="75" Style="{StaticResource TouchToggleButtonCheck}" Margin="30 0 0 0" Height="38" HorizontalAlignment="Left" />
</DockPanel>
<DockPanel Margin="0 25 0 0" LastChildFill="False">
@@ -558,7 +562,80 @@
</DockPanel>
</StackPanel>
</StackPanel>
- </Border>
+ </Border>-->
+
+ <touch:TouchExpander Margin="0 0 0 120" Padding="20 15" IsExpanded="True">
+ <touch:TouchExpander.Header>
+ <StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="0 0 20 0">
+ <Image Source="../Images/JobView/sample-dye.png" Width="39" />
+ <TextBlock FontWeight="Medium" Margin="20 0 0 0" VerticalAlignment="Center" FontSize="{StaticResource TangoExpanderHeaderFontSize}">Sample Dye</TextBlock>
+ </StackPanel>
+ </touch:TouchExpander.Header>
+
+ <StackPanel Margin="60 20 0 0">
+
+ <ContentControl Content="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext}">
+ <ContentControl.Style>
+ <Style TargetType="ContentControl">
+ <Setter Property="ContentTemplate">
+ <Setter.Value>
+ <DataTemplate>
+ <StackPanel>
+ <TextBlock>
+ <Run>Dye 1 or more units in order to get approval.</Run>
+ <LineBreak/>
+ <Run>Once approved, you can dye the entire job.</Run>
+ </TextBlock>
+
+ <DockPanel Margin="0 50 0 0" LastChildFill="True" Width="450" HorizontalAlignment="Left">
+ <TextBlock DockPanel.Dock="Left" VerticalAlignment="Center">How many sample units?</TextBlock>
+
+ <DockPanel Margin="50 0 0 0">
+ <touch:TouchIconButton Command="{Binding IncreaseDecreaseSamplesToDyeCommand}" CommandParameter="-" DockPanel.Dock="Left" Icon="Minus" Padding="15" Style="{StaticResource TangoHollowButton}" BorderThickness="2" Width="51" Height="51" />
+ <touch:TouchIconButton Command="{Binding IncreaseDecreaseSamplesToDyeCommand}" CommandParameter="+" DockPanel.Dock="Right" Icon="Plus" Padding="15" Style="{StaticResource TangoHollowButton}" BorderThickness="2" Width="51" Height="51" />
+ <touch:TouchNumericTextBox Value="{Binding Job.SampleUnitsOrMeters}" Minimum="1" Maximum="100" HorizontalContentAlignment="Center" VerticalAlignment="Center" Margin="10 0" Foreground="{StaticResource TangoPrimaryAccentBrush}" FontSize="{StaticResource TangoTitleFontSize}" DockPanel.Dock="Right" KeyboardContainer="{Binding ElementName=Container}" />
+ </DockPanel>
+ </DockPanel>
+ </StackPanel>
+ </DataTemplate>
+ </Setter.Value>
+ </Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding Job.JobType}" Value="{x:Static enumerations:JobTypes.Sewing}">
+ <Setter Property="ContentTemplate">
+ <Setter.Value>
+ <DataTemplate>
+ <StackPanel>
+ <TextBlock>
+ <Run>Dye several meters per segment in order to get approval.</Run>
+ <LineBreak/>
+ <Run>Once approved, you can dye the entire job.</Run>
+ </TextBlock>
+
+ <DockPanel Margin="0 50 0 0" LastChildFill="True" Width="450" HorizontalAlignment="Left">
+ <TextBlock DockPanel.Dock="Left" VerticalAlignment="Center">Meters per segment</TextBlock>
+
+ <DockPanel Margin="50 0 0 0">
+ <touch:TouchIconButton Command="{Binding IncreaseDecreaseSamplesToDyeCommand}" CommandParameter="-" DockPanel.Dock="Left" Icon="Minus" Padding="15" Style="{StaticResource TangoHollowButton}" BorderThickness="2" Width="51" Height="51" />
+ <touch:TouchIconButton Command="{Binding IncreaseDecreaseSamplesToDyeCommand}" CommandParameter="+" DockPanel.Dock="Right" Icon="Plus" Padding="15" Style="{StaticResource TangoHollowButton}" BorderThickness="2" Width="51" Height="51" />
+ <touch:TouchNumericTextBox Value="{Binding Job.SampleUnitsOrMeters}" Minimum="1" Maximum="100" HorizontalContentAlignment="Center" VerticalAlignment="Center" Margin="10 0" Foreground="{StaticResource TangoPrimaryAccentBrush}" FontSize="{StaticResource TangoTitleFontSize}" DockPanel.Dock="Right" KeyboardContainer="{Binding ElementName=Container}" />
+ </DockPanel>
+ </DockPanel>
+ </StackPanel>
+ </DataTemplate>
+ </Setter.Value>
+ </Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </ContentControl.Style>
+ </ContentControl>
+
+ <touch:TouchButton Margin="0 50 0 15" DockPanel.Dock="Right" Height="54" Padding="0" Width="184" CornerRadius="30" BlurRadius="20" HorizontalAlignment="Right" Command="{Binding StartSampleDyeCommand}">
+ START
+ </touch:TouchButton>
+ </StackPanel>
+ </touch:TouchExpander>
</StackPanel>
</StackPanel>
</touch:LightTouchScrollViewer>
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Navigation/INavigationBlocker.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Navigation/INavigationBlocker.cs
index ea5173b95..622c9e2d4 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Navigation/INavigationBlocker.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Navigation/INavigationBlocker.cs
@@ -17,5 +17,12 @@ namespace Tango.PPC.Common.Navigation
/// </summary>
/// <returns></returns>
Task<bool> OnNavigateOutRequest();
+
+ /// <summary>
+ /// Called before the navigation system navigates back from this object.
+ /// Return false to abort the navigation.
+ /// </summary>
+ /// <returns></returns>
+ Task<bool> OnNavigateBackRequest();
}
}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCViewModel.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCViewModel.cs
index fae905b13..12534959e 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCViewModel.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCViewModel.cs
@@ -139,6 +139,16 @@ namespace Tango.PPC.Common
{
return Task.FromResult(true);
}
+
+ /// <summary>
+ /// Called before the navigation system navigates back from this object.
+ /// Return false to abort the navigation.
+ /// </summary>
+ /// <returns></returns>
+ public virtual Task<bool> OnNavigateBackRequest()
+ {
+ return Task.FromResult(true);
+ }
}
/// <summary>
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Images/preloader_rectangles.gif b/Software/Visual_Studio/PPC/Tango.PPC.UI/Images/preloader_rectangles.gif
new file mode 100644
index 000000000..5bb37cc50
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Images/preloader_rectangles.gif
Binary files differ
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Navigation/DefaultNavigationManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/Navigation/DefaultNavigationManager.cs
index 448fc0edc..0ede1306f 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Navigation/DefaultNavigationManager.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Navigation/DefaultNavigationManager.cs
@@ -28,6 +28,7 @@ namespace Tango.PPC.UI.Navigation
private Object _currentVM;
private String _lastFullPath;
private bool _preventHistory;
+ private bool _navigating_back;
private Stack<String> _navigationHistory;
@@ -139,9 +140,19 @@ namespace Tango.PPC.UI.Navigation
if (_currentVM != null && _currentVM is INavigationBlocker)
{
- if (!await (_currentVM as INavigationBlocker).OnNavigateOutRequest())
+ if (_navigating_back)
{
- return false;
+ if (!await (_currentVM as INavigationBlocker).OnNavigateBackRequest())
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (!await (_currentVM as INavigationBlocker).OnNavigateOutRequest())
+ {
+ return false;
+ }
}
}
@@ -260,6 +271,8 @@ namespace Tango.PPC.UI.Navigation
/// </summary>
public async Task<bool> NavigateBack()
{
+ _navigating_back = true;
+
String first = _navigationHistory.Pop();
_preventHistory = true;
@@ -268,12 +281,14 @@ namespace Tango.PPC.UI.Navigation
{
RaisePropertyChanged(nameof(CanNavigateBack));
_preventHistory = false;
+ _navigating_back = false;
return true;
}
else
{
_navigationHistory.Push(first);
_preventHistory = false;
+ _navigating_back = false;
RaisePropertyChanged(nameof(CanNavigateBack));
return false;
}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs
index 4978fa6e0..c67e83fc6 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs
@@ -194,7 +194,7 @@ namespace Tango.PPC.UI.PPCApplication
private async void ConnectToMachine()
{
Transport.Discovery.UsbCommunicationScanner<ConnectRequest, ConnectResponse> scanner = new Transport.Discovery.UsbCommunicationScanner<ConnectRequest, ConnectResponse>(UsbSerialBaudRates.BR_9600);
- var response = await scanner.Scan(new ConnectRequest() { Password = "1234" }, TimeSpan.FromSeconds(60));
+ var response = await scanner.Scan(new ConnectRequest() { Password = "1234" }, TimeSpan.FromSeconds(10));
var machine = new MachineOperator(response.Adapter);
await machine.Connect();
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj b/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj
index 4f6221144..159484c0b 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj
@@ -224,6 +224,10 @@
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
+ <ProjectReference Include="..\..\Tango.AnimatedGif\Tango.AnimatedGif.csproj">
+ <Project>{d129789c-3096-4d0b-8dd7-fe24a4df4b21}</Project>
+ <Name>Tango.AnimatedGif</Name>
+ </ProjectReference>
<ProjectReference Include="..\..\Tango.BL\Tango.BL.csproj">
<Project>{f441feee-322a-4943-b566-110e12fd3b72}</Project>
<Name>Tango.BL</Name>
@@ -325,6 +329,7 @@
<Link>Tango.ColorLib.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Resource Include="Images\preloader_rectangles.gif" />
<Resource Include="Images\logo.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LayoutView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LayoutView.xaml
index 621bfabdb..2f1b7dd59 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LayoutView.xaml
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LayoutView.xaml
@@ -105,7 +105,7 @@
</touch:TouchHamburgerButton>
</Border>
<Grid DockPanel.Dock="Right" Margin="0 0 20 0">
- <StackPanel VerticalAlignment="Center">
+ <StackPanel VerticalAlignment="Center" >
<Image Source="/Images/GlobalStatus/ready-to-dye.png" Width="33" />
<TextBlock Margin="0 10 0 0">Ready to Dye</TextBlock>
</StackPanel>
@@ -127,12 +127,9 @@
</Style.Triggers>
</Style>
</commonControls:AsyncAdornerControl.Style>
- <Grid>
- <StackPanel Orientation="Horizontal">
- <touch:TouchBusyIndicator Width="50" Height="50" IsIndeterminate="{Binding NotificationProvider.IsInGlobalBusyState}" />
- <TextBlock VerticalAlignment="Center" Margin="10 0 0 0" FontSize="20" Text="{Binding NotificationProvider.GlobalBusyMessage}"></TextBlock>
- </StackPanel>
- </Grid>
+ <StackPanel VerticalAlignment="Center">
+ <touch:TouchGifAnimation Source="/Images/preloader_rectangles.gif" EnableAnimation="{Binding NotificationProvider.IsInGlobalBusyState}" />
+ </StackPanel>
</commonControls:AsyncAdornerControl>
</Grid>
</DockPanel>
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LoginView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LoginView.xaml
index 74bb85e7d..027e61d08 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LoginView.xaml
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LoginView.xaml
@@ -29,9 +29,8 @@
</StackPanel>
<StackPanel>
<controls:AsyncAdornerControl Height="130" Visibility="{Binding IsLoading,Converter={StaticResource BooleanToVisibilityConverter}}">
- <StackPanel>
- <touch:TouchBusyIndicator IsIndeterminate="{Binding IsLoading}" Width="80" Height="80" />
- <TextBlock HorizontalAlignment="Center" Margin="0 20 0 0" FontSize="{StaticResource TangoTitleFontSize}">Logging in...</TextBlock>
+ <StackPanel VerticalAlignment="Center">
+ <touch:TouchGifAnimation Source="/Images/preloader_rectangles.gif" EnableAnimation="{Binding IsLoading}" />
</StackPanel>
</controls:AsyncAdornerControl>
</StackPanel>
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/AnimationCache.cs b/Software/Visual_Studio/Tango.AnimatedGif/AnimationCache.cs
new file mode 100644
index 000000000..b9eaf189a
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/AnimationCache.cs
@@ -0,0 +1,151 @@
+using System;
+using System.Collections.Generic;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Media.Imaging;
+
+namespace Tango.AnimatedGif
+{
+ static class AnimationCache
+ {
+ private class CacheKey
+ {
+ private readonly ImageSource _source;
+ private readonly RepeatBehavior _repeatBehavior;
+
+ public CacheKey(ImageSource source, RepeatBehavior repeatBehavior)
+ {
+ _source = source;
+ _repeatBehavior = repeatBehavior;
+ }
+
+ private bool Equals(CacheKey other)
+ {
+ return ImageEquals(_source, other._source)
+ && Equals(_repeatBehavior, other._repeatBehavior);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != this.GetType()) return false;
+ return Equals((CacheKey)obj);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return (ImageGetHashCode(_source) * 397) ^ _repeatBehavior.GetHashCode();
+ }
+ }
+
+ private static int ImageGetHashCode(ImageSource image)
+ {
+ if (image != null)
+ {
+ var uri = GetUri(image);
+ if (uri != null)
+ return uri.GetHashCode();
+ }
+ return 0;
+ }
+
+ private static bool ImageEquals(ImageSource x, ImageSource y)
+ {
+ if (Equals(x, y))
+ return true;
+ if ((x == null) != (y == null))
+ return false;
+ // They can't both be null or Equals would have returned true
+ // and if any is null, the previous would have detected it
+ // ReSharper disable PossibleNullReferenceException
+ if (x.GetType() != y.GetType())
+ return false;
+ // ReSharper restore PossibleNullReferenceException
+ var xUri = GetUri(x);
+ var yUri = GetUri(y);
+ return xUri != null && xUri == yUri;
+ }
+
+ private static Uri GetUri(ImageSource image)
+ {
+ var bmp = image as BitmapImage;
+ if (bmp != null && bmp.UriSource != null)
+ {
+ if (bmp.UriSource.IsAbsoluteUri)
+ return bmp.UriSource;
+ if (bmp.BaseUri != null)
+ return new Uri(bmp.BaseUri, bmp.UriSource);
+ }
+ var frame = image as BitmapFrame;
+ if (frame != null)
+ {
+ string s = frame.ToString();
+ if (s != frame.GetType().FullName)
+ {
+ Uri fUri;
+ if (Uri.TryCreate(s, UriKind.RelativeOrAbsolute, out fUri))
+ {
+ if (fUri.IsAbsoluteUri)
+ return fUri;
+ if (frame.BaseUri != null)
+ return new Uri(frame.BaseUri, fUri);
+ }
+ }
+ }
+ return null;
+ }
+ }
+
+ private static readonly Dictionary<CacheKey, ObjectAnimationUsingKeyFrames> _animationCache = new Dictionary<CacheKey, ObjectAnimationUsingKeyFrames>();
+ private static readonly Dictionary<CacheKey, int> _referenceCount = new Dictionary<CacheKey, int>();
+
+ public static void IncrementReferenceCount(ImageSource source, RepeatBehavior repeatBehavior)
+ {
+ var cacheKey = new CacheKey(source, repeatBehavior);
+ int count;
+ _referenceCount.TryGetValue(cacheKey, out count);
+ count++;
+ _referenceCount[cacheKey] = count;
+ }
+
+ public static void DecrementReferenceCount(ImageSource source, RepeatBehavior repeatBehavior)
+ {
+ var cacheKey = new CacheKey(source, repeatBehavior);
+ int count;
+ _referenceCount.TryGetValue(cacheKey, out count);
+ if (count > 0)
+ {
+ count--;
+ _referenceCount[cacheKey] = count;
+ }
+ if (count == 0)
+ {
+ _animationCache.Remove(cacheKey);
+ _referenceCount.Remove(cacheKey);
+ }
+ }
+
+ public static void AddAnimation(ImageSource source, RepeatBehavior repeatBehavior, ObjectAnimationUsingKeyFrames animation)
+ {
+ var key = new CacheKey(source, repeatBehavior);
+ _animationCache[key] = animation;
+ }
+
+ public static void RemoveAnimation(ImageSource source, RepeatBehavior repeatBehavior, ObjectAnimationUsingKeyFrames animation)
+ {
+ var key = new CacheKey(source, repeatBehavior);
+ _animationCache.Remove(key);
+ }
+
+ public static ObjectAnimationUsingKeyFrames GetAnimation(ImageSource source, RepeatBehavior repeatBehavior)
+ {
+ var key = new CacheKey(source, repeatBehavior);
+ ObjectAnimationUsingKeyFrames animation;
+ _animationCache.TryGetValue(key, out animation);
+ return animation;
+ }
+ }
+} \ No newline at end of file
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifApplicationExtension.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifApplicationExtension.cs
new file mode 100644
index 000000000..bbf8a5820
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifApplicationExtension.cs
@@ -0,0 +1,50 @@
+using System;
+using System.IO;
+using System.Text;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ // label 0xFF
+ internal class GifApplicationExtension : GifExtension
+ {
+ internal const int ExtensionLabel = 0xFF;
+
+ public int BlockSize { get; private set; }
+ public string ApplicationIdentifier { get; private set; }
+ public byte[] AuthenticationCode { get; private set; }
+ public byte[] Data { get; private set; }
+
+ private GifApplicationExtension()
+ {
+ }
+
+ internal override GifBlockKind Kind
+ {
+ get { return GifBlockKind.SpecialPurpose; }
+ }
+
+ internal static GifApplicationExtension ReadApplication(Stream stream)
+ {
+ var ext = new GifApplicationExtension();
+ ext.Read(stream);
+ return ext;
+ }
+
+ private void Read(Stream stream)
+ {
+ // Note: at this point, the label (0xFF) has already been read
+
+ byte[] bytes = new byte[12];
+ stream.ReadAll(bytes, 0, bytes.Length);
+ BlockSize = bytes[0]; // should always be 11
+ if (BlockSize != 11)
+ throw GifHelpers.InvalidBlockSizeException("Application Extension", 11, BlockSize);
+
+ ApplicationIdentifier = Encoding.ASCII.GetString(bytes, 1, 8);
+ byte[] authCode = new byte[3];
+ Array.Copy(bytes, 9, authCode, 0, 3);
+ AuthenticationCode = authCode;
+ Data = GifHelpers.ReadDataBlocks(stream, false);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifBlock.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifBlock.cs
new file mode 100644
index 000000000..331e7bd8f
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifBlock.cs
@@ -0,0 +1,28 @@
+using System.Collections.Generic;
+using System.IO;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ internal abstract class GifBlock
+ {
+ internal static GifBlock ReadBlock(Stream stream, IEnumerable<GifExtension> controlExtensions, bool metadataOnly)
+ {
+ int blockId = stream.ReadByte();
+ if (blockId < 0)
+ throw GifHelpers.UnexpectedEndOfStreamException();
+ switch (blockId)
+ {
+ case GifExtension.ExtensionIntroducer:
+ return GifExtension.ReadExtension(stream, controlExtensions, metadataOnly);
+ case GifFrame.ImageSeparator:
+ return GifFrame.ReadFrame(stream, controlExtensions, metadataOnly);
+ case GifTrailer.TrailerByte:
+ return GifTrailer.ReadTrailer();
+ default:
+ throw GifHelpers.UnknownBlockTypeException(blockId);
+ }
+ }
+
+ internal abstract GifBlockKind Kind { get; }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifBlockKind.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifBlockKind.cs
new file mode 100644
index 000000000..eab7ea2c1
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifBlockKind.cs
@@ -0,0 +1,10 @@
+namespace Tango.AnimatedGif.Decoding
+{
+ internal enum GifBlockKind
+ {
+ Control,
+ GraphicRendering,
+ SpecialPurpose,
+ Other
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifColor.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifColor.cs
new file mode 100644
index 000000000..8c0461941
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifColor.cs
@@ -0,0 +1,25 @@
+namespace Tango.AnimatedGif.Decoding
+{
+ internal struct GifColor
+ {
+ private readonly byte _r;
+ private readonly byte _g;
+ private readonly byte _b;
+
+ internal GifColor(byte r, byte g, byte b)
+ {
+ _r = r;
+ _g = g;
+ _b = b;
+ }
+
+ public byte R { get { return _r; } }
+ public byte G { get { return _g; } }
+ public byte B { get { return _b; } }
+
+ public override string ToString()
+ {
+ return string.Format("#{0:x2}{1:x2}{2:x2}", _r, _g, _b);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifCommentExtension.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifCommentExtension.cs
new file mode 100644
index 000000000..cde458d0f
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifCommentExtension.cs
@@ -0,0 +1,37 @@
+using System.IO;
+using System.Text;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ internal class GifCommentExtension : GifExtension
+ {
+ internal const int ExtensionLabel = 0xFE;
+
+ public string Text { get; private set; }
+
+ private GifCommentExtension()
+ {
+ }
+
+ internal override GifBlockKind Kind
+ {
+ get { return GifBlockKind.SpecialPurpose; }
+ }
+
+ internal static GifCommentExtension ReadComment(Stream stream)
+ {
+ var comment = new GifCommentExtension();
+ comment.Read(stream);
+ return comment;
+ }
+
+ private void Read(Stream stream)
+ {
+ // Note: at this point, the label (0xFE) has already been read
+
+ var bytes = GifHelpers.ReadDataBlocks(stream, false);
+ if (bytes != null)
+ Text = Encoding.ASCII.GetString(bytes);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifDecoderException.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifDecoderException.cs
new file mode 100644
index 000000000..7ff8ef6e0
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifDecoderException.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ [Serializable]
+ internal class GifDecoderException : Exception
+ {
+ internal GifDecoderException() { }
+ internal GifDecoderException(string message) : base(message) { }
+ internal GifDecoderException(string message, Exception inner) : base(message, inner) { }
+ protected GifDecoderException(
+ System.Runtime.Serialization.SerializationInfo info,
+ System.Runtime.Serialization.StreamingContext context)
+ : base(info, context) { }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifExtension.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifExtension.cs
new file mode 100644
index 000000000..fda8909ec
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifExtension.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+using System.IO;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ internal abstract class GifExtension : GifBlock
+ {
+ internal const int ExtensionIntroducer = 0x21;
+
+ internal static GifExtension ReadExtension(Stream stream, IEnumerable<GifExtension> controlExtensions, bool metadataOnly)
+ {
+ // Note: at this point, the Extension Introducer (0x21) has already been read
+
+ int label = stream.ReadByte();
+ if (label < 0)
+ throw GifHelpers.UnexpectedEndOfStreamException();
+ switch (label)
+ {
+ case GifGraphicControlExtension.ExtensionLabel:
+ return GifGraphicControlExtension.ReadGraphicsControl(stream);
+ case GifCommentExtension.ExtensionLabel:
+ return GifCommentExtension.ReadComment(stream);
+ case GifPlainTextExtension.ExtensionLabel:
+ return GifPlainTextExtension.ReadPlainText(stream, controlExtensions, metadataOnly);
+ case GifApplicationExtension.ExtensionLabel:
+ return GifApplicationExtension.ReadApplication(stream);
+ default:
+ throw GifHelpers.UnknownExtensionTypeException(label);
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifFile.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifFile.cs
new file mode 100644
index 000000000..500ce12a8
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifFile.cs
@@ -0,0 +1,86 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ internal class GifFile
+ {
+ public GifHeader Header { get; private set; }
+ public GifColor[] GlobalColorTable { get; set; }
+ public IList<GifFrame> Frames { get; set; }
+ public IList<GifExtension> Extensions { get; set; }
+ public ushort RepeatCount { get; set; }
+
+ private GifFile()
+ {
+ }
+
+ internal static GifFile ReadGifFile(Stream stream, bool metadataOnly)
+ {
+ var file = new GifFile();
+ file.Read(stream, metadataOnly);
+ return file;
+ }
+
+ private void Read(Stream stream, bool metadataOnly)
+ {
+ Header = GifHeader.ReadHeader(stream);
+
+ if (Header.LogicalScreenDescriptor.HasGlobalColorTable)
+ {
+ GlobalColorTable = GifHelpers.ReadColorTable(stream, Header.LogicalScreenDescriptor.GlobalColorTableSize);
+ }
+ ReadFrames(stream, metadataOnly);
+
+ var netscapeExtension =
+ Extensions
+ .OfType<GifApplicationExtension>()
+ .FirstOrDefault(GifHelpers.IsNetscapeExtension);
+
+ if (netscapeExtension != null)
+ RepeatCount = GifHelpers.GetRepeatCount(netscapeExtension);
+ else
+ RepeatCount = 1;
+ }
+
+ private void ReadFrames(Stream stream, bool metadataOnly)
+ {
+ List<GifFrame> frames = new List<GifFrame>();
+ List<GifExtension> controlExtensions = new List<GifExtension>();
+ List<GifExtension> specialExtensions = new List<GifExtension>();
+ while (true)
+ {
+ var block = GifBlock.ReadBlock(stream, controlExtensions, metadataOnly);
+
+ if (block.Kind == GifBlockKind.GraphicRendering)
+ controlExtensions = new List<GifExtension>();
+
+ if (block is GifFrame)
+ {
+ frames.Add((GifFrame)block);
+ }
+ else if (block is GifExtension)
+ {
+ var extension = (GifExtension)block;
+ switch (extension.Kind)
+ {
+ case GifBlockKind.Control:
+ controlExtensions.Add(extension);
+ break;
+ case GifBlockKind.SpecialPurpose:
+ specialExtensions.Add(extension);
+ break;
+ }
+ }
+ else if (block is GifTrailer)
+ {
+ break;
+ }
+ }
+
+ this.Frames = frames.AsReadOnly();
+ this.Extensions = specialExtensions.AsReadOnly();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifFrame.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifFrame.cs
new file mode 100644
index 000000000..85740ec87
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifFrame.cs
@@ -0,0 +1,47 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ internal class GifFrame : GifBlock
+ {
+ internal const int ImageSeparator = 0x2C;
+
+ public GifImageDescriptor Descriptor { get; private set; }
+ public GifColor[] LocalColorTable { get; private set; }
+ public IList<GifExtension> Extensions { get; private set; }
+ public GifImageData ImageData { get; private set; }
+
+ private GifFrame()
+ {
+ }
+
+ internal override GifBlockKind Kind
+ {
+ get { return GifBlockKind.GraphicRendering; }
+ }
+
+ internal static GifFrame ReadFrame(Stream stream, IEnumerable<GifExtension> controlExtensions, bool metadataOnly)
+ {
+ var frame = new GifFrame();
+
+ frame.Read(stream, controlExtensions, metadataOnly);
+
+ return frame;
+ }
+
+ private void Read(Stream stream, IEnumerable<GifExtension> controlExtensions, bool metadataOnly)
+ {
+ // Note: at this point, the Image Separator (0x2C) has already been read
+
+ Descriptor = GifImageDescriptor.ReadImageDescriptor(stream);
+ if (Descriptor.HasLocalColorTable)
+ {
+ LocalColorTable = GifHelpers.ReadColorTable(stream, Descriptor.LocalColorTableSize);
+ }
+ ImageData = GifImageData.ReadImageData(stream, metadataOnly);
+ Extensions = controlExtensions.ToList().AsReadOnly();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifGraphicControlExtension.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifGraphicControlExtension.cs
new file mode 100644
index 000000000..a3782c011
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifGraphicControlExtension.cs
@@ -0,0 +1,52 @@
+using System;
+using System.IO;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ // label 0xF9
+ internal class GifGraphicControlExtension : GifExtension
+ {
+ internal const int ExtensionLabel = 0xF9;
+
+ public int BlockSize { get; private set; }
+ public int DisposalMethod { get; private set; }
+ public bool UserInput { get; private set; }
+ public bool HasTransparency { get; private set; }
+ public int Delay { get; private set; }
+ public int TransparencyIndex { get; private set; }
+
+ private GifGraphicControlExtension()
+ {
+
+ }
+
+ internal override GifBlockKind Kind
+ {
+ get { return GifBlockKind.Control; }
+ }
+
+ internal static GifGraphicControlExtension ReadGraphicsControl(Stream stream)
+ {
+ var ext = new GifGraphicControlExtension();
+ ext.Read(stream);
+ return ext;
+ }
+
+ private void Read(Stream stream)
+ {
+ // Note: at this point, the label (0xF9) has already been read
+
+ byte[] bytes = new byte[6];
+ stream.ReadAll(bytes, 0, bytes.Length);
+ BlockSize = bytes[0]; // should always be 4
+ if (BlockSize != 4)
+ throw GifHelpers.InvalidBlockSizeException("Graphic Control Extension", 4, BlockSize);
+ byte packedFields = bytes[1];
+ DisposalMethod = (packedFields & 0x1C) >> 2;
+ UserInput = (packedFields & 0x02) != 0;
+ HasTransparency = (packedFields & 0x01) != 0;
+ Delay = BitConverter.ToUInt16(bytes, 2) * 10; // milliseconds
+ TransparencyIndex = bytes[4];
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifHeader.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifHeader.cs
new file mode 100644
index 000000000..b903b83c9
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifHeader.cs
@@ -0,0 +1,38 @@
+using System.IO;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ internal class GifHeader : GifBlock
+ {
+ public string Signature { get; private set; }
+ public string Version { get; private set; }
+ public GifLogicalScreenDescriptor LogicalScreenDescriptor { get; private set; }
+
+ private GifHeader()
+ {
+ }
+
+ internal override GifBlockKind Kind
+ {
+ get { return GifBlockKind.Other; }
+ }
+
+ internal static GifHeader ReadHeader(Stream stream)
+ {
+ var header = new GifHeader();
+ header.Read(stream);
+ return header;
+ }
+
+ private void Read(Stream stream)
+ {
+ Signature = GifHelpers.ReadString(stream, 3);
+ if (Signature != "GIF")
+ throw GifHelpers.InvalidSignatureException(Signature);
+ Version = GifHelpers.ReadString(stream, 3);
+ if (Version != "87a" && Version != "89a")
+ throw GifHelpers.UnsupportedVersionException(Version);
+ LogicalScreenDescriptor = GifLogicalScreenDescriptor.ReadLogicalScreenDescriptor(stream);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifHelpers.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifHelpers.cs
new file mode 100644
index 000000000..801b3da27
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifHelpers.cs
@@ -0,0 +1,110 @@
+using System;
+using System.IO;
+using System.Text;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ internal static class GifHelpers
+ {
+ public static string ReadString(Stream stream, int length)
+ {
+ byte[] bytes = new byte[length];
+ stream.ReadAll(bytes, 0, length);
+ return Encoding.ASCII.GetString(bytes);
+ }
+
+ public static byte[] ReadDataBlocks(Stream stream, bool discard)
+ {
+ MemoryStream ms = discard ? null : new MemoryStream();
+ using (ms)
+ {
+ int len;
+ while ((len = stream.ReadByte()) > 0)
+ {
+ byte[] bytes = new byte[len];
+ stream.ReadAll(bytes, 0, len);
+ if (ms != null)
+ ms.Write(bytes, 0, len);
+ }
+ if (ms != null)
+ return ms.ToArray();
+ return null;
+ }
+ }
+
+ public static GifColor[] ReadColorTable(Stream stream, int size)
+ {
+ int length = 3 * size;
+ byte[] bytes = new byte[length];
+ stream.ReadAll(bytes, 0, length);
+ GifColor[] colorTable = new GifColor[size];
+ for (int i = 0; i < size; i++)
+ {
+ byte r = bytes[3 * i];
+ byte g = bytes[3 * i + 1];
+ byte b = bytes[3 * i + 2];
+ colorTable[i] = new GifColor(r, g, b);
+ }
+ return colorTable;
+ }
+
+ public static bool IsNetscapeExtension(GifApplicationExtension ext)
+ {
+ return ext.ApplicationIdentifier == "NETSCAPE"
+ && Encoding.ASCII.GetString(ext.AuthenticationCode) == "2.0";
+ }
+
+ public static ushort GetRepeatCount(GifApplicationExtension ext)
+ {
+ if (ext.Data.Length >= 3)
+ {
+ return BitConverter.ToUInt16(ext.Data, 1);
+ }
+ return 1;
+ }
+
+ public static Exception UnexpectedEndOfStreamException()
+ {
+ return new GifDecoderException("Unexpected end of stream before trailer was encountered");
+ }
+
+ public static Exception UnknownBlockTypeException(int blockId)
+ {
+ return new GifDecoderException("Unknown block type: 0x" + blockId.ToString("x2"));
+ }
+
+ public static Exception UnknownExtensionTypeException(int extensionLabel)
+ {
+ return new GifDecoderException("Unknown extension type: 0x" + extensionLabel.ToString("x2"));
+ }
+
+ public static Exception InvalidBlockSizeException(string blockName, int expectedBlockSize, int actualBlockSize)
+ {
+ return new GifDecoderException(
+ string.Format(
+ "Invalid block size for {0}. Expected {1}, but was {2}",
+ blockName,
+ expectedBlockSize,
+ actualBlockSize));
+ }
+
+ public static Exception InvalidSignatureException(string signature)
+ {
+ return new GifDecoderException("Invalid file signature: " + signature);
+ }
+
+ public static Exception UnsupportedVersionException(string version)
+ {
+ return new GifDecoderException("Unsupported version: " + version);
+ }
+
+ public static void ReadAll(this Stream stream, byte[] buffer, int offset, int count)
+ {
+ int totalRead = 0;
+ while (totalRead < count)
+ {
+ totalRead += stream.Read(buffer, offset + totalRead, count - totalRead);
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifImageData.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifImageData.cs
new file mode 100644
index 000000000..32ae1359b
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifImageData.cs
@@ -0,0 +1,27 @@
+using System.IO;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ internal class GifImageData
+ {
+ public byte LzwMinimumCodeSize { get; set; }
+ public byte[] CompressedData { get; set; }
+
+ private GifImageData()
+ {
+ }
+
+ internal static GifImageData ReadImageData(Stream stream, bool metadataOnly)
+ {
+ var imgData = new GifImageData();
+ imgData.Read(stream, metadataOnly);
+ return imgData;
+ }
+
+ private void Read(Stream stream, bool metadataOnly)
+ {
+ LzwMinimumCodeSize = (byte)stream.ReadByte();
+ CompressedData = GifHelpers.ReadDataBlocks(stream, metadataOnly);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifImageDescriptor.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifImageDescriptor.cs
new file mode 100644
index 000000000..ad344ef4e
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifImageDescriptor.cs
@@ -0,0 +1,43 @@
+using System;
+using System.IO;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ internal class GifImageDescriptor
+ {
+ public int Left { get; private set; }
+ public int Top { get; private set; }
+ public int Width { get; private set; }
+ public int Height { get; private set; }
+ public bool HasLocalColorTable { get; private set; }
+ public bool Interlace { get; private set; }
+ public bool IsLocalColorTableSorted { get; private set; }
+ public int LocalColorTableSize { get; private set; }
+
+ private GifImageDescriptor()
+ {
+ }
+
+ internal static GifImageDescriptor ReadImageDescriptor(Stream stream)
+ {
+ var descriptor = new GifImageDescriptor();
+ descriptor.Read(stream);
+ return descriptor;
+ }
+
+ private void Read(Stream stream)
+ {
+ byte[] bytes = new byte[9];
+ stream.ReadAll(bytes, 0, bytes.Length);
+ Left = BitConverter.ToUInt16(bytes, 0);
+ Top = BitConverter.ToUInt16(bytes, 2);
+ Width = BitConverter.ToUInt16(bytes, 4);
+ Height = BitConverter.ToUInt16(bytes, 6);
+ byte packedFields = bytes[8];
+ HasLocalColorTable = (packedFields & 0x80) != 0;
+ Interlace = (packedFields & 0x40) != 0;
+ IsLocalColorTableSorted = (packedFields & 0x20) != 0;
+ LocalColorTableSize = 1 << ((packedFields & 0x07) + 1);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifLogicalScreenDescriptor.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifLogicalScreenDescriptor.cs
new file mode 100644
index 000000000..55bcb860b
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifLogicalScreenDescriptor.cs
@@ -0,0 +1,43 @@
+using System;
+using System.IO;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ internal class GifLogicalScreenDescriptor
+ {
+ public int Width { get; private set; }
+ public int Height { get; private set; }
+ public bool HasGlobalColorTable { get; private set; }
+ public int ColorResolution { get; private set; }
+ public bool IsGlobalColorTableSorted { get; private set; }
+ public int GlobalColorTableSize { get; private set; }
+ public int BackgroundColorIndex { get; private set; }
+ public double PixelAspectRatio { get; private set; }
+
+ internal static GifLogicalScreenDescriptor ReadLogicalScreenDescriptor(Stream stream)
+ {
+ var descriptor = new GifLogicalScreenDescriptor();
+ descriptor.Read(stream);
+ return descriptor;
+ }
+
+ private void Read(Stream stream)
+ {
+ byte[] bytes = new byte[7];
+ stream.ReadAll(bytes, 0, bytes.Length);
+
+ Width = BitConverter.ToUInt16(bytes, 0);
+ Height = BitConverter.ToUInt16(bytes, 2);
+ byte packedFields = bytes[4];
+ HasGlobalColorTable = (packedFields & 0x80) != 0;
+ ColorResolution = ((packedFields & 0x70) >> 4) + 1;
+ IsGlobalColorTableSorted = (packedFields & 0x08) != 0;
+ GlobalColorTableSize = 1 << ((packedFields & 0x07) + 1);
+ BackgroundColorIndex = bytes[5];
+ PixelAspectRatio =
+ bytes[5] == 0
+ ? 0.0
+ : (15 + bytes[5]) / 64.0;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifPlainTextExtension.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifPlainTextExtension.cs
new file mode 100644
index 000000000..ddd20c7b7
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifPlainTextExtension.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ // label 0x01
+ internal class GifPlainTextExtension : GifExtension
+ {
+ internal const int ExtensionLabel = 0x01;
+
+ public int BlockSize { get; private set; }
+ public int Left { get; private set; }
+ public int Top { get; private set; }
+ public int Width { get; private set; }
+ public int Height { get; private set; }
+ public int CellWidth { get; private set; }
+ public int CellHeight { get; private set; }
+ public int ForegroundColorIndex { get; private set; }
+ public int BackgroundColorIndex { get; private set; }
+ public string Text { get; private set; }
+
+ public IList<GifExtension> Extensions { get; private set; }
+
+ private GifPlainTextExtension()
+ {
+ }
+
+ internal override GifBlockKind Kind
+ {
+ get { return GifBlockKind.GraphicRendering; }
+ }
+
+ internal static GifPlainTextExtension ReadPlainText(Stream stream, IEnumerable<GifExtension> controlExtensions, bool metadataOnly)
+ {
+ var plainText = new GifPlainTextExtension();
+ plainText.Read(stream, controlExtensions, metadataOnly);
+ return plainText;
+ }
+
+ private void Read(Stream stream, IEnumerable<GifExtension> controlExtensions, bool metadataOnly)
+ {
+ // Note: at this point, the label (0x01) has already been read
+
+ byte[] bytes = new byte[13];
+ stream.ReadAll(bytes,0, bytes.Length);
+
+ BlockSize = bytes[0];
+ if (BlockSize != 12)
+ throw GifHelpers.InvalidBlockSizeException("Plain Text Extension", 12, BlockSize);
+
+ Left = BitConverter.ToUInt16(bytes, 1);
+ Top = BitConverter.ToUInt16(bytes, 3);
+ Width = BitConverter.ToUInt16(bytes, 5);
+ Height = BitConverter.ToUInt16(bytes, 7);
+ CellWidth = bytes[9];
+ CellHeight = bytes[10];
+ ForegroundColorIndex = bytes[11];
+ BackgroundColorIndex = bytes[12];
+
+ var dataBytes = GifHelpers.ReadDataBlocks(stream, metadataOnly);
+ Text = Encoding.ASCII.GetString(dataBytes);
+ Extensions = controlExtensions.ToList().AsReadOnly();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifTrailer.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifTrailer.cs
new file mode 100644
index 000000000..82e153ad3
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifTrailer.cs
@@ -0,0 +1,21 @@
+namespace Tango.AnimatedGif.Decoding
+{
+ internal class GifTrailer : GifBlock
+ {
+ internal const int TrailerByte = 0x3B;
+
+ private GifTrailer()
+ {
+ }
+
+ internal override GifBlockKind Kind
+ {
+ get { return GifBlockKind.Other; }
+ }
+
+ internal static GifTrailer ReadTrailer()
+ {
+ return new GifTrailer();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/ImageAnimationController.cs b/Software/Visual_Studio/Tango.AnimatedGif/ImageAnimationController.cs
new file mode 100644
index 000000000..239af9c8b
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/ImageAnimationController.cs
@@ -0,0 +1,192 @@
+using System;
+using System.ComponentModel;
+using System.Linq;
+using System.Windows.Controls;
+using System.Windows.Media.Animation;
+
+namespace Tango.AnimatedGif
+{
+ /// <summary>
+ /// Provides a way to pause, resume or seek a GIF animation.
+ /// </summary>
+ public class ImageAnimationController : IDisposable
+ {
+ private static readonly DependencyPropertyDescriptor _sourceDescriptor;
+
+ static ImageAnimationController()
+ {
+ _sourceDescriptor = DependencyPropertyDescriptor.FromProperty(Image.SourceProperty, typeof (Image));
+ }
+
+ private readonly Image _image;
+ private readonly ObjectAnimationUsingKeyFrames _animation;
+ private readonly AnimationClock _clock;
+ private readonly ClockController _clockController;
+
+
+ public double SpeedRatio
+ {
+ get
+ {
+ return _clockController.SpeedRatio;
+ }
+ set
+ {
+ _clockController.SpeedRatio = value;
+ }
+ }
+
+ internal ImageAnimationController(Image image, ObjectAnimationUsingKeyFrames animation, bool autoStart)
+ {
+ _image = image;
+ _animation = animation;
+ _animation.Completed += AnimationCompleted;
+ _clock = _animation.CreateClock();
+ _clockController = _clock.Controller;
+ _sourceDescriptor.AddValueChanged(image, ImageSourceChanged);
+
+ // ReSharper disable once PossibleNullReferenceException
+ _clockController.Pause();
+
+ _image.ApplyAnimationClock(Image.SourceProperty, _clock);
+
+ if (autoStart)
+ _clockController.Resume();
+ }
+
+ void AnimationCompleted(object sender, EventArgs e)
+ {
+ _image.RaiseEvent(new System.Windows.RoutedEventArgs(ImageBehavior.AnimationCompletedEvent, _image));
+ }
+
+ private void ImageSourceChanged(object sender, EventArgs e)
+ {
+ OnCurrentFrameChanged();
+ }
+
+ /// <summary>
+ /// Returns the number of frames in the image.
+ /// </summary>
+ public int FrameCount
+ {
+ get { return _animation.KeyFrames.Count; }
+ }
+
+ /// <summary>
+ /// Returns the duration of the animation.
+ /// </summary>
+ public TimeSpan Duration
+ {
+ get
+ {
+ return _animation.Duration.HasTimeSpan
+ ? _animation.Duration.TimeSpan
+ : TimeSpan.Zero;
+ }
+ }
+
+ /// <summary>
+ /// Returns a value that indicates whether the animation is paused.
+ /// </summary>
+ public bool IsPaused
+ {
+ get { return _clock.IsPaused; }
+ }
+
+ /// <summary>
+ /// Returns a value that indicates whether the animation is complete.
+ /// </summary>
+ public bool IsComplete
+ {
+ get { return _clock.CurrentState == ClockState.Filling; }
+ }
+
+ /// <summary>
+ /// Seeks the animation to the specified frame index.
+ /// </summary>
+ /// <param name="index">The index of the frame to seek to</param>
+ public void GotoFrame(int index)
+ {
+ var frame = _animation.KeyFrames[index];
+ _clockController.Seek(frame.KeyTime.TimeSpan, TimeSeekOrigin.BeginTime);
+ }
+
+ /// <summary>
+ /// Returns the current frame index.
+ /// </summary>
+ public int CurrentFrame
+ {
+ get
+ {
+ var time = _clock.CurrentTime;
+ var frameAndIndex =
+ _animation.KeyFrames
+ .Cast<ObjectKeyFrame>()
+ .Select((f, i) => new { Time = f.KeyTime.TimeSpan, Index = i })
+ .FirstOrDefault(fi => fi.Time >= time);
+ if (frameAndIndex != null)
+ return frameAndIndex.Index;
+ return -1;
+ }
+ }
+
+ /// <summary>
+ /// Pauses the animation.
+ /// </summary>
+ public void Pause()
+ {
+ _clockController.Pause();
+ }
+
+ /// <summary>
+ /// Starts or resumes the animation. If the animation is complete, it restarts from the beginning.
+ /// </summary>
+ public void Play()
+ {
+ _clockController.Resume();
+ }
+
+ /// <summary>
+ /// Raised when the current frame changes.
+ /// </summary>
+ public event EventHandler CurrentFrameChanged;
+
+ private void OnCurrentFrameChanged()
+ {
+ EventHandler handler = CurrentFrameChanged;
+ if (handler != null) handler(this, EventArgs.Empty);
+ }
+
+ /// <summary>
+ /// Finalizes the current object.
+ /// </summary>
+ ~ImageAnimationController()
+ {
+ Dispose(false);
+ }
+
+ /// <summary>
+ /// Disposes the current object.
+ /// </summary>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Disposes the current object
+ /// </summary>
+ /// <param name="disposing">true to dispose both managed an unmanaged resources, false to dispose only managed resources</param>
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ _image.BeginAnimation(Image.SourceProperty, null);
+ _animation.Completed -= AnimationCompleted;
+ _sourceDescriptor.RemoveValueChanged(_image, ImageSourceChanged);
+ _image.Source = null;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/ImageBehavior.cs b/Software/Visual_Studio/Tango.AnimatedGif/ImageBehavior.cs
new file mode 100644
index 000000000..a159106e6
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/ImageBehavior.cs
@@ -0,0 +1,966 @@
+using System;
+using System.ComponentModel;
+using System.IO;
+using System.IO.Packaging;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Media.Imaging;
+using System.Windows.Resources;
+using Tango.AnimatedGif.Decoding;
+
+namespace Tango.AnimatedGif
+{
+ /// <summary>
+ /// Provides attached properties that display animated GIFs in a standard Image control.
+ /// </summary>
+ public static class ImageBehavior
+ {
+ #region Public attached properties and events
+
+ /// <summary>
+ /// Gets the value of the <c>RepeatBehavior</c> attached property for the specified object.
+ /// </summary>
+ /// <param name="obj">The element from which to read the property value.</param>
+ /// <returns>The repeat behavior of the animated image.</returns>
+ [AttachedPropertyBrowsableForType(typeof(Image))]
+ public static double GetSpeedRatio(Image obj)
+ {
+ return (double)obj.GetValue(SpeedRatioProperty);
+ }
+
+ /// <summary>
+ /// Sets the value of the <c>RepeatBehavior</c> attached property for the specified object.
+ /// </summary>
+ /// <param name="obj">The element on which to set the property value.</param>
+ /// <param name="value">The repeat behavior of the animated image.</param>
+ public static void SetSpeedRatio(Image obj, double value)
+ {
+ obj.SetValue(SpeedRatioProperty, value);
+ }
+
+ /// <summary>
+ /// Identifies the <c>RepeatBehavior</c> attached property.
+ /// </summary>
+ public static readonly DependencyProperty SpeedRatioProperty =
+ DependencyProperty.RegisterAttached(
+ "SpeedRatio",
+ typeof(double),
+ typeof(ImageBehavior),
+ new UIPropertyMetadata(
+ 1.0,
+ SpeedRatioChanged));
+
+ private static void SpeedRatioChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var controller = GetAnimationController(d as Image);
+
+ if (controller != null)
+ {
+ controller.SpeedRatio = (double)e.NewValue;
+ }
+ }
+
+ /// <summary>
+ /// Gets the value of the <c>RepeatBehavior</c> attached property for the specified object.
+ /// </summary>
+ /// <param name="obj">The element from which to read the property value.</param>
+ /// <returns>The repeat behavior of the animated image.</returns>
+ [AttachedPropertyBrowsableForType(typeof(Image))]
+ public static bool GetEnableAnimation(Image obj)
+ {
+ return (bool)obj.GetValue(EnableAnimationProperty);
+ }
+
+ /// <summary>
+ /// Sets the value of the <c>RepeatBehavior</c> attached property for the specified object.
+ /// </summary>
+ /// <param name="obj">The element on which to set the property value.</param>
+ /// <param name="value">The repeat behavior of the animated image.</param>
+ public static void SetEnableAnimation(Image obj, bool value)
+ {
+ Application.Current.Dispatcher.BeginInvoke(new Action(() =>
+ {
+ obj.SetValue(EnableAnimationProperty, value);
+ }));
+ }
+
+ /// <summary>
+ /// Identifies the <c>RepeatBehavior</c> attached property.
+ /// </summary>
+ public static readonly DependencyProperty EnableAnimationProperty =
+ DependencyProperty.RegisterAttached(
+ "EnableAnimation",
+ typeof(bool),
+ typeof(ImageBehavior),
+ new UIPropertyMetadata(
+ false,
+ EnableAnimationChanged));
+
+ private static void EnableAnimationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var controller = GetAnimationController(d as Image);
+
+ if (controller != null)
+ {
+ if (e.NewValue != e.OldValue)
+ {
+ if ((bool)e.NewValue)
+ {
+ controller.SpeedRatio = GetSpeedRatio(d as Image);
+ controller.Play();
+ }
+ else
+ {
+ controller.Pause();
+ controller.GotoFrame(0);
+ }
+ }
+ }
+ }
+
+
+ /// <summary>
+ /// Gets the value of the <c>AnimatedSource</c> attached property for the specified object.
+ /// </summary>
+ /// <param name="obj">The element from which to read the property value.</param>
+ /// <returns>The currently displayed animated image.</returns>
+ [AttachedPropertyBrowsableForType(typeof(Image))]
+ public static ImageSource GetAnimatedSource(Image obj)
+ {
+ return (ImageSource)obj.GetValue(AnimatedSourceProperty);
+ }
+
+ /// <summary>
+ /// Sets the value of the <c>AnimatedSource</c> attached property for the specified object.
+ /// </summary>
+ /// <param name="obj">The element on which to set the property value.</param>
+ /// <param name="value">The animated image to display.</param>
+ public static void SetAnimatedSource(Image obj, ImageSource value)
+ {
+ obj.SetValue(AnimatedSourceProperty, value);
+ }
+
+ /// <summary>
+ /// Identifies the <c>AnimatedSource</c> attached property.
+ /// </summary>
+ public static readonly DependencyProperty AnimatedSourceProperty =
+ DependencyProperty.RegisterAttached(
+ "AnimatedSource",
+ typeof(ImageSource),
+ typeof(ImageBehavior),
+ new UIPropertyMetadata(
+ null,
+ AnimatedSourceChanged));
+
+ /// <summary>
+ /// Gets the value of the <c>RepeatBehavior</c> attached property for the specified object.
+ /// </summary>
+ /// <param name="obj">The element from which to read the property value.</param>
+ /// <returns>The repeat behavior of the animated image.</returns>
+ [AttachedPropertyBrowsableForType(typeof(Image))]
+ public static RepeatBehavior GetRepeatBehavior(Image obj)
+ {
+ return (RepeatBehavior)obj.GetValue(RepeatBehaviorProperty);
+ }
+
+ /// <summary>
+ /// Sets the value of the <c>RepeatBehavior</c> attached property for the specified object.
+ /// </summary>
+ /// <param name="obj">The element on which to set the property value.</param>
+ /// <param name="value">The repeat behavior of the animated image.</param>
+ public static void SetRepeatBehavior(Image obj, RepeatBehavior value)
+ {
+ obj.SetValue(RepeatBehaviorProperty, value);
+ }
+
+ /// <summary>
+ /// Identifies the <c>RepeatBehavior</c> attached property.
+ /// </summary>
+ public static readonly DependencyProperty RepeatBehaviorProperty =
+ DependencyProperty.RegisterAttached(
+ "RepeatBehavior",
+ typeof(RepeatBehavior),
+ typeof(ImageBehavior),
+ new UIPropertyMetadata(
+ default(RepeatBehavior),
+ RepeatBehaviorChanged));
+
+ /// <summary>
+ /// Gets the value of the <c>AnimateInDesignMode</c> attached property for the specified object.
+ /// </summary>
+ /// <param name="obj">The element from which to read the property value.</param>
+ /// <returns>true if GIF animations are shown in design mode; false otherwise.</returns>
+ public static bool GetAnimateInDesignMode(DependencyObject obj)
+ {
+ return (bool)obj.GetValue(AnimateInDesignModeProperty);
+ }
+
+ /// <summary>
+ /// Sets the value of the <c>AnimateInDesignMode</c> attached property for the specified object.
+ /// </summary>
+ /// <param name="obj">The element on which to set the property value.</param>
+ /// <param name="value">true to show GIF animations in design mode; false otherwise.</param>
+ public static void SetAnimateInDesignMode(DependencyObject obj, bool value)
+ {
+ obj.SetValue(AnimateInDesignModeProperty, value);
+ }
+
+ /// <summary>
+ /// Identifies the <c>AnimateInDesignMode</c> attached property.
+ /// </summary>
+ public static readonly DependencyProperty AnimateInDesignModeProperty =
+ DependencyProperty.RegisterAttached(
+ "AnimateInDesignMode",
+ typeof(bool),
+ typeof(ImageBehavior),
+ new FrameworkPropertyMetadata(
+ false,
+ FrameworkPropertyMetadataOptions.Inherits,
+ AnimateInDesignModeChanged));
+
+ /// <summary>
+ /// Gets the value of the <c>AutoStart</c> attached property for the specified object.
+ /// </summary>
+ /// <param name="obj">The element from which to read the property value.</param>
+ /// <returns>true if the animation should start immediately when loaded. Otherwise, false.</returns>
+ [AttachedPropertyBrowsableForType(typeof(Image))]
+ public static bool GetAutoStart(Image obj)
+ {
+ return (bool)obj.GetValue(AutoStartProperty);
+ }
+
+ /// <summary>
+ /// Sets the value of the <c>AutoStart</c> attached property for the specified object.
+ /// </summary>
+ /// <param name="obj">The element from which to read the property value.</param>
+ /// <param name="value">true if the animation should start immediately when loaded. Otherwise, false.</param>
+ /// <remarks>The default value is true.</remarks>
+ public static void SetAutoStart(Image obj, bool value)
+ {
+ obj.SetValue(AutoStartProperty, value);
+ }
+
+ /// <summary>
+ /// Identifies the <c>AutoStart</c> attached property.
+ /// </summary>
+ public static readonly DependencyProperty AutoStartProperty =
+ DependencyProperty.RegisterAttached("AutoStart", typeof(bool), typeof(ImageBehavior), new PropertyMetadata(false));
+
+ /// <summary>
+ /// Gets the animation controller for the specified <c>Image</c> control.
+ /// </summary>
+ /// <param name="imageControl"></param>
+ /// <returns></returns>
+ public static ImageAnimationController GetAnimationController(Image imageControl)
+ {
+ return (ImageAnimationController)imageControl.GetValue(AnimationControllerPropertyKey.DependencyProperty);
+ }
+
+ private static void SetAnimationController(DependencyObject obj, ImageAnimationController value)
+ {
+ obj.SetValue(AnimationControllerPropertyKey, value);
+ }
+
+ private static readonly DependencyPropertyKey AnimationControllerPropertyKey =
+ DependencyProperty.RegisterAttachedReadOnly("AnimationController", typeof(ImageAnimationController), typeof(ImageBehavior), new PropertyMetadata(null));
+
+ /// <summary>
+ /// Gets the value of the <c>IsAnimationLoaded</c> attached property for the specified object.
+ /// </summary>
+ /// <param name="image">The element from which to read the property value.</param>
+ /// <returns>true if the animation is loaded. Otherwise, false.</returns>
+ public static bool GetIsAnimationLoaded(Image image)
+ {
+ return (bool)image.GetValue(IsAnimationLoadedProperty);
+ }
+
+ private static void SetIsAnimationLoaded(Image image, bool value)
+ {
+ image.SetValue(IsAnimationLoadedPropertyKey, value);
+ }
+
+ private static readonly DependencyPropertyKey IsAnimationLoadedPropertyKey =
+ DependencyProperty.RegisterAttachedReadOnly("IsAnimationLoaded", typeof(bool), typeof(ImageBehavior), new PropertyMetadata(false));
+
+ /// <summary>
+ /// Identifies the <c>IsAnimationLoaded</c> attached property.
+ /// </summary>
+ public static readonly DependencyProperty IsAnimationLoadedProperty =
+ IsAnimationLoadedPropertyKey.DependencyProperty;
+
+ /// <summary>
+ /// Identifies the <c>AnimationLoaded</c> attached event.
+ /// </summary>
+ public static readonly RoutedEvent AnimationLoadedEvent =
+ EventManager.RegisterRoutedEvent(
+ "AnimationLoaded",
+ RoutingStrategy.Bubble,
+ typeof(RoutedEventHandler),
+ typeof(ImageBehavior));
+
+ /// <summary>
+ /// Adds a handler for the AnimationLoaded attached event.
+ /// </summary>
+ /// <param name="image">The UIElement that listens to this event.</param>
+ /// <param name="handler">The event handler to be added.</param>
+ public static void AddAnimationLoadedHandler(Image image, RoutedEventHandler handler)
+ {
+ if (image == null)
+ throw new ArgumentNullException("image");
+ if (handler == null)
+ throw new ArgumentNullException("handler");
+ image.AddHandler(AnimationLoadedEvent, handler);
+ }
+
+ /// <summary>
+ /// Removes a handler for the AnimationLoaded attached event.
+ /// </summary>
+ /// <param name="image">The UIElement that listens to this event.</param>
+ /// <param name="handler">The event handler to be removed.</param>
+ public static void RemoveAnimationLoadedHandler(Image image, RoutedEventHandler handler)
+ {
+ if (image == null)
+ throw new ArgumentNullException("image");
+ if (handler == null)
+ throw new ArgumentNullException("handler");
+ image.RemoveHandler(AnimationLoadedEvent, handler);
+ }
+
+ /// <summary>
+ /// Identifies the <c>AnimationCompleted</c> attached event.
+ /// </summary>
+ public static readonly RoutedEvent AnimationCompletedEvent =
+ EventManager.RegisterRoutedEvent(
+ "AnimationCompleted",
+ RoutingStrategy.Bubble,
+ typeof(RoutedEventHandler),
+ typeof(ImageBehavior));
+
+ /// <summary>
+ /// Adds a handler for the AnimationCompleted attached event.
+ /// </summary>
+ /// <param name="d">The UIElement that listens to this event.</param>
+ /// <param name="handler">The event handler to be added.</param>
+ public static void AddAnimationCompletedHandler(Image d, RoutedEventHandler handler)
+ {
+ var element = d as UIElement;
+ if (element == null)
+ return;
+ element.AddHandler(AnimationCompletedEvent, handler);
+ }
+
+ /// <summary>
+ /// Removes a handler for the AnimationCompleted attached event.
+ /// </summary>
+ /// <param name="d">The UIElement that listens to this event.</param>
+ /// <param name="handler">The event handler to be removed.</param>
+ public static void RemoveAnimationCompletedHandler(Image d, RoutedEventHandler handler)
+ {
+ var element = d as UIElement;
+ if (element == null)
+ return;
+ element.RemoveHandler(AnimationCompletedEvent, handler);
+ }
+
+ #endregion
+
+ private static void AnimatedSourceChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
+ {
+ Image imageControl = o as Image;
+ if (imageControl == null)
+ return;
+
+ var oldValue = e.OldValue as ImageSource;
+ var newValue = e.NewValue as ImageSource;
+ if (ReferenceEquals(oldValue, newValue))
+ {
+ if (imageControl.IsLoaded)
+ {
+ var isAnimLoaded = GetIsAnimationLoaded(imageControl);
+ if (!isAnimLoaded)
+ InitAnimationOrImage(imageControl);
+ }
+ return;
+ }
+ if (oldValue != null)
+ {
+ imageControl.Loaded -= ImageControlLoaded;
+ imageControl.Unloaded -= ImageControlUnloaded;
+ AnimationCache.DecrementReferenceCount(oldValue, GetRepeatBehavior(imageControl));
+ var controller = GetAnimationController(imageControl);
+ if (controller != null)
+ controller.Dispose();
+ imageControl.Source = null;
+ }
+ if (newValue != null)
+ {
+ imageControl.Loaded += ImageControlLoaded;
+ imageControl.Unloaded += ImageControlUnloaded;
+ if (imageControl.IsLoaded)
+ InitAnimationOrImage(imageControl);
+ }
+ }
+
+ private static void ImageControlLoaded(object sender, RoutedEventArgs e)
+ {
+ Image imageControl = sender as Image;
+ if (imageControl == null)
+ return;
+ InitAnimationOrImage(imageControl);
+ }
+
+ static void ImageControlUnloaded(object sender, RoutedEventArgs e)
+ {
+ Image imageControl = sender as Image;
+ if (imageControl == null)
+ return;
+ var source = GetAnimatedSource(imageControl);
+ if (source != null)
+ AnimationCache.DecrementReferenceCount(source, GetRepeatBehavior(imageControl));
+ var controller = GetAnimationController(imageControl);
+ if (controller != null)
+ controller.Dispose();
+ }
+
+ private static void RepeatBehaviorChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
+ {
+ Image imageControl = o as Image;
+ if (imageControl == null)
+ return;
+
+ ImageSource source = GetAnimatedSource(imageControl);
+ if (source != null)
+ {
+ if (!Equals(e.OldValue, e.NewValue))
+ AnimationCache.DecrementReferenceCount(source, (RepeatBehavior)e.OldValue);
+ if (imageControl.IsLoaded)
+ InitAnimationOrImage(imageControl);
+ }
+ }
+
+ private static void AnimateInDesignModeChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
+ {
+ Image imageControl = o as Image;
+ if (imageControl == null)
+ return;
+
+ bool newValue = (bool)e.NewValue;
+
+ ImageSource source = GetAnimatedSource(imageControl);
+ if (source != null && imageControl.IsLoaded)
+ {
+ if (newValue)
+ InitAnimationOrImage(imageControl);
+ else
+ imageControl.BeginAnimation(Image.SourceProperty, null);
+ }
+ }
+
+ private static void InitAnimationOrImage(Image imageControl)
+ {
+ var controller = GetAnimationController(imageControl);
+ if (controller != null)
+ controller.Dispose();
+ SetAnimationController(imageControl, null);
+ SetIsAnimationLoaded(imageControl, false);
+
+ BitmapSource source = GetAnimatedSource(imageControl) as BitmapSource;
+ bool isInDesignMode = DesignerProperties.GetIsInDesignMode(imageControl);
+ bool animateInDesignMode = GetAnimateInDesignMode(imageControl);
+ bool shouldAnimate = !isInDesignMode || animateInDesignMode;
+
+ // For a BitmapImage with a relative UriSource, the loading is deferred until
+ // BaseUri is set. This method will be called again when BaseUri is set.
+ bool isLoadingDeferred = IsLoadingDeferred(source);
+
+ if (source != null && shouldAnimate && !isLoadingDeferred)
+ {
+ // Case of image being downloaded: retry after download is complete
+ if (source.IsDownloading)
+ {
+ EventHandler handler = null;
+ handler = (sender, args) =>
+ {
+ source.DownloadCompleted -= handler;
+ InitAnimationOrImage(imageControl);
+ };
+ source.DownloadCompleted += handler;
+ imageControl.Source = source;
+ return;
+ }
+
+ var animation = GetAnimation(imageControl, source);
+ if (animation != null)
+ {
+ if (animation.KeyFrames.Count > 0)
+ {
+ // For some reason, it sometimes throws an exception the first time... the second time it works.
+ TryTwice(() => imageControl.Source = (ImageSource)animation.KeyFrames[0].Value);
+ }
+ else
+ {
+ imageControl.Source = source;
+ }
+
+ controller = new ImageAnimationController(imageControl, animation, GetAutoStart(imageControl));
+ SetAnimationController(imageControl, controller);
+ SetIsAnimationLoaded(imageControl, true);
+ imageControl.RaiseEvent(new RoutedEventArgs(AnimationLoadedEvent, imageControl));
+ return;
+ }
+ }
+ imageControl.Source = source;
+ if (source != null)
+ {
+ SetIsAnimationLoaded(imageControl, true);
+ imageControl.RaiseEvent(new RoutedEventArgs(AnimationLoadedEvent, imageControl));
+ }
+ }
+
+ private static ObjectAnimationUsingKeyFrames GetAnimation(Image imageControl, BitmapSource source)
+ {
+ var animation = AnimationCache.GetAnimation(source, GetRepeatBehavior(imageControl));
+ if (animation != null)
+ return animation;
+ GifFile gifMetadata;
+ var decoder = GetDecoder(source, out gifMetadata) as GifBitmapDecoder;
+ if (decoder != null && decoder.Frames.Count > 1)
+ {
+ var fullSize = GetFullSize(decoder, gifMetadata);
+ int index = 0;
+ animation = new ObjectAnimationUsingKeyFrames();
+ var totalDuration = TimeSpan.Zero;
+ BitmapSource baseFrame = null;
+ foreach (var rawFrame in decoder.Frames)
+ {
+ var metadata = GetFrameMetadata(decoder, gifMetadata, index);
+
+ var frame = MakeFrame(fullSize, rawFrame, metadata, baseFrame);
+ var keyFrame = new DiscreteObjectKeyFrame(frame, totalDuration);
+ animation.KeyFrames.Add(keyFrame);
+
+ totalDuration += metadata.Delay;
+
+ switch (metadata.DisposalMethod)
+ {
+ case FrameDisposalMethod.None:
+ case FrameDisposalMethod.DoNotDispose:
+ baseFrame = frame;
+ break;
+ case FrameDisposalMethod.RestoreBackground:
+ if (IsFullFrame(metadata, fullSize))
+ {
+ baseFrame = null;
+ }
+ else
+ {
+ baseFrame = ClearArea(frame, metadata);
+ }
+ break;
+ case FrameDisposalMethod.RestorePrevious:
+ // Reuse same base frame
+ break;
+ }
+
+ index++;
+ }
+ animation.Duration = totalDuration;
+
+ animation.RepeatBehavior = GetActualRepeatBehavior(imageControl, decoder, gifMetadata);
+
+ //Removed animation cache for PPC AsyncAdornerControl!
+
+ //AnimationCache.AddAnimation(source, GetRepeatBehavior(imageControl), animation);
+ //AnimationCache.IncrementReferenceCount(source, GetRepeatBehavior(imageControl));
+ return animation;
+ }
+ return null;
+ }
+
+ private static BitmapSource ClearArea(BitmapSource frame, FrameMetadata metadata)
+ {
+ DrawingVisual visual = new DrawingVisual();
+ using (var context = visual.RenderOpen())
+ {
+ var fullRect = new Rect(0, 0, frame.PixelWidth, frame.PixelHeight);
+ var clearRect = new Rect(metadata.Left, metadata.Top, metadata.Width, metadata.Height);
+ var clip = Geometry.Combine(
+ new RectangleGeometry(fullRect),
+ new RectangleGeometry(clearRect),
+ GeometryCombineMode.Exclude,
+ null);
+ context.PushClip(clip);
+ context.DrawImage(frame, fullRect);
+ }
+
+ var bitmap = new RenderTargetBitmap(
+ frame.PixelWidth, frame.PixelHeight,
+ frame.DpiX, frame.DpiY,
+ PixelFormats.Pbgra32);
+ bitmap.Render(visual);
+
+ var result = new WriteableBitmap(bitmap);
+
+ if (result.CanFreeze && !result.IsFrozen)
+ result.Freeze();
+ return result;
+ }
+
+ private static void TryTwice(Action action)
+ {
+ try
+ {
+ action();
+ }
+ catch (Exception)
+ {
+ action();
+ }
+ }
+
+ private static bool IsLoadingDeferred(BitmapSource source)
+ {
+ var bmp = source as BitmapImage;
+ if (bmp == null)
+ return false;
+ if (bmp.UriSource != null && !bmp.UriSource.IsAbsoluteUri)
+ return bmp.BaseUri == null;
+ return false;
+ }
+
+ private static BitmapDecoder GetDecoder(BitmapSource image, out GifFile gifFile)
+ {
+ gifFile = null;
+ BitmapDecoder decoder = null;
+ Stream stream = null;
+ Uri uri = null;
+ BitmapCreateOptions createOptions = BitmapCreateOptions.None;
+
+ var bmp = image as BitmapImage;
+ if (bmp != null)
+ {
+ createOptions = bmp.CreateOptions;
+ if (bmp.StreamSource != null)
+ {
+ stream = bmp.StreamSource;
+ }
+ else if (bmp.UriSource != null)
+ {
+ uri = bmp.UriSource;
+ if (bmp.BaseUri != null && !uri.IsAbsoluteUri)
+ uri = new Uri(bmp.BaseUri, uri);
+ }
+ }
+ else
+ {
+ BitmapFrame frame = image as BitmapFrame;
+ if (frame != null)
+ {
+ decoder = frame.Decoder;
+ Uri.TryCreate(frame.BaseUri, frame.ToString(), out uri);
+ }
+ }
+
+ if (decoder == null)
+ {
+ if (stream != null)
+ {
+ stream.Position = 0;
+ decoder = BitmapDecoder.Create(stream, createOptions, BitmapCacheOption.OnLoad);
+ }
+ else if (uri != null && uri.IsAbsoluteUri)
+ {
+ decoder = BitmapDecoder.Create(uri, createOptions, BitmapCacheOption.OnLoad);
+ }
+ }
+
+ if (decoder is GifBitmapDecoder && !CanReadNativeMetadata(decoder))
+ {
+ if (stream != null)
+ {
+ stream.Position = 0;
+ gifFile = GifFile.ReadGifFile(stream, true);
+ }
+ else if (uri != null)
+ {
+ gifFile = DecodeGifFile(uri);
+ }
+ else
+ {
+ throw new InvalidOperationException("Can't get URI or Stream from the source. AnimatedSource should be either a BitmapImage, or a BitmapFrame constructed from a URI.");
+ }
+ }
+ if (decoder == null)
+ {
+ throw new InvalidOperationException("Can't get a decoder from the source. AnimatedSource should be either a BitmapImage or a BitmapFrame.");
+ }
+ return decoder;
+ }
+
+ private static bool CanReadNativeMetadata(BitmapDecoder decoder)
+ {
+ try
+ {
+ var m = decoder.Metadata;
+ return m != null;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ private static GifFile DecodeGifFile(Uri uri)
+ {
+ Stream stream = null;
+ if (uri.Scheme == PackUriHelper.UriSchemePack)
+ {
+ StreamResourceInfo sri;
+ if (uri.Authority == "siteoforigin:,,,")
+ sri = Application.GetRemoteStream(uri);
+ else
+ sri = Application.GetResourceStream(uri);
+
+ if (sri != null)
+ stream = sri.Stream;
+ }
+ else
+ {
+ WebClient wc = new WebClient();
+ stream = wc.OpenRead(uri);
+ }
+ if (stream != null)
+ {
+ using (stream)
+ {
+ return GifFile.ReadGifFile(stream, true);
+ }
+ }
+ return null;
+ }
+
+ private static bool IsFullFrame(FrameMetadata metadata, Int32Size fullSize)
+ {
+ return metadata.Left == 0
+ && metadata.Top == 0
+ && metadata.Width == fullSize.Width
+ && metadata.Height == fullSize.Height;
+ }
+
+ private static BitmapSource MakeFrame(
+ Int32Size fullSize,
+ BitmapSource rawFrame, FrameMetadata metadata,
+ BitmapSource baseFrame)
+ {
+ if (baseFrame == null && IsFullFrame(metadata, fullSize))
+ {
+ // No previous image to combine with, and same size as the full image
+ // Just return the frame as is
+ return rawFrame;
+ }
+
+ DrawingVisual visual = new DrawingVisual();
+ using (var context = visual.RenderOpen())
+ {
+ if (baseFrame != null)
+ {
+ var fullRect = new Rect(0, 0, fullSize.Width, fullSize.Height);
+ context.DrawImage(baseFrame, fullRect);
+ }
+
+ var rect = new Rect(metadata.Left, metadata.Top, metadata.Width, metadata.Height);
+ context.DrawImage(rawFrame, rect);
+ }
+ var bitmap = new RenderTargetBitmap(
+ fullSize.Width, fullSize.Height,
+ 96, 96,
+ PixelFormats.Pbgra32);
+ bitmap.Render(visual);
+
+ var result = new WriteableBitmap(bitmap);
+
+ if (result.CanFreeze && !result.IsFrozen)
+ result.Freeze();
+ return result;
+ }
+
+ private static RepeatBehavior GetActualRepeatBehavior(Image imageControl, BitmapDecoder decoder, GifFile gifMetadata)
+ {
+ // If specified explicitly, use this value
+ var repeatBehavior = GetRepeatBehavior(imageControl);
+ if (repeatBehavior != default(RepeatBehavior))
+ return repeatBehavior;
+
+ int repeatCount;
+ if (gifMetadata != null)
+ {
+ repeatCount = gifMetadata.RepeatCount;
+ }
+ else
+ {
+ repeatCount = GetRepeatCount(decoder);
+ }
+ if (repeatCount == 0)
+ return RepeatBehavior.Forever;
+ return new RepeatBehavior(repeatCount);
+ }
+
+ private static int GetRepeatCount(BitmapDecoder decoder)
+ {
+ var ext = GetApplicationExtension(decoder, "NETSCAPE2.0");
+ if (ext != null)
+ {
+ byte[] bytes = ext.GetQueryOrNull<byte[]>("/Data");
+ if (bytes != null && bytes.Length >= 4)
+ return BitConverter.ToUInt16(bytes, 2);
+ }
+ return 1;
+ }
+
+ private static BitmapMetadata GetApplicationExtension(BitmapDecoder decoder, string application)
+ {
+ int count = 0;
+ string query = "/appext";
+ BitmapMetadata extension = decoder.Metadata.GetQueryOrNull<BitmapMetadata>(query);
+ while (extension != null)
+ {
+ byte[] bytes = extension.GetQueryOrNull<byte[]>("/Application");
+ if (bytes != null)
+ {
+ string extApplication = Encoding.ASCII.GetString(bytes);
+ if (extApplication == application)
+ return extension;
+ }
+ query = string.Format("/[{0}]appext", ++count);
+ extension = decoder.Metadata.GetQueryOrNull<BitmapMetadata>(query);
+ }
+ return null;
+ }
+
+ private static FrameMetadata GetFrameMetadata(BitmapDecoder decoder, GifFile gifMetadata, int frameIndex)
+ {
+ if (gifMetadata != null && gifMetadata.Frames.Count > frameIndex)
+ {
+ return GetFrameMetadata(gifMetadata.Frames[frameIndex]);
+ }
+
+ return GetFrameMetadata(decoder.Frames[frameIndex]);
+ }
+
+ private static FrameMetadata GetFrameMetadata(BitmapFrame frame)
+ {
+ var metadata = (BitmapMetadata)frame.Metadata;
+ var delay = TimeSpan.FromMilliseconds(100);
+ var metadataDelay = metadata.GetQueryOrDefault("/grctlext/Delay", 10);
+ if (metadataDelay != 0)
+ delay = TimeSpan.FromMilliseconds(metadataDelay * 10);
+ var disposalMethod = (FrameDisposalMethod)metadata.GetQueryOrDefault("/grctlext/Disposal", 0);
+ var frameMetadata = new FrameMetadata
+ {
+ Left = metadata.GetQueryOrDefault("/imgdesc/Left", 0),
+ Top = metadata.GetQueryOrDefault("/imgdesc/Top", 0),
+ Width = metadata.GetQueryOrDefault("/imgdesc/Width", frame.PixelWidth),
+ Height = metadata.GetQueryOrDefault("/imgdesc/Height", frame.PixelHeight),
+ Delay = delay,
+ DisposalMethod = disposalMethod
+ };
+ return frameMetadata;
+ }
+
+ private static FrameMetadata GetFrameMetadata(GifFrame gifMetadata)
+ {
+ var d = gifMetadata.Descriptor;
+ var frameMetadata = new FrameMetadata
+ {
+ Left = d.Left,
+ Top = d.Top,
+ Width = d.Width,
+ Height = d.Height,
+ Delay = TimeSpan.FromMilliseconds(100),
+ DisposalMethod = FrameDisposalMethod.None
+ };
+
+ var gce = gifMetadata.Extensions.OfType<GifGraphicControlExtension>().FirstOrDefault();
+ if (gce != null)
+ {
+ if (gce.Delay != 0)
+ frameMetadata.Delay = TimeSpan.FromMilliseconds(gce.Delay);
+ frameMetadata.DisposalMethod = (FrameDisposalMethod)gce.DisposalMethod;
+ }
+ return frameMetadata;
+ }
+
+ private static Int32Size GetFullSize(BitmapDecoder decoder, GifFile gifMetadata)
+ {
+ if (gifMetadata != null)
+ {
+ var lsd = gifMetadata.Header.LogicalScreenDescriptor;
+ return new Int32Size(lsd.Width, lsd.Height);
+ }
+ int width = decoder.Metadata.GetQueryOrDefault("/logscrdesc/Width", 0);
+ int height = decoder.Metadata.GetQueryOrDefault("/logscrdesc/Height", 0);
+ return new Int32Size(width, height);
+ }
+
+ private struct Int32Size
+ {
+ public Int32Size(int width, int height) : this()
+ {
+ Width = width;
+ Height = height;
+ }
+
+ public int Width { get; private set; }
+ public int Height { get; private set; }
+ }
+
+ private class FrameMetadata
+ {
+ public int Left { get; set; }
+ public int Top { get; set; }
+ public int Width { get; set; }
+ public int Height { get; set; }
+ public TimeSpan Delay { get; set; }
+ public FrameDisposalMethod DisposalMethod { get; set; }
+ }
+
+ private enum FrameDisposalMethod
+ {
+ None = 0,
+ DoNotDispose = 1,
+ RestoreBackground = 2,
+ RestorePrevious = 3
+ }
+
+ private static T GetQueryOrDefault<T>(this BitmapMetadata metadata, string query, T defaultValue)
+ {
+ if (metadata.ContainsQuery(query))
+ return (T)Convert.ChangeType(metadata.GetQuery(query), typeof(T));
+ return defaultValue;
+ }
+
+ private static T GetQueryOrNull<T>(this BitmapMetadata metadata, string query)
+ where T : class
+ {
+ if (metadata.ContainsQuery(query))
+ return metadata.GetQuery(query) as T;
+ return null;
+ }
+
+ // For debug purposes
+ //private static void Save(BitmapSource image, string path)
+ //{
+ // var encoder = new PngBitmapEncoder();
+ // encoder.Frames.Add(BitmapFrame.Create(image));
+ // using (var stream = File.OpenWrite(path))
+ // {
+ // encoder.Save(stream);
+ // }
+ //}
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Properties/AssemblyInfo.cs b/Software/Visual_Studio/Tango.AnimatedGif/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..2c8b459c4
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Properties/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+using System.Windows.Markup;
+
+[assembly: AssemblyTitle("Tango - GIF Animation Library")]
+[assembly: ComVisible(false)]
+
+[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)] \ No newline at end of file
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Tango.AnimatedGif.csproj b/Software/Visual_Studio/Tango.AnimatedGif/Tango.AnimatedGif.csproj
new file mode 100644
index 000000000..18d991271
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Tango.AnimatedGif.csproj
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{D129789C-3096-4D0B-8DD7-FE24A4DF4B21}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Tango.AnimatedGif</RootNamespace>
+ <AssemblyName>Tango.AnimatedGif</AssemblyName>
+ <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <TargetFrameworkProfile>
+ </TargetFrameworkProfile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\Build\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <Prefer32Bit>false</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\Build\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <DocumentationFile>
+ </DocumentationFile>
+ <Prefer32Bit>false</Prefer32Bit>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="PresentationCore" />
+ <Reference Include="PresentationFramework" />
+ <Reference Include="System" />
+ <Reference Include="System.Xaml" />
+ <Reference Include="System.Xml" />
+ <Reference Include="WindowsBase" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Versioning\Core.cs">
+ <Link>Core.cs</Link>
+ </Compile>
+ <Compile Include="AnimationCache.cs" />
+ <Compile Include="Decoding\GifApplicationExtension.cs" />
+ <Compile Include="Decoding\GifBlock.cs" />
+ <Compile Include="Decoding\GifBlockKind.cs" />
+ <Compile Include="Decoding\GifColor.cs" />
+ <Compile Include="Decoding\GifCommentExtension.cs" />
+ <Compile Include="Decoding\GifDecoderException.cs" />
+ <Compile Include="Decoding\GifExtension.cs" />
+ <Compile Include="Decoding\GifFile.cs" />
+ <Compile Include="Decoding\GifFrame.cs" />
+ <Compile Include="Decoding\GifGraphicControlExtension.cs" />
+ <Compile Include="Decoding\GifHeader.cs" />
+ <Compile Include="Decoding\GifHelpers.cs" />
+ <Compile Include="Decoding\GifImageData.cs" />
+ <Compile Include="Decoding\GifImageDescriptor.cs" />
+ <Compile Include="Decoding\GifLogicalScreenDescriptor.cs" />
+ <Compile Include="Decoding\GifPlainTextExtension.cs" />
+ <Compile Include="Decoding\GifTrailer.cs" />
+ <Compile Include="ImageAnimationController.cs" />
+ <Compile Include="ImageBehavior.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="UserControl1.xaml.cs">
+ <DependentUpon>UserControl1.xaml</DependentUpon>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <Page Include="UserControl1.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/UserControl1.xaml b/Software/Visual_Studio/Tango.AnimatedGif/UserControl1.xaml
new file mode 100644
index 000000000..1ae2a1cd4
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/UserControl1.xaml
@@ -0,0 +1,12 @@
+<UserControl x:Class="Tango.AnimatedGif.UserControl1"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:local="clr-namespace:Tango.AnimatedGif"
+ mc:Ignorable="d"
+ d:DesignHeight="300" d:DesignWidth="300">
+ <Grid>
+
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/UserControl1.xaml.cs b/Software/Visual_Studio/Tango.AnimatedGif/UserControl1.xaml.cs
new file mode 100644
index 000000000..8d90270d3
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/UserControl1.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Tango.AnimatedGif
+{
+ /// <summary>
+ /// Interaction logic for UserControl1.xaml
+ /// </summary>
+ public partial class UserControl1 : UserControl
+ {
+ public UserControl1()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.BL/ColorConversion/TangoColorConverter.cs b/Software/Visual_Studio/Tango.BL/ColorConversion/TangoColorConverter.cs
index 210d4d3e8..147309f54 100644
--- a/Software/Visual_Studio/Tango.BL/ColorConversion/TangoColorConverter.cs
+++ b/Software/Visual_Studio/Tango.BL/ColorConversion/TangoColorConverter.cs
@@ -82,6 +82,11 @@ namespace Tango.BL.ColorConversion
return GetSuggestions(brushStop).OutOfGamut;
}
+ public static int GetLeastCommonProcessParametersTableIndex(IEnumerable<BrushStop> stops)
+ {
+ return stops.Select(x => GetSuggestions(x)).Select(x => x.SingleCoordinates).Min(x => x.ProcessParametersTableIndex);
+ }
+
private static ConversionInput CreateConversionInput(BrushStop brushStop)
{
ConversionInput conversionInput = new ConversionInput();
diff --git a/Software/Visual_Studio/Tango.BL/Entities/HardwareMotor.cs b/Software/Visual_Studio/Tango.BL/Entities/HardwareMotor.cs
index 3104dfafd..cb7abbd64 100644
--- a/Software/Visual_Studio/Tango.BL/Entities/HardwareMotor.cs
+++ b/Software/Visual_Studio/Tango.BL/Entities/HardwareMotor.cs
@@ -23,7 +23,7 @@ namespace Tango.BL.Entities
/// <summary>
///
- ///</summary>
+ /// </summary>
[Table("HARDWARE_MOTORS")]
public partial class HardwareMotor : ObservableEntity<HardwareMotor>
@@ -584,8 +584,8 @@ namespace Tango.BL.Entities
protected Int32 _fsspd;
/// <summary>
- ///The speed in which the motor moves to full step operation.
- ///</summary>
+ /// The speed in which the motor moves to full step operation.
+ /// </summary>
[Column("FS_SPD")]
diff --git a/Software/Visual_Studio/Tango.BL/Entities/Job.cs b/Software/Visual_Studio/Tango.BL/Entities/Job.cs
index 15ac3d199..0adfe0b23 100644
--- a/Software/Visual_Studio/Tango.BL/Entities/Job.cs
+++ b/Software/Visual_Studio/Tango.BL/Entities/Job.cs
@@ -23,7 +23,7 @@ namespace Tango.BL.Entities
/// <summary>
///
- ///</summary>
+ /// </summary>
[Table("JOBS")]
public partial class Job : ObservableEntity<Job>
@@ -433,13 +433,13 @@ namespace Tango.BL.Entities
protected Int32 _status;
/// <summary>
- ///0 = Draft
- ///1 = PendingApproval
- ///2 = Ready
- ///3 = Approved
- ///4 = Disrupted
- ///5 = Completed
- ///</summary>
+ /// 0 = Draft
+ /// 1 = PendingApproval
+ /// 2 = Ready
+ /// 3 = Approved
+ /// 4 = Disrupted
+ /// 5 = Completed
+ /// </summary>
[Column("STATUS")]
@@ -505,9 +505,9 @@ namespace Tango.BL.Entities
protected Int32 _type;
/// <summary>
- ///0 = Sewing
- ///1 = Embroidery
- ///</summary>
+ /// 0 = Sewing
+ /// 1 = Embroidery
+ /// </summary>
[Column("TYPE")]
@@ -551,9 +551,9 @@ namespace Tango.BL.Entities
protected Int32 _spoolsdistribution;
/// <summary>
- ///0 = All segments per spool
- ///1 = One segments per spool
- ///</summary>
+ /// 0 = All segments per spool
+ /// 1 = One segments per spool
+ /// </summary>
[Column("SPOOLS_DISTRIBUTION")]
@@ -593,6 +593,28 @@ namespace Tango.BL.Entities
}
+ protected Int32 _sampleunitsormeters;
+
+ /// <summary>
+ /// Gets or sets the job sample units or meters.
+ /// </summary>
+
+ [Column("SAMPLE_UNITS_OR_METERS")]
+
+ public Int32 SampleUnitsOrMeters
+ {
+ get
+ {
+ return _sampleunitsormeters;
+ }
+
+ set
+ {
+ _sampleunitsormeters = value; RaisePropertyChanged(nameof(SampleUnitsOrMeters));
+ }
+
+ }
+
protected ColorSpace _colorspace;
/// <summary>
diff --git a/Software/Visual_Studio/Tango.BL/EntitiesExtensions/Job.cs b/Software/Visual_Studio/Tango.BL/EntitiesExtensions/Job.cs
index 4c68f3c72..292fe000d 100644
--- a/Software/Visual_Studio/Tango.BL/EntitiesExtensions/Job.cs
+++ b/Software/Visual_Studio/Tango.BL/EntitiesExtensions/Job.cs
@@ -56,6 +56,19 @@ namespace Tango.BL.Entities
}
/// <summary>
+ /// Gets the total job segments length multiplied by number of units if it is an embroidery job.
+ /// </summary>
+ [NotMapped]
+ [JsonIgnore]
+ public double LengthIncludingNumberOfUnits
+ {
+ get
+ {
+ return _lastLength * NumberOfUnits;
+ }
+ }
+
+ /// <summary>
/// Gets or sets the job <see cref="Status"/> property as <see cref="JobStatus"/> enum instead of int.
/// </summary>
[NotMapped]
@@ -193,6 +206,7 @@ namespace Tango.BL.Entities
if (_lastLength != GetLength())
{
RaisePropertyChanged(nameof(Length));
+ RaisePropertyChanged(nameof(LengthIncludingNumberOfUnits));
LengthChanged?.Invoke(this, new EventArgs());
}
}
@@ -349,7 +363,7 @@ namespace Tango.BL.Entities
/// <returns></returns>
public TimeSpan GetEstimatedDuration(ProcessParametersTable processParameters)
{
- return TimeSpan.FromSeconds(Length / (processParameters.DyeingSpeed / 100d));
+ return TimeSpan.FromSeconds(LengthIncludingNumberOfUnits / (processParameters.DyeingSpeed / 100d));
}
/// <summary>
diff --git a/Software/Visual_Studio/Tango.Core/ExtensionMethods/IEnumerableExtensions.cs b/Software/Visual_Studio/Tango.Core/ExtensionMethods/IEnumerableExtensions.cs
index ffe164a53..0f15ad060 100644
--- a/Software/Visual_Studio/Tango.Core/ExtensionMethods/IEnumerableExtensions.cs
+++ b/Software/Visual_Studio/Tango.Core/ExtensionMethods/IEnumerableExtensions.cs
@@ -80,5 +80,17 @@ public static class IEnumerableExtensions
{
return String.Join(separator, source);
}
+
+ /// <summary>
+ /// Returns a distinct collection by the specified property.
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="source">The source.</param>
+ /// <param name="property">The property.</param>
+ /// <returns></returns>
+ public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> source, Func<T, TKey> property)
+ {
+ return source.GroupBy(property).Select(g => g.First());
+ }
}
diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB.cs b/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB.cs
index 433dacee4..109e876b5 100644
--- a/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB.cs
+++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB.cs
@@ -49,6 +49,7 @@ namespace Tango.DAL.Remote.DB
public string CUSTOMER_GUID { get; set; }
public int SPOOLS_DISTRIBUTION { get; set; }
public int NUMBER_OF_HEADS { get; set; }
+ public int SAMPLE_UNITS_OR_METERS { get; set; }
public virtual COLOR_SPACES COLOR_SPACES { get; set; }
public virtual CUSTOMER CUSTOMER { get; set; }
diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx
index 7f17f8940..9030a9f0b 100644
--- a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx
+++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx
@@ -582,6 +582,7 @@
<Property Name="CUSTOMER_GUID" Type="varchar" MaxLength="36" />
<Property Name="SPOOLS_DISTRIBUTION" Type="int" Nullable="false" />
<Property Name="NUMBER_OF_HEADS" Type="int" Nullable="false" />
+ <Property Name="SAMPLE_UNITS_OR_METERS" Type="int" Nullable="false" />
</EntityType>
<EntityType Name="LINEAR_MASS_DENSITY_UNITS">
<Key>
@@ -3397,6 +3398,7 @@
<Property Name="CUSTOMER_GUID" Type="String" MaxLength="36" FixedLength="false" Unicode="false" />
<Property Name="SPOOLS_DISTRIBUTION" Type="Int32" Nullable="false" />
<Property Name="NUMBER_OF_HEADS" Type="Int32" Nullable="false" />
+ <Property Name="SAMPLE_UNITS_OR_METERS" Type="Int32" Nullable="false" />
<NavigationProperty Name="COLOR_SPACES" Relationship="RemoteModel.FK_JOBS_COLOR_SPACES" FromRole="JOB" ToRole="COLOR_SPACES" />
<NavigationProperty Name="CUSTOMER" Relationship="RemoteModel.FK_JOBS_CUSTOMERS" FromRole="JOB" ToRole="CUSTOMER" />
<NavigationProperty Name="JOB_RUNS" Relationship="RemoteModel.FK_JOB_RUNS_JOBS" FromRole="JOB" ToRole="JOB_RUNS" />
@@ -5462,6 +5464,7 @@
<EntitySetMapping Name="JOBS">
<EntityTypeMapping TypeName="RemoteModel.JOB">
<MappingFragment StoreEntitySet="JOBS">
+ <ScalarProperty Name="SAMPLE_UNITS_OR_METERS" ColumnName="SAMPLE_UNITS_OR_METERS" />
<ScalarProperty Name="NUMBER_OF_HEADS" ColumnName="NUMBER_OF_HEADS" />
<ScalarProperty Name="SPOOLS_DISTRIBUTION" ColumnName="SPOOLS_DISTRIBUTION" />
<ScalarProperty Name="CUSTOMER_GUID" ColumnName="CUSTOMER_GUID" />
diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram
index 668abf151..305fe3ebd 100644
--- a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram
+++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram
@@ -5,78 +5,78 @@
<!-- Diagram content (shape and connector positions) -->
<edmx:Diagrams>
<Diagram DiagramId="f9ae01d708754bbd997add25a4bacc79" Name="Diagram1">
- <EntityTypeShape EntityType="RemoteModel.ACTION_TYPES" Width="1.5" PointX="6" PointY="75.5" />
- <EntityTypeShape EntityType="RemoteModel.ADDRESS" Width="1.5" PointX="1.5" PointY="37.625" />
- <EntityTypeShape EntityType="RemoteModel.APPLICATION_DISPLAY_PANEL_VERSIONS" Width="1.5" PointX="1.5" PointY="76.625" />
- <EntityTypeShape EntityType="RemoteModel.APPLICATION_FIRMWARE_VERSIONS" Width="1.5" PointX="1.5" PointY="73.625" />
- <EntityTypeShape EntityType="RemoteModel.APPLICATION_OS_VERSIONS" Width="1.5" PointX="1.5" PointY="79.5" />
- <EntityTypeShape EntityType="RemoteModel.APPLICATION_VERSIONS" Width="1.5" PointX="1.5" PointY="70.75" />
- <EntityTypeShape EntityType="RemoteModel.BRUSH_STOPS" Width="1.5" PointX="12.75" PointY="11.125" />
- <EntityTypeShape EntityType="RemoteModel.CARTRIDGE_TYPES" Width="1.5" PointX="3" PointY="4.5" />
- <EntityTypeShape EntityType="RemoteModel.CAT" Width="1.5" PointX="5.25" PointY="10.75" />
- <EntityTypeShape EntityType="RemoteModel.CCT" Width="1.5" PointX="5.25" PointY="34" />
- <EntityTypeShape EntityType="RemoteModel.COLOR_CATALOGS" Width="1.5" PointX="10.5" PointY="5.5" />
- <EntityTypeShape EntityType="RemoteModel.COLOR_SPACES" Width="1.5" PointX="6" PointY="18.5" />
- <EntityTypeShape EntityType="RemoteModel.CONFIGURATION" Width="1.5" PointX="0.75" PointY="61.625" />
- <EntityTypeShape EntityType="RemoteModel.CONTACT" Width="1.5" PointX="1.5" PointY="50" />
- <EntityTypeShape EntityType="RemoteModel.CUSTOMER" Width="1.5" PointX="6" PointY="22" />
- <EntityTypeShape EntityType="RemoteModel.DISPENSER_TYPES" Width="1.5" PointX="3" PointY="95.375" />
- <EntityTypeShape EntityType="RemoteModel.EMBEDDED_FIRMWARE_VERSIONS" Width="1.5" PointX="1.5" PointY="67.875" />
- <EntityTypeShape EntityType="RemoteModel.EMBEDDED_SOFTWARE_VERSIONS" Width="1.5" PointX="1.5" PointY="57.875" />
- <EntityTypeShape EntityType="RemoteModel.EVENT_TYPES" Width="1.5" PointX="6" PointY="70.625" />
- <EntityTypeShape EntityType="RemoteModel.EVENT_TYPES_ACTIONS" Width="1.5" PointX="8.25" PointY="71.5" />
- <EntityTypeShape EntityType="RemoteModel.EVENT_TYPES_CATEGORIES" Width="1.5" PointX="3.75" PointY="74.75" />
- <EntityTypeShape EntityType="RemoteModel.EVENT_TYPES_GROUPS" Width="1.5" PointX="3.75" PointY="71.625" />
- <EntityTypeShape EntityType="RemoteModel.FIBER_SHAPES" Width="1.5" PointX="0.75" PointY="27.5" />
- <EntityTypeShape EntityType="RemoteModel.FIBER_SYNTHS" Width="1.5" PointX="0.75" PointY="21.625" />
- <EntityTypeShape EntityType="RemoteModel.HARDWARE_DANCER_TYPES" Width="1.5" PointX="4.5" PointY="64.375" />
- <EntityTypeShape EntityType="RemoteModel.HARDWARE_DANCERS" Width="1.5" PointX="6.75" PointY="53.5" />
- <EntityTypeShape EntityType="RemoteModel.HARDWARE_MOTOR_TYPES" Width="1.5" PointX="7.5" PointY="49.375" />
- <EntityTypeShape EntityType="RemoteModel.HARDWARE_MOTORS" Width="1.5" PointX="9.75" PointY="52.125" />
- <EntityTypeShape EntityType="RemoteModel.HARDWARE_PID_CONTROL_TYPES" Width="1.5" PointX="1.5" PointY="91.375" />
- <EntityTypeShape EntityType="RemoteModel.HARDWARE_PID_CONTROLS" Width="1.5" PointX="3.75" PointY="57.75" />
- <EntityTypeShape EntityType="RemoteModel.HARDWARE_SPEED_SENSOR_TYPES" Width="1.5" PointX="1.5" PointY="87.375" />
- <EntityTypeShape EntityType="RemoteModel.HARDWARE_SPEED_SENSORS" Width="1.5" PointX="3.75" PointY="54.25" />
- <EntityTypeShape EntityType="RemoteModel.HARDWARE_VERSIONS" Width="1.5" PointX="1.5" PointY="54" />
- <EntityTypeShape EntityType="RemoteModel.HARDWARE_WINDER_TYPES" Width="1.5" PointX="1.5" PointY="83.375" />
- <EntityTypeShape EntityType="RemoteModel.HARDWARE_WINDERS" Width="1.5" PointX="3.75" PointY="50.375" />
- <EntityTypeShape EntityType="RemoteModel.HTML_PAGES" Width="1.5" PointX="3.75" PointY="68.25" />
- <EntityTypeShape EntityType="RemoteModel.IDS_PACK_FORMULAS" Width="1.5" PointX="3" PointY="8.25" />
- <EntityTypeShape EntityType="RemoteModel.IDS_PACKS" Width="1.5" PointX="5.25" PointY="43.75" />
- <EntityTypeShape EntityType="RemoteModel.JOB_RUNS" Width="1.5" PointX="10.5" PointY="16.75" />
- <EntityTypeShape EntityType="RemoteModel.JOB" Width="1.5" PointX="8.25" PointY="12.25" />
- <EntityTypeShape EntityType="RemoteModel.LINEAR_MASS_DENSITY_UNITS" Width="1.5" PointX="0.75" PointY="10.875" />
- <EntityTypeShape EntityType="RemoteModel.LIQUID_TYPES" Width="1.5" PointX="3" PointY="21" />
- <EntityTypeShape EntityType="RemoteModel.LIQUID_TYPES_RMLS" Width="1.5" PointX="5.25" PointY="15" />
- <EntityTypeShape EntityType="RemoteModel.MACHINE_STUDIO_VERSIONS" Width="1.5" PointX="8.25" PointY="38" />
- <EntityTypeShape EntityType="RemoteModel.MACHINE_VERSIONS" Width="1.5" PointX="0.75" PointY="46.5" />
- <EntityTypeShape EntityType="RemoteModel.MACHINE" Width="1.5" PointX="3" PointY="44.625" />
- <EntityTypeShape EntityType="RemoteModel.MACHINES_CONFIGURATIONS" Width="1.5" PointX="6.25" PointY="58.625" />
- <EntityTypeShape EntityType="RemoteModel.MACHINES_EVENTS" Width="1.5" PointX="8.25" PointY="42" />
+ <EntityTypeShape EntityType="RemoteModel.ACTION_TYPES" Width="1.5" PointX="6" PointY="98.25" />
+ <EntityTypeShape EntityType="RemoteModel.ADDRESS" Width="1.5" PointX="1.5" PointY="43.5" />
+ <EntityTypeShape EntityType="RemoteModel.APPLICATION_DISPLAY_PANEL_VERSIONS" Width="1.5" PointX="1.5" PointY="70.25" />
+ <EntityTypeShape EntityType="RemoteModel.APPLICATION_FIRMWARE_VERSIONS" Width="1.5" PointX="1.5" PointY="57.5" />
+ <EntityTypeShape EntityType="RemoteModel.APPLICATION_OS_VERSIONS" Width="1.5" PointX="1.5" PointY="60.5" />
+ <EntityTypeShape EntityType="RemoteModel.APPLICATION_VERSIONS" Width="1.5" PointX="1.5" PointY="76" />
+ <EntityTypeShape EntityType="RemoteModel.BRUSH_STOPS" Width="1.5" PointX="12.75" PointY="14.5" />
+ <EntityTypeShape EntityType="RemoteModel.CARTRIDGE_TYPES" Width="1.5" PointX="6.75" PointY="84.75" />
+ <EntityTypeShape EntityType="RemoteModel.CAT" Width="1.5" PointX="5.25" PointY="19.75" />
+ <EntityTypeShape EntityType="RemoteModel.CCT" Width="1.5" PointX="5.25" PointY="11.375" />
+ <EntityTypeShape EntityType="RemoteModel.COLOR_CATALOGS" Width="1.5" PointX="10.5" PointY="20.875" />
+ <EntityTypeShape EntityType="RemoteModel.COLOR_SPACES" Width="1.5" PointX="6" PointY="23.75" />
+ <EntityTypeShape EntityType="RemoteModel.CONFIGURATION" Width="1.5" PointX="3.75" PointY="65.125" />
+ <EntityTypeShape EntityType="RemoteModel.CONTACT" Width="1.5" PointX="1.5" PointY="47.75" />
+ <EntityTypeShape EntityType="RemoteModel.CUSTOMER" Width="1.5" PointX="6" PointY="46.125" />
+ <EntityTypeShape EntityType="RemoteModel.DISPENSER_TYPES" Width="1.5" PointX="6.75" PointY="81.375" />
+ <EntityTypeShape EntityType="RemoteModel.EMBEDDED_FIRMWARE_VERSIONS" Width="1.5" PointX="1.5" PointY="67.25" />
+ <EntityTypeShape EntityType="RemoteModel.EMBEDDED_SOFTWARE_VERSIONS" Width="1.5" PointX="1.5" PointY="73.125" />
+ <EntityTypeShape EntityType="RemoteModel.EVENT_TYPES" Width="1.5" PointX="6" PointY="93.375" />
+ <EntityTypeShape EntityType="RemoteModel.EVENT_TYPES_ACTIONS" Width="1.5" PointX="8.25" PointY="94.25" />
+ <EntityTypeShape EntityType="RemoteModel.EVENT_TYPES_CATEGORIES" Width="1.5" PointX="3.75" PointY="97.5" />
+ <EntityTypeShape EntityType="RemoteModel.EVENT_TYPES_GROUPS" Width="1.5" PointX="3.75" PointY="94.375" />
+ <EntityTypeShape EntityType="RemoteModel.FIBER_SHAPES" Width="1.5" PointX="0.75" PointY="18.75" />
+ <EntityTypeShape EntityType="RemoteModel.FIBER_SYNTHS" Width="1.5" PointX="0.75" PointY="27.5" />
+ <EntityTypeShape EntityType="RemoteModel.HARDWARE_DANCER_TYPES" Width="1.5" PointX="4.5" PointY="71.75" />
+ <EntityTypeShape EntityType="RemoteModel.HARDWARE_DANCERS" Width="1.5" PointX="6.75" PointY="55.875" />
+ <EntityTypeShape EntityType="RemoteModel.HARDWARE_MOTOR_TYPES" Width="1.5" PointX="6.5" PointY="77.75" />
+ <EntityTypeShape EntityType="RemoteModel.HARDWARE_MOTORS" Width="1.5" PointX="8.75" PointY="61.5" />
+ <EntityTypeShape EntityType="RemoteModel.HARDWARE_PID_CONTROL_TYPES" Width="1.5" PointX="1.5" PointY="53.75" />
+ <EntityTypeShape EntityType="RemoteModel.HARDWARE_PID_CONTROLS" Width="1.5" PointX="3.75" PointY="58.125" />
+ <EntityTypeShape EntityType="RemoteModel.HARDWARE_SPEED_SENSOR_TYPES" Width="1.5" PointX="4.5" PointY="81.75" />
+ <EntityTypeShape EntityType="RemoteModel.HARDWARE_SPEED_SENSORS" Width="1.5" PointX="6.75" PointY="69.625" />
+ <EntityTypeShape EntityType="RemoteModel.HARDWARE_VERSIONS" Width="1.5" PointX="1.5" PointY="63.375" />
+ <EntityTypeShape EntityType="RemoteModel.HARDWARE_WINDER_TYPES" Width="1.5" PointX="7.5" PointY="73.75" />
+ <EntityTypeShape EntityType="RemoteModel.HARDWARE_WINDERS" Width="1.5" PointX="9.75" PointY="57.75" />
+ <EntityTypeShape EntityType="RemoteModel.HTML_PAGES" Width="1.5" PointX="3.75" PointY="91" />
+ <EntityTypeShape EntityType="RemoteModel.IDS_PACK_FORMULAS" Width="1.5" PointX="6.75" PointY="87.625" />
+ <EntityTypeShape EntityType="RemoteModel.IDS_PACKS" Width="1.5" PointX="9" PointY="44" />
+ <EntityTypeShape EntityType="RemoteModel.JOB_RUNS" Width="1.5" PointX="10.5" PointY="13.25" />
+ <EntityTypeShape EntityType="RemoteModel.JOB" Width="1.5" PointX="8.25" PointY="12.125" />
+ <EntityTypeShape EntityType="RemoteModel.LINEAR_MASS_DENSITY_UNITS" Width="1.5" PointX="0.75" PointY="21.625" />
+ <EntityTypeShape EntityType="RemoteModel.LIQUID_TYPES" Width="1.5" PointX="3" PointY="21.875" />
+ <EntityTypeShape EntityType="RemoteModel.LIQUID_TYPES_RMLS" Width="1.5" PointX="5.25" PointY="16" />
+ <EntityTypeShape EntityType="RemoteModel.MACHINE_STUDIO_VERSIONS" Width="1.5" PointX="8.25" PointY="39.125" />
+ <EntityTypeShape EntityType="RemoteModel.MACHINE_VERSIONS" Width="1.5" PointX="3.75" PointY="54.25" />
+ <EntityTypeShape EntityType="RemoteModel.MACHINE" Width="1.5" PointX="6" PointY="64" />
+ <EntityTypeShape EntityType="RemoteModel.MACHINES_CONFIGURATIONS" Width="1.5" PointX="11.25" PointY="66.125" />
+ <EntityTypeShape EntityType="RemoteModel.MACHINES_EVENTS" Width="1.5" PointX="8.25" PointY="51.75" />
<EntityTypeShape EntityType="RemoteModel.MEDIA_COLORS" Width="1.5" PointX="0.75" PointY="15" />
- <EntityTypeShape EntityType="RemoteModel.MEDIA_CONDITIONS" Width="1.5" PointX="0.75" PointY="18.75" />
- <EntityTypeShape EntityType="RemoteModel.MEDIA_MATERIALS" Width="1.5" PointX="0.75" PointY="7.875" />
+ <EntityTypeShape EntityType="RemoteModel.MEDIA_CONDITIONS" Width="1.5" PointX="0.75" PointY="7.875" />
+ <EntityTypeShape EntityType="RemoteModel.MEDIA_MATERIALS" Width="1.5" PointX="0.75" PointY="10.875" />
<EntityTypeShape EntityType="RemoteModel.MEDIA_PURPOSES" Width="1.5" PointX="0.75" PointY="24.625" />
- <EntityTypeShape EntityType="RemoteModel.MID_TANK_TYPES" Width="1.5" PointX="3" PointY="25.125" />
- <EntityTypeShape EntityType="RemoteModel.ORGANIZATION" Width="1.5" PointX="0.75" PointY="32.875" />
- <EntityTypeShape EntityType="RemoteModel.PERMISSION" Width="1.5" PointX="9" PointY="24.25" />
- <EntityTypeShape EntityType="RemoteModel.PROCESS_PARAMETERS_TABLES" Width="1.5" PointX="7.5" PointY="27.375" />
- <EntityTypeShape EntityType="RemoteModel.PROCESS_PARAMETERS_TABLES_GROUPS" Width="1.5" PointX="5.25" PointY="29" />
+ <EntityTypeShape EntityType="RemoteModel.MID_TANK_TYPES" Width="1.5" PointX="6.75" PointY="7.25" />
+ <EntityTypeShape EntityType="RemoteModel.ORGANIZATION" Width="1.5" PointX="3.75" PointY="45.625" />
+ <EntityTypeShape EntityType="RemoteModel.PERMISSION" Width="1.5" PointX="9" PointY="8.375" />
+ <EntityTypeShape EntityType="RemoteModel.PROCESS_PARAMETERS_TABLES" Width="1.5" PointX="7.5" PointY="31.75" />
+ <EntityTypeShape EntityType="RemoteModel.PROCESS_PARAMETERS_TABLES_GROUPS" Width="1.5" PointX="5.25" PointY="33.25" />
<EntityTypeShape EntityType="RemoteModel.RML" Width="1.5" PointX="3" PointY="12.375" />
- <EntityTypeShape EntityType="RemoteModel.ROLE" Width="1.5" PointX="9" PointY="34.125" />
- <EntityTypeShape EntityType="RemoteModel.ROLES_PERMISSIONS" Width="1.5" PointX="11.25" PointY="34.25" />
- <EntityTypeShape EntityType="RemoteModel.SEGMENT" Width="1.5" PointX="10.5" PointY="13.25" />
- <EntityTypeShape EntityType="RemoteModel.SPOOL_TYPES" Width="1.5" PointX="6" PointY="6" />
+ <EntityTypeShape EntityType="RemoteModel.ROLE" Width="1.5" PointX="9" PointY="28.25" />
+ <EntityTypeShape EntityType="RemoteModel.ROLES_PERMISSIONS" Width="1.5" PointX="11.25" PointY="28.375" />
+ <EntityTypeShape EntityType="RemoteModel.SEGMENT" Width="1.5" PointX="10.5" PointY="16.625" />
+ <EntityTypeShape EntityType="RemoteModel.SPOOL_TYPES" Width="1.5" PointX="6" PointY="49.75" />
<EntityTypeShape EntityType="RemoteModel.SYNC_CONFIGURATIONS" Width="1.5" PointX="0.75" PointY="0.75" />
<EntityTypeShape EntityType="RemoteModel.sysdiagram" Width="1.5" PointX="2.75" PointY="0.75" />
- <EntityTypeShape EntityType="RemoteModel.TECH_CONTROLLERS" Width="1.5" PointX="8.75" PointY="0.75" />
- <EntityTypeShape EntityType="RemoteModel.TECH_DISPENSERS" Width="1.5" PointX="10.75" PointY="0.75" />
- <EntityTypeShape EntityType="RemoteModel.TECH_IOS" Width="1.5" PointX="12.75" PointY="0.75" />
- <EntityTypeShape EntityType="RemoteModel.TECH_MONITORS" Width="1.5" PointX="12.75" PointY="5.75" />
- <EntityTypeShape EntityType="RemoteModel.TECH_VALVES" Width="1.5" PointX="14.75" PointY="0.75" />
- <EntityTypeShape EntityType="RemoteModel.USER" Width="1.5" PointX="6" PointY="38.25" />
- <EntityTypeShape EntityType="RemoteModel.USERS_ROLES" Width="1.5" PointX="11.25" PointY="39.125" />
- <EntityTypeShape EntityType="RemoteModel.WINDING_METHODS" Width="1.5" PointX="6" PointY="2.125" />
+ <EntityTypeShape EntityType="RemoteModel.TECH_CONTROLLERS" Width="1.5" PointX="0.75" PointY="3.75" />
+ <EntityTypeShape EntityType="RemoteModel.TECH_DISPENSERS" Width="1.5" PointX="2.75" PointY="3.75" />
+ <EntityTypeShape EntityType="RemoteModel.TECH_IOS" Width="1.5" PointX="4.75" PointY="0.75" />
+ <EntityTypeShape EntityType="RemoteModel.TECH_MONITORS" Width="1.5" PointX="6.75" PointY="0.75" />
+ <EntityTypeShape EntityType="RemoteModel.TECH_VALVES" Width="1.5" PointX="2.75" PointY="6.75" />
+ <EntityTypeShape EntityType="RemoteModel.USER" Width="1.5" PointX="6" PointY="38.375" />
+ <EntityTypeShape EntityType="RemoteModel.USERS_ROLES" Width="1.5" PointX="11.25" PointY="39.25" />
+ <EntityTypeShape EntityType="RemoteModel.WINDING_METHODS" Width="1.5" PointX="6" PointY="27.25" />
<AssociationConnector Association="RemoteModel.FK_EVENTS_ACTIONS_ACTIONS" />
<AssociationConnector Association="RemoteModel.FK_ORGANIZATIONS_ADDRESSES" />
<AssociationConnector Association="RemoteModel.FK_USERS_ADDRESSES" />
diff --git a/Software/Visual_Studio/Tango.Integration/Operation/IMachineOperator.cs b/Software/Visual_Studio/Tango.Integration/Operation/IMachineOperator.cs
index c0bf390c0..24ec40fc3 100644
--- a/Software/Visual_Studio/Tango.Integration/Operation/IMachineOperator.cs
+++ b/Software/Visual_Studio/Tango.Integration/Operation/IMachineOperator.cs
@@ -94,6 +94,15 @@ namespace Tango.Integration.Operation
IMachineEventsStateProvider MachineEventsStateProvider { get; set; }
/// <summary>
+ /// Prints the specified job.
+ /// The process parameters table will be calculated using color conversion gamut region.
+ /// This method cannot accept brush stops with 'Volume' as color space.
+ /// </summary>
+ /// <param name="job">The job.</param>
+ /// <returns></returns>
+ JobHandler Print(Job job);
+
+ /// <summary>
/// Prints the specified job using the specified job parameters.
/// </summary>
/// <param name="job">The job.</param>
diff --git a/Software/Visual_Studio/Tango.Integration/Operation/JobHandler.cs b/Software/Visual_Studio/Tango.Integration/Operation/JobHandler.cs
index 02c663e1b..02579b20a 100644
--- a/Software/Visual_Studio/Tango.Integration/Operation/JobHandler.cs
+++ b/Software/Visual_Studio/Tango.Integration/Operation/JobHandler.cs
@@ -116,7 +116,9 @@ namespace Tango.Integration.Operation
Status = new RunningJobStatus();
Status.TotalTime = job.GetEstimatedDuration(processParameters);
- Status.TotalProgress = Job.Length;
+ Status.RemainingUnits = job.NumberOfUnits;
+ Status.TotalProgress = Job.LengthIncludingNumberOfUnits;
+ Status.CurrentUnitTotalProgress = Job.Length;
Status.Progress = 0;
Status.RemainingTime = Status.TotalTime;
Status.RemainingProgress = Status.TotalProgress;
@@ -177,6 +179,8 @@ namespace Tango.Integration.Operation
Status.Progress = s.Progress;
Status.RemainingTime = Status.TotalTime - Job.TranslateProgressToTime(Status.Progress, ProcessParameters);
Status.RemainingProgress = Status.TotalProgress - Status.Progress;
+ Status.RemainingUnits = Job.NumberOfUnits - (int)((Job.LengthIncludingNumberOfUnits / Status.CurrentUnitTotalProgress) * Status.Progress / Status.TotalProgress);
+ Status.CurrentUnitProgress = s.Progress - (Status.CurrentUnitTotalProgress * (Job.NumberOfUnits - Status.RemainingUnits));
if (s.Message != _lastStatusMessage && s.Message != String.Empty)
{
diff --git a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs
index 8cc2465b9..d75e2fc49 100644
--- a/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs
+++ b/Software/Visual_Studio/Tango.Integration/Operation/MachineOperator.cs
@@ -21,6 +21,8 @@ using Tango.BL.Entities;
using Tango.PMR.Hardware;
using Google.Protobuf;
using Tango.PMR.Connection;
+using Tango.BL.Enumerations;
+using Tango.BL.ColorConversion;
namespace Tango.Integration.Operation
{
@@ -471,6 +473,74 @@ namespace Tango.Integration.Operation
#region Public Methods
/// <summary>
+ /// Prints the specified job.
+ /// The process parameters table will be calculated using color conversion gamut region.
+ /// This method cannot accept brush stops with 'Volume' as color space.
+ /// </summary>
+ /// <param name="job">The job.</param>
+ /// <returns></returns>
+ public JobHandler Print(Job job)
+ {
+ //Check not brush stop has color space 'Volume'.
+ if (job.Segments.SelectMany(x => x.BrushStops).ToList().Exists(x => x.ColorSpace.Code == ColorSpaces.Volume.ToInt32()))
+ {
+ throw new InvalidOperationException("Cannot print a brush stop with volume color space when process parameters table has not been specified.");
+ }
+
+ //Get least common process parameters table index.
+ int processParametersTableIndex = TangoColorConverter.GetLeastCommonProcessParametersTableIndex(job.Segments.SelectMany(x => x.BrushStops));
+
+ if (job.Rml == null)
+ {
+ throw new NullReferenceException("Job RML is null");
+ }
+
+ var processGroup = job.Rml.ProcessParametersTablesGroups.FirstOrDefault(x => x.Active);
+
+ if (processGroup == null)
+ {
+ throw new NullReferenceException("Could not locate an active process parameters tables group for RML " + job.Rml.Name);
+ }
+
+ var processParameters = processGroup.ProcessParametersTables.FirstOrDefault(x => x.TableIndex == processParametersTableIndex);
+
+ if (processParameters == null)
+ {
+ throw new NullReferenceException("Could not locate process parameters table index " + processParametersTableIndex + " in group " + processGroup.Name + " for RML " + job.Rml.Name);
+ }
+
+ //Perform color correction
+ foreach (var stop in job.Segments.SelectMany(x => x.BrushStops))
+ {
+ if (stop.LiquidVolumes == null)
+ {
+ var suggestions = TangoColorConverter.GetSuggestions(stop);
+
+ if (suggestions.OutOfGamut)
+ {
+ 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 suggestions.SingleCoordinates.OutputLiquids)
+ {
+ 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 '" + outputLiquid.LiquidType + "'.");
+ }
+
+ liquidVolume.Volume = outputLiquid.Volume;
+ }
+ }
+ }
+
+ return Print(job, processParameters);
+ }
+
+ /// <summary>
/// Prints the specified job using the specified job parameters.
/// </summary>
/// <param name="job">The job.</param>
@@ -478,10 +548,24 @@ namespace Tango.Integration.Operation
/// <returns></returns>
public JobHandler Print(Job job, ProcessParametersTable processParameters)
{
+ var originalJob = job;
+
CurrentProcessParameters = processParameters;
JobRequest request = new JobRequest();
+ job = job.Clone();
+
+ var segments = job.Segments.ToList();
+
+ for (int i = 0; i < job.NumberOfUnits - 1; i++)
+ {
+ foreach (var s in segments)
+ {
+ job.Segments.Add(s);
+ }
+ }
+
JobTicket ticket = new JobTicket();
ticket.EnableInterSegment = job.EnableInterSegment;
ticket.InterSegmentLength = job.InterSegmentLength;
@@ -553,7 +637,7 @@ namespace Tango.Integration.Operation
{
LogManager.Log(ex, "Failed to cancel job.");
}
- }, job, processParameters);
+ }, originalJob, processParameters);
LogRequestSent(request);
bool responseLogged = false;
diff --git a/Software/Visual_Studio/Tango.Integration/Operation/RunningJobStatus.cs b/Software/Visual_Studio/Tango.Integration/Operation/RunningJobStatus.cs
index 335930277..17e5f3a40 100644
--- a/Software/Visual_Studio/Tango.Integration/Operation/RunningJobStatus.cs
+++ b/Software/Visual_Studio/Tango.Integration/Operation/RunningJobStatus.cs
@@ -37,6 +37,21 @@ namespace Tango.Integration.Operation
public double RemainingProgress { get; set; }
/// <summary>
+ /// Gets or sets the remaining units if it is an embroidery job.
+ /// </summary>
+ public int RemainingUnits { get; set; }
+
+ /// <summary>
+ /// Gets or sets the current unit progress.
+ /// </summary>
+ public double CurrentUnitProgress { get; set; }
+
+ /// <summary>
+ /// Gets or sets the current unit total progress.
+ /// </summary>
+ public double CurrentUnitTotalProgress { get; set; }
+
+ /// <summary>
/// Gets or sets a value indicating whether this instance is canceled.
/// </summary>
public bool IsCanceled { get; set; }
diff --git a/Software/Visual_Studio/Tango.Settings/SettingsManager.cs b/Software/Visual_Studio/Tango.Settings/SettingsManager.cs
index cd8b97c92..88a3f59e1 100644
--- a/Software/Visual_Studio/Tango.Settings/SettingsManager.cs
+++ b/Software/Visual_Studio/Tango.Settings/SettingsManager.cs
@@ -6,6 +6,7 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Tango.Logging;
namespace Tango.Settings
{
@@ -37,6 +38,7 @@ namespace Tango.Settings
private List<SettingsBase> _settingsCollection;
private JsonSerializerSettings _jsonSettings;
+ private LogManager _logManager;
private bool _loaded;
/// <summary>
@@ -54,6 +56,7 @@ namespace Tango.Settings
/// </summary>
private SettingsManager()
{
+ _logManager = LogManager.Default;
FilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Twine", "Tango", "Settings", Path.GetFileNameWithoutExtension(AppDomain.CurrentDomain.FriendlyName) + ".json");
Folder = Path.GetDirectoryName(FilePath);
Directory.CreateDirectory(Folder);
@@ -88,12 +91,21 @@ namespace Tango.Settings
/// <returns></returns>
public T GetOrCreate<T>() where T : SettingsBase
{
- EnsureLoaded();
+ try
+ {
+ _logManager.Log("Retrieving settings for " + typeof(T).Name);
+ EnsureLoaded();
+ }
+ catch (Exception ex)
+ {
+ _logManager.Log(ex, "Error deserializing settings for " + typeof(T).Name);
+ }
var settings = _settingsCollection.SingleOrDefault(x => x.GetType() == typeof(T)) as T;
if (settings == null)
{
+ _logManager.Log("Settings for " + typeof(T).Name + " were not found. Initializing default settings.");
settings = Activator.CreateInstance<T>();
settings.SaveAction = Save;
_settingsCollection.Add(settings);
@@ -109,6 +121,8 @@ namespace Tango.Settings
{
if (File.Exists(FilePath))
{
+ _logManager.Log("Loading settings from " + FilePath + "...");
+
_settingsCollection = JsonConvert.DeserializeObject<List<SettingsBase>>(File.ReadAllText(FilePath), _jsonSettings);
foreach (var settings in _settingsCollection)
@@ -135,6 +149,7 @@ namespace Tango.Settings
{
EnsureLoaded();
+ _logManager.Log("Saving settings to " + FilePath + "...");
String json = JsonConvert.SerializeObject(_settingsCollection, _jsonSettings);
File.WriteAllText(FilePath, json);
}
diff --git a/Software/Visual_Studio/Tango.Touch/Controls/TouchGifAnimation.cs b/Software/Visual_Studio/Tango.Touch/Controls/TouchGifAnimation.cs
new file mode 100644
index 000000000..45e552a43
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Touch/Controls/TouchGifAnimation.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Tango.Touch.Controls
+{
+ public class TouchGifAnimation : Control
+ {
+ public ImageSource Source
+ {
+ get { return (ImageSource)GetValue(SourceProperty); }
+ set { SetValue(SourceProperty, value); }
+ }
+ public static readonly DependencyProperty SourceProperty =
+ DependencyProperty.Register("Source", typeof(ImageSource), typeof(TouchGifAnimation), new PropertyMetadata(null));
+
+ public double SpeedRatio
+ {
+ get { return (double)GetValue(SpeedRatioProperty); }
+ set { SetValue(SpeedRatioProperty, value); }
+ }
+ public static readonly DependencyProperty SpeedRatioProperty =
+ DependencyProperty.Register("SpeedRatio", typeof(double), typeof(TouchGifAnimation), new PropertyMetadata(1.0));
+
+ public Stretch Stretch
+ {
+ get { return (Stretch)GetValue(StretchProperty); }
+ set { SetValue(StretchProperty, value); }
+ }
+ public static readonly DependencyProperty StretchProperty =
+ DependencyProperty.Register("Stretch", typeof(Stretch), typeof(TouchGifAnimation), new PropertyMetadata(Stretch.None));
+
+ public bool EnableAnimation
+ {
+ get { return (bool)GetValue(EnableAnimationProperty); }
+ set { SetValue(EnableAnimationProperty, value); }
+ }
+ public static readonly DependencyProperty EnableAnimationProperty =
+ DependencyProperty.Register("EnableAnimation", typeof(bool), typeof(TouchGifAnimation), new PropertyMetadata(false));
+
+
+ static TouchGifAnimation()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(TouchGifAnimation), new FrameworkPropertyMetadata(typeof(TouchGifAnimation)));
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Touch/Controls/TouchGifAnimation.xaml b/Software/Visual_Studio/Tango.Touch/Controls/TouchGifAnimation.xaml
new file mode 100644
index 000000000..15154125e
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Touch/Controls/TouchGifAnimation.xaml
@@ -0,0 +1,21 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:gif="clr-namespace:Tango.AnimatedGif;assembly=Tango.AnimatedGif"
+ xmlns:local="clr-namespace:Tango.Touch.Controls">
+
+ <Style TargetType="{x:Type local:TouchGifAnimation}">
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type local:TouchGifAnimation}">
+ <Image
+ Stretch="{TemplateBinding Stretch}"
+ gif:ImageBehavior.AnimatedSource="{TemplateBinding Source}"
+ gif:ImageBehavior.EnableAnimation="{TemplateBinding EnableAnimation}"
+ gif:ImageBehavior.SpeedRatio="{TemplateBinding SpeedRatio}"
+ />
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+</ResourceDictionary> \ No newline at end of file
diff --git a/Software/Visual_Studio/Tango.Touch/Controls/TouchNumericTextBox.cs b/Software/Visual_Studio/Tango.Touch/Controls/TouchNumericTextBox.cs
index c45701e99..aee5fae26 100644
--- a/Software/Visual_Studio/Tango.Touch/Controls/TouchNumericTextBox.cs
+++ b/Software/Visual_Studio/Tango.Touch/Controls/TouchNumericTextBox.cs
@@ -70,7 +70,7 @@ namespace Tango.Touch.Controls
set { SetValue(MinimumProperty, value); }
}
public static readonly DependencyProperty MinimumProperty =
- DependencyProperty.Register("Minimum", typeof(double), typeof(TouchNumericTextBox), new PropertyMetadata(.0));
+ DependencyProperty.Register("Minimum", typeof(double), typeof(TouchNumericTextBox), new PropertyMetadata(0.0));
public double Maximum
{
@@ -108,6 +108,8 @@ namespace Tango.Touch.Controls
_text_box.GotFocus += _text_box_GotFocus;
_text_box.TextChanged += _text_box_TextChanged;
+ Value = Value;
+
OnValueChanged();
}
diff --git a/Software/Visual_Studio/Tango.Touch/Controls/TouchToggleButton.cs b/Software/Visual_Studio/Tango.Touch/Controls/TouchToggleButton.cs
index 8187645ca..f24d716db 100644
--- a/Software/Visual_Studio/Tango.Touch/Controls/TouchToggleButton.cs
+++ b/Software/Visual_Studio/Tango.Touch/Controls/TouchToggleButton.cs
@@ -19,6 +19,8 @@ namespace Tango.Touch.Controls
public class TouchToggleButton : ToggleButton, ITouchControl
{
private Object _uncheckedContent;
+ private bool _loaded;
+ private bool first_checked;
#region ITouchControl
@@ -91,8 +93,33 @@ namespace Tango.Touch.Controls
public TouchToggleButton()
{
- Loaded += (_, __) => _uncheckedContent = Content;
- Checked += (_, __) => Content = CheckedContent != null ? CheckedContent : Content;
+ Loaded += (_, __) =>
+ {
+ if (!_loaded)
+ {
+ _uncheckedContent = Content;
+ _loaded = true;
+ }
+ };
+
+ Checked += (_, __) =>
+ {
+ if (_loaded)
+ {
+ Content = CheckedContent != null ? CheckedContent : Content;
+ }
+ else
+ {
+ Loaded += (x, y) =>
+ {
+ if (!first_checked)
+ {
+ Content = CheckedContent != null ? CheckedContent : Content;
+ first_checked = true;
+ }
+ };
+ }
+ };
Unchecked += (_, __) => Content = _uncheckedContent;
}
}
diff --git a/Software/Visual_Studio/Tango.Touch/Tango.Touch.csproj b/Software/Visual_Studio/Tango.Touch/Tango.Touch.csproj
index fada6cad8..e078d0887 100644
--- a/Software/Visual_Studio/Tango.Touch/Tango.Touch.csproj
+++ b/Software/Visual_Studio/Tango.Touch/Tango.Touch.csproj
@@ -68,6 +68,7 @@
<Compile Include="Controls\TouchCheckBox.cs" />
<Compile Include="Controls\TouchComboBox.cs" />
<Compile Include="Controls\TouchExpander.cs" />
+ <Compile Include="Controls\TouchGifAnimation.cs" />
<Compile Include="Controls\TouchIcon.cs" />
<Compile Include="Controls\TouchIconKind.cs" />
<Compile Include="Controls\TouchImageButton.cs" />
@@ -118,6 +119,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
+ <Page Include="Controls\TouchGifAnimation.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
<Page Include="Controls\TouchIcon.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -331,6 +336,10 @@
</None>
</ItemGroup>
<ItemGroup>
+ <ProjectReference Include="..\Tango.AnimatedGif\Tango.AnimatedGif.csproj">
+ <Project>{d129789c-3096-4d0b-8dd7-fe24a4df4b21}</Project>
+ <Name>Tango.AnimatedGif</Name>
+ </ProjectReference>
<ProjectReference Include="..\Tango.Core\Tango.Core.csproj">
<Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project>
<Name>Tango.Core</Name>
diff --git a/Software/Visual_Studio/Tango.Touch/Themes/Generic.xaml b/Software/Visual_Studio/Tango.Touch/Themes/Generic.xaml
index 971f3dd46..e077d1388 100644
--- a/Software/Visual_Studio/Tango.Touch/Themes/Generic.xaml
+++ b/Software/Visual_Studio/Tango.Touch/Themes/Generic.xaml
@@ -38,7 +38,8 @@
<ResourceDictionary Source="pack://application:,,,/Tango.Touch;component/Controls/TouchStaticListBox.xaml" />
<ResourceDictionary Source="pack://application:,,,/Tango.Touch;component/Controls/TouchRingProgress.xaml" />
<ResourceDictionary Source="pack://application:,,,/Tango.Touch;component/Controls/TouchNativeListBox.xaml" />
-
+ <ResourceDictionary Source="pack://application:,,,/Tango.Touch;component/Controls/TouchGifAnimation.xaml" />
+
<ResourceDictionary Source="pack://application:,,,/Tango.Touch;component/Styles/TouchToggleButton.xaml" />
<ResourceDictionary Source="pack://application:,,,/Tango.Touch;component/Styles/TouchButton.xaml" />
diff --git a/Software/Visual_Studio/Tango.sln b/Software/Visual_Studio/Tango.sln
index bfb278f0f..794b8be2d 100644
--- a/Software/Visual_Studio/Tango.sln
+++ b/Software/Visual_Studio/Tango.sln
@@ -210,6 +210,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.Hive", "Tango.Hive\Ta
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.CatalogGenerator", "Utilities\Tango.CatalogGenerator\Tango.CatalogGenerator.csproj", "{808E47B6-BAA7-4D23-83CB-40C53DC4B38A}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.AnimatedGif", "Tango.AnimatedGif\Tango.AnimatedGif.csproj", "{D129789C-3096-4D0B-8DD7-FE24A4DF4B21}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
AppVeyor|Any CPU = AppVeyor|Any CPU
@@ -3569,6 +3571,46 @@ Global
{808E47B6-BAA7-4D23-83CB-40C53DC4B38A}.Release|x64.Build.0 = Release|Any CPU
{808E47B6-BAA7-4D23-83CB-40C53DC4B38A}.Release|x86.ActiveCfg = Release|Any CPU
{808E47B6-BAA7-4D23-83CB-40C53DC4B38A}.Release|x86.Build.0 = Release|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.AppVeyor|Any CPU.ActiveCfg = Release|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.AppVeyor|Any CPU.Build.0 = Release|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.AppVeyor|ARM.ActiveCfg = Release|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.AppVeyor|ARM.Build.0 = Release|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.AppVeyor|ARM64.ActiveCfg = Release|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.AppVeyor|ARM64.Build.0 = Release|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.AppVeyor|x64.ActiveCfg = Release|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.AppVeyor|x64.Build.0 = Release|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.AppVeyor|x86.ActiveCfg = Release|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.AppVeyor|x86.Build.0 = Release|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.Debug|ARM.Build.0 = Debug|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.Debug|ARM64.ActiveCfg = Debug|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.Debug|ARM64.Build.0 = Debug|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.Debug|x64.Build.0 = Debug|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.Debug|x86.Build.0 = Debug|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.DefaultBuild|Any CPU.ActiveCfg = Debug|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.DefaultBuild|Any CPU.Build.0 = Debug|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.DefaultBuild|ARM.ActiveCfg = Debug|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.DefaultBuild|ARM.Build.0 = Debug|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.DefaultBuild|ARM64.ActiveCfg = Debug|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.DefaultBuild|ARM64.Build.0 = Debug|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.DefaultBuild|x64.ActiveCfg = Debug|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.DefaultBuild|x64.Build.0 = Debug|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.DefaultBuild|x86.ActiveCfg = Debug|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.DefaultBuild|x86.Build.0 = Debug|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.Release|ARM.ActiveCfg = Release|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.Release|ARM.Build.0 = Release|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.Release|ARM64.ActiveCfg = Release|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.Release|ARM64.Build.0 = Release|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.Release|x64.ActiveCfg = Release|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.Release|x64.Build.0 = Release|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.Release|x86.ActiveCfg = Release|Any CPU
+ {D129789C-3096-4D0B-8DD7-FE24A4DF4B21}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Software/Visual_Studio/Utilities/Tango.UITests/App.xaml b/Software/Visual_Studio/Utilities/Tango.UITests/App.xaml
index 0ede32b42..43576481f 100644
--- a/Software/Visual_Studio/Utilities/Tango.UITests/App.xaml
+++ b/Software/Visual_Studio/Utilities/Tango.UITests/App.xaml
@@ -6,20 +6,20 @@
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
- <ResourceDictionary.MergedDictionaries>
- <!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
+ <!--<ResourceDictionary.MergedDictionaries>
+ --><!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! --><!--
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
- <!-- Accent and AppTheme setting -->
+ --><!-- Accent and AppTheme setting --><!--
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/FlatButton.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/VS/Colors.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/VS/Styles.xaml" />
- </ResourceDictionary.MergedDictionaries>
+ </ResourceDictionary.MergedDictionaries>-->
</ResourceDictionary>
</Application.Resources>
</Application>
diff --git a/Software/Visual_Studio/Utilities/Tango.UITests/MainWindow.xaml b/Software/Visual_Studio/Utilities/Tango.UITests/MainWindow.xaml
index 05bcad25c..6f821d30f 100644
--- a/Software/Visual_Studio/Utilities/Tango.UITests/MainWindow.xaml
+++ b/Software/Visual_Studio/Utilities/Tango.UITests/MainWindow.xaml
@@ -16,6 +16,6 @@
Title="MainWindow" Height="500" Width="800" Foreground="Red" DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
- <stubs:StubsView/>
+ <touch:TouchNumericTextBox Value="{Binding Value}" Minimum="1" Maximum="100" Margin="0 100 0 0" VerticalAlignment="Top" Width="100" />
</Grid>
</Window>
diff --git a/Software/Visual_Studio/Utilities/Tango.UITests/MainWindow.xaml.cs b/Software/Visual_Studio/Utilities/Tango.UITests/MainWindow.xaml.cs
index 06613ee1e..c3eca4c76 100644
--- a/Software/Visual_Studio/Utilities/Tango.UITests/MainWindow.xaml.cs
+++ b/Software/Visual_Studio/Utilities/Tango.UITests/MainWindow.xaml.cs
@@ -110,6 +110,14 @@ namespace Tango.UITests
public RelayCommand<DropEventArgs> DropCommand { get; set; }
+ public int Value
+ {
+ get { return (int)GetValue(ValueProperty); }
+ set { SetValue(ValueProperty, value); }
+ }
+ public static readonly DependencyProperty ValueProperty =
+ DependencyProperty.Register("Value", typeof(int), typeof(MainWindow), new PropertyMetadata(0));
+
public MainWindow()
{
Persons = new ObservableCollection<Person>();
@@ -127,9 +135,11 @@ namespace Tango.UITests
DropCommand = new RelayCommand<DropEventArgs>(OnDrop);
+ Value = 10;
+
InitializeComponent();
- DataContext = new VM();
+ //DataContext = new VM();
}
private void OnDrop(DropEventArgs e)