2016-06-01 18:17:11 -07:00
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
using MatterHackers.Agg ;
using MatterHackers.Agg.PlatformAbstract ;
using MatterHackers.Agg.UI ;
using MatterHackers.Localizations ;
using MatterHackers.MatterControl.ConfigurationPage.PrintLeveling ;
using MatterHackers.MatterControl.DataStorage ;
using MatterHackers.MatterControl.CustomWidgets ;
using MatterHackers.MatterControl.PrinterCommunication ;
using MatterHackers.SerialPortCommunication.FrostedSerial ;
#if __ANDROID__
using Com.Hoho.Android.Usbserial.Driver ;
using Android.Hardware.Usb ;
using Android.Content ;
#endif
namespace MatterHackers.MatterControl
{
2016-06-08 09:31:26 -07:00
public class SetupWizardTroubleshooting : WizardPage
2016-06-01 18:17:11 -07:00
{
private Button nextButton ;
private event EventHandler unregisterEvents ;
private CriteriaRow connectToPrinterRow ;
2016-06-07 17:23:41 -07:00
// Used in Android
private System . Threading . Timer checkForPermissionTimer ;
2016-06-01 18:17:11 -07:00
#if __ANDROID__
private static UsbManager usbManager
{
get { return ( UsbManager ) Android . App . Application . Context . ApplicationContext . GetSystemService ( Context . UsbService ) ; }
}
#endif
2016-06-07 15:45:50 -07:00
public SetupWizardTroubleshooting ( )
2016-06-01 18:17:11 -07:00
{
RefreshStatus ( ) ;
//Construct buttons
2016-06-07 15:45:50 -07:00
cancelButton = whiteImageButtonFactory . Generate ( "Cancel" . Localize ( ) , centerText : true ) ;
2016-06-08 09:31:26 -07:00
cancelButton . Click + = ( s , e ) = > this . WizardWindow . ChangeToPage < AndroidConnectDevicePage > ( ) ;
2016-06-01 18:17:11 -07:00
//Construct buttons
2016-06-07 15:45:50 -07:00
nextButton = textImageButtonFactory . Generate ( "Continue" . Localize ( ) ) ;
nextButton . Click + = ( sender , e ) = > UiThread . RunOnIdle ( this . WizardWindow . Close ) ;
2016-06-01 18:17:11 -07:00
nextButton . Visible = false ;
//Add buttons to buttonContainer
footerRow . AddChild ( nextButton ) ;
footerRow . AddChild ( new GuiWidget ( ) { HAnchor = HAnchor . ParentLeftRight } ) ;
footerRow . AddChild ( cancelButton ) ;
// Register for connection notifications
PrinterConnectionAndCommunication . Instance . CommunicationStateChanged . RegisterEvent ( ConnectionStatusChanged , ref unregisterEvents ) ;
}
public void ConnectionStatusChanged ( object test , EventArgs args )
{
if ( PrinterConnectionAndCommunication . Instance . CommunicationState = = PrinterConnectionAndCommunication . CommunicationStates . Connected & & connectToPrinterRow ! = null )
{
connectToPrinterRow . SetSuccessful ( ) ;
nextButton . Visible = true ;
}
}
public override void OnClosed ( EventArgs e )
{
if ( checkForPermissionTimer ! = null )
{
checkForPermissionTimer . Dispose ( ) ;
}
2016-06-07 17:23:41 -07:00
unregisterEvents ? . Invoke ( this , null ) ;
2016-06-01 18:17:11 -07:00
base . OnClosed ( e ) ;
}
private void RefreshStatus ( )
{
CriteriaRow . ResetAll ( ) ;
// Clear the main container
contentRow . CloseAllChildren ( ) ;
// Regen and refresh the troubleshooting criteria
TextWidget printerNameLabel = new TextWidget ( string . Format ( "{0}:" , "Connection Troubleshooting" . Localize ( ) ) , 0 , 0 , labelFontSize ) ;
2016-06-02 17:46:49 -07:00
printerNameLabel . TextColor = ActiveTheme . Instance . PrimaryTextColor ;
2016-06-01 18:17:11 -07:00
printerNameLabel . Margin = new BorderDouble ( bottom : 10 ) ;
#if __ANDROID__
IUsbSerialPort serialPort = FrostedSerialPort . LoadSerialDriver ( ) ;
#if ANDROID7
// Filter out the built-in 002 device and select the first item from the list
// On the T7 Android device, there is a non-printer device always registered at usb/002/002 that must be ignored
UsbDevice usbPrintDevice = usbManager . DeviceList . Values . Where ( d = > d . DeviceName ! = "/dev/bus/usb/002/002" ) . FirstOrDefault ( ) ;
#else
UsbDevice usbPrintDevice = usbManager . DeviceList . Values . FirstOrDefault ( ) ;
#endif
UsbStatus usbStatus = new UsbStatus ( ) {
IsDriverLoadable = ( serialPort ! = null ) ,
HasUsbDevice = true ,
HasUsbPermission = false ,
AnyUsbDeviceExists = usbPrintDevice ! = null
} ;
if ( ! usbStatus . IsDriverLoadable )
{
usbStatus . HasUsbDevice = usbPrintDevice ! = null ;
if ( usbStatus . HasUsbDevice ) {
// TODO: Testing specifically for UsbClass.Comm seems fragile but no better alternative exists without more research
usbStatus . UsbDetails = new UsbDeviceDetails ( ) {
ProductID = usbPrintDevice . ProductId ,
VendorID = usbPrintDevice . VendorId ,
DriverClass = usbManager . DeviceList . Values . First ( ) . DeviceClass = = Android . Hardware . Usb . UsbClass . Comm ? "cdcDriverType" : "ftdiDriverType"
} ;
usbStatus . Summary = string . Format ( "No USB device definition found. Click the 'Fix' button to add an override for your device " , usbStatus . UsbDetails . VendorID , usbStatus . UsbDetails . ProductID ) ;
}
}
usbStatus . HasUsbPermission = usbStatus . IsDriverLoadable & & FrostedSerialPort . HasPermissionToDevice ( serialPort ) ;
contentRow . AddChild ( printerNameLabel ) ;
contentRow . AddChild ( new CriteriaRow (
"USB Connection" ,
"Retry" ,
"No USB device found. Check and reseat cables and try again" ,
usbStatus . AnyUsbDeviceExists ,
( ) = > UiThread . RunOnIdle ( RefreshStatus ) ) ) ;
contentRow . AddChild ( new CriteriaRow (
"USB Driver" ,
"Fix" ,
usbStatus . Summary ,
usbStatus . IsDriverLoadable ,
( ) = > {
string overridePath = Path . Combine ( ApplicationDataStorage . ApplicationUserDataPath , "data" , "usboverride.local" ) ;
UsbDeviceDetails usbDetails = usbStatus . UsbDetails ;
File . AppendAllText ( overridePath , string . Format ( "{0},{1},{2}\r\n" , usbDetails . VendorID , usbDetails . ProductID , usbDetails . DriverClass ) ) ;
UiThread . RunOnIdle ( ( ) = > RefreshStatus ( ) ) ;
} ) ) ;
contentRow . AddChild ( new CriteriaRow (
"USB Permission" ,
"Request Permission" ,
"Click the 'Request Permission' button to gain Android access rights" ,
usbStatus . HasUsbPermission ,
( ) = > {
if ( checkForPermissionTimer = = null )
{
checkForPermissionTimer = new System . Threading . Timer ( ( state ) = > {
if ( FrostedSerialPort . HasPermissionToDevice ( serialPort ) )
{
UiThread . RunOnIdle ( this . RefreshStatus ) ;
checkForPermissionTimer . Dispose ( ) ;
}
} , null , 200 , 200 ) ;
}
FrostedSerialPort . RequestPermissionToDevice ( serialPort ) ;
} ) ) ;
#endif
connectToPrinterRow = new CriteriaRow (
"Connect to Printer" ,
"Connect" ,
"Click the 'Connect' button to retry the original connection attempt" ,
false ,
( ) = > PrinterConnectionAndCommunication . Instance . ConnectToActivePrinter ( ) ) ;
contentRow . AddChild ( connectToPrinterRow ) ;
if ( CriteriaRow . ActiveErrorItem ! = null ) {
FlowLayoutWidget errorText = new FlowLayoutWidget ( ) {
Padding = new BorderDouble ( 0 , 15 )
} ;
errorText . AddChild ( new TextWidget ( CriteriaRow . ActiveErrorItem . ErrorText ) {
TextColor = ActiveTheme . Instance . PrimaryAccentColor
} ) ;
contentRow . AddChild ( errorText ) ;
}
}
private class CriteriaRow : FlowLayoutWidget
{
public static CriteriaRow ActiveErrorItem { get ; private set ; }
public string ErrorText { get ; private set ; }
private static bool stillSuccessful = true ;
private static int criteriaCount = 0 ;
private static RGBA_Bytes disabledTextColor = new RGBA_Bytes ( 0.35 , 0.35 , 0.35 ) ;
private static RGBA_Bytes disabledBackColor = new RGBA_Bytes ( 0.22 , 0.22 , 0.22 ) ;
private static RGBA_Bytes toggleColor = new RGBA_Bytes ( RGBA_Bytes . Gray . red + 2 , RGBA_Bytes . Gray . green + 2 , RGBA_Bytes . Gray . blue + 2 ) ;
public CriteriaRow ( string itemText , string fixitText , string errorText , bool succeeded , Action fixAction ) : base ( FlowDirection . LeftToRight , HAnchor . ParentLeftRight , VAnchor . AbsolutePosition )
{
TextImageButtonFactory buttonFactory = new TextImageButtonFactory ( ) ;
ErrorText = errorText ;
base . Height = 40 ;
base . AddChild ( new TextWidget ( string . Format ( " {0}. {1}" , criteriaCount + 1 , itemText ) ) {
TextColor = stillSuccessful ? RGBA_Bytes . White : disabledTextColor ,
VAnchor = VAnchor . ParentCenter
} ) ;
if ( stillSuccessful & & ! succeeded )
{
ActiveErrorItem = this ;
}
base . AddChild ( new HorizontalSpacer ( ) ) ;
if ( stillSuccessful ) {
if ( succeeded )
{
// Add checkmark image
AddSuccessIcon ( ) ;
} else {
// Add Fix button
Button button = buttonFactory . Generate ( LocalizedString . Get ( fixitText ) , centerText : true ) ;
button . VAnchor = VAnchor . ParentCenter ;
button . Padding = new BorderDouble ( 3 , 8 ) ;
button . Click + = ( sender , e ) = > fixAction ( ) ;
base . AddChild ( button ) ;
}
}
if ( stillSuccessful )
{
this . BackgroundColor = ( criteriaCount % 2 = = 0 ) ? RGBA_Bytes . Gray : toggleColor ;
}
else
{
this . BackgroundColor = disabledBackColor ;
}
stillSuccessful & = succeeded ;
criteriaCount + + ;
}
public void SetSuccessful ( )
{
this . RemoveChild ( this . Children . Last ( ) ) ;
ActiveErrorItem = null ;
AddSuccessIcon ( ) ;
}
public static void ResetAll ( )
{
criteriaCount = 0 ;
stillSuccessful = true ;
ActiveErrorItem = null ;
}
private void AddSuccessIcon ( )
{
base . AddChild ( new ImageWidget ( StaticData . Instance . LoadImage ( Path . Combine ( "Icons" , "426.png" ) ) ) {
VAnchor = VAnchor . ParentCenter
} ) ;
}
}
private class UsbStatus
{
public bool HasUsbDevice { get ; set ; }
public bool IsDriverLoadable { get ; set ; }
public string Summary { get ; set ; }
public bool HasUsbPermission { get ; set ; }
public bool AnyUsbDeviceExists { get ; set ; }
public UsbDeviceDetails UsbDetails { get ; set ; }
}
private class UsbDeviceDetails
{
public int VendorID { get ; set ; }
public int ProductID { get ; set ; }
public string DriverClass { get ; set ; }
}
}
}