2019-04-04 17:18:12 -07:00
/ *
Copyright ( c ) 2019 , Lars Brubaker , John Lewin
All rights reserved .
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions are met :
1. Redistributions of source code must retain the above copyright notice , this
list of conditions and the following disclaimer .
2. Redistributions in binary form must reproduce the above copyright notice ,
this list of conditions and the following disclaimer in the documentation
and / or other materials provided with the distribution .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies ,
either expressed or implied , of the FreeBSD Project .
* /
2020-10-27 17:19:51 -07:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
2019-04-25 08:03:46 -07:00
using MatterHackers.Agg ;
2019-05-15 17:42:42 -07:00
using MatterHackers.Agg.Platform ;
2019-04-04 17:18:12 -07:00
using MatterHackers.Agg.UI ;
2021-05-21 15:23:25 -07:00
using MatterHackers.ImageProcessing ;
2019-04-04 17:18:12 -07:00
using MatterHackers.Localizations ;
using MatterHackers.MatterControl.ConfigurationPage.PrintLeveling ;
2019-04-25 08:03:46 -07:00
using MatterHackers.MatterControl.CustomWidgets ;
2019-04-25 12:32:27 -07:00
using MatterHackers.MatterControl.PartPreviewWindow ;
2019-04-04 17:18:12 -07:00
using MatterHackers.MatterControl.PrinterControls ;
2019-04-25 08:03:46 -07:00
using MatterHackers.MatterControl.SlicerConfiguration ;
2019-04-04 17:18:12 -07:00
using MatterHackers.VectorMath ;
namespace MatterHackers.MatterControl
{
public class PrinterCalibrationWizard : IStagedSetupWizard
{
2020-08-13 11:15:30 -07:00
private PrinterConfig printer ;
2019-05-15 17:42:42 -07:00
private RoundedToggleSwitch printLevelingSwitch ;
2019-04-04 17:18:12 -07:00
public PrinterCalibrationWizard ( PrinterConfig printer , ThemeConfig theme )
{
2019-05-09 15:20:28 -07:00
var stages = new List < ISetupWizard > ( )
2019-04-04 17:18:12 -07:00
{
2019-05-15 13:31:07 -07:00
new ZCalibrationWizard ( printer ) ,
2019-04-22 11:36:38 -07:00
new PrintLevelingWizard ( printer ) ,
2019-05-15 16:00:07 -07:00
new LoadFilamentWizard ( printer , extruderIndex : 0 , showAlreadyLoadedButton : true ) ,
new LoadFilamentWizard ( printer , extruderIndex : 1 , showAlreadyLoadedButton : true ) ,
new XyCalibrationWizard ( printer , 1 )
2019-04-04 17:18:12 -07:00
} ;
2019-05-09 15:20:28 -07:00
this . Stages = stages ;
2019-05-15 17:42:42 -07:00
this . printer = printer ;
2019-05-09 15:20:28 -07:00
2019-04-04 17:18:12 -07:00
this . HomePageGenerator = ( ) = >
{
var homePage = new WizardSummaryPage ( )
{
HeaderText = "Printer Setup & Calibration" . Localize ( )
} ;
2019-04-25 08:03:46 -07:00
var contentRow = homePage . ContentRow ;
2019-06-01 09:30:55 -07:00
if ( ! ReturnedToHomePage )
{
2020-11-12 21:56:20 -08:00
if ( printer . Connection . IsConnected )
{
contentRow . AddChild (
new WrappedTextWidget (
@"Select the calibration task to continue" . Replace ( "\r\n" , "\n" ) ,
pointSize : theme . DefaultFontSize ,
textColor : theme . TextColor ) ) ;
}
else
{
contentRow . AddChild (
new WrappedTextWidget (
@"Connect the printer to complete the calibration tasks." . Replace ( "\r\n" , "\n" ) ,
pointSize : theme . DefaultFontSize ,
textColor : theme . TextColor ) ) ;
}
2019-06-01 09:30:55 -07:00
}
2019-04-25 08:03:46 -07:00
contentRow . BackgroundColor = Color . Transparent ;
2020-11-13 09:12:14 -08:00
foreach ( var stage in this . Stages . Where ( s = > s . Visible ) )
2019-04-25 08:03:46 -07:00
{
2019-05-15 17:42:42 -07:00
GuiWidget rightWidget = null ;
2019-04-25 08:03:46 -07:00
var widget = new GuiWidget ( ) ;
2019-05-15 13:31:07 -07:00
if ( stage is ZCalibrationWizard probeWizard )
2019-04-25 08:03:46 -07:00
{
var column = CreateColumn ( theme ) ;
column . FlowDirection = FlowDirection . LeftToRight ;
var offset = printer . Settings . GetValue < Vector3 > ( SettingsKey . probe_offset ) ;
2019-04-25 12:32:27 -07:00
column . AddChild (
new ValueTag (
"Z Offset" . Localize ( ) ,
offset . Z . ToString ( "0.###" ) ,
new BorderDouble ( 12 , 5 , 2 , 5 ) ,
5 ,
2019-04-26 12:10:54 -07:00
11 )
{
Margin = new BorderDouble ( bottom : 4 ) ,
MinimumSize = new Vector2 ( 125 , 0 )
} ) ;
2019-04-25 08:03:46 -07:00
2020-11-12 07:52:34 -08:00
column . AddChild ( new HorizontalSpacer ( ) ) ;
2020-08-13 11:15:30 -07:00
AddRunStageButton ( "Run Z Calibration" . Localize ( ) , theme , stage , column ) ;
2020-08-12 18:08:35 -07:00
2019-04-25 08:03:46 -07:00
widget = column ;
}
2020-11-12 07:52:34 -08:00
if ( stage is LoadFilamentWizard loadWizard )
{
var column = CreateColumn ( theme ) ;
column . FlowDirection = FlowDirection . LeftToRight ;
var lastRow = new FlowLayoutWidget ( )
{
HAnchor = HAnchor . Stretch
} ;
column . AddChild ( lastRow ) ;
lastRow . AddChild ( new HorizontalSpacer ( ) ) ;
AddRunStageButton ( "Load Filament" . Localize ( ) , theme , stage , lastRow ) . Margin = new BorderDouble ( 10 ) ;
widget = column ;
}
2019-04-25 08:03:46 -07:00
if ( stage is PrintLevelingWizard levelingWizard )
{
PrintLevelingData levelingData = printer . Settings . Helpers . PrintLevelingData ;
2020-05-16 11:47:42 -07:00
var column = CreateColumn ( theme ) ;
2020-08-12 18:08:35 -07:00
2020-11-12 07:52:34 -08:00
var lastRow = new FlowLayoutWidget ( )
{
HAnchor = HAnchor . Stretch
} ;
2019-04-25 08:03:46 -07:00
if ( levelingData ! = null
& & printer . Settings ? . GetValue < bool > ( SettingsKey . print_leveling_enabled ) = = true )
{
var positions = levelingData . SampledPositions ;
var levelingSolution = printer . Settings . GetValue ( SettingsKey . print_leveling_solution ) ;
2019-05-13 12:06:16 -07:00
column . AddChild (
new ValueTag (
"Leveling Solution" . Localize ( ) ,
levelingSolution ,
new BorderDouble ( 12 , 5 , 2 , 5 ) ,
5 ,
11 )
{
Margin = new BorderDouble ( bottom : 4 ) ,
MinimumSize = new Vector2 ( 125 , 0 )
} ) ;
2019-04-25 08:03:46 -07:00
2021-05-21 15:23:25 -07:00
var editButton = new IconButton ( StaticData . Instance . LoadIcon ( "icon_edit.png" , 16 , 16 ) . SetToColor ( theme . TextColor ) , theme )
2019-05-15 17:42:42 -07:00
{
Name = "Edit Leveling Data Button" ,
ToolTipText = "Edit Leveling Data" . Localize ( ) ,
} ;
editButton . Click + = ( s , e ) = >
{
DialogWindow . Show ( new EditLevelingSettingsPage ( printer , theme ) ) ;
} ;
var row = new FlowLayoutWidget ( )
{
VAnchor = VAnchor . Fit ,
HAnchor = HAnchor . Fit
} ;
row . AddChild ( editButton ) ;
// only show the switch if leveling can be turned off (it can't if it is required).
if ( ! printer . Settings . GetValue < bool > ( SettingsKey . print_leveling_required_to_print ) )
{
// put in the switch
printLevelingSwitch = new RoundedToggleSwitch ( theme )
{
VAnchor = VAnchor . Center ,
Margin = new BorderDouble ( theme . DefaultContainerPadding , 0 ) ,
Checked = printer . Settings . GetValue < bool > ( SettingsKey . print_leveling_enabled ) ,
ToolTipText = "Enable Software Leveling" . Localize ( )
} ;
printLevelingSwitch . CheckedStateChanged + = ( sender , e ) = >
{
printer . Settings . Helpers . DoPrintLeveling ( printLevelingSwitch . Checked ) ;
} ;
printLevelingSwitch . Closed + = ( s , e ) = >
{
// Unregister listeners
printer . Settings . PrintLevelingEnabledChanged - = Settings_PrintLevelingEnabledChanged ;
} ;
// TODO: Why is this listener conditional? If the leveling changes somehow, shouldn't we be updated the UI to reflect that?
// Register listeners
printer . Settings . PrintLevelingEnabledChanged + = Settings_PrintLevelingEnabledChanged ;
row . AddChild ( printLevelingSwitch ) ;
}
rightWidget = row ;
2020-11-12 07:52:34 -08:00
column . AddChild ( lastRow ) ;
2020-08-12 18:08:35 -07:00
2019-04-25 19:54:19 -07:00
var probeWidget = new ProbePositionsWidget ( printer , positions . Select ( v = > new Vector2 ( v ) ) . ToList ( ) , theme )
2019-04-25 08:03:46 -07:00
{
HAnchor = HAnchor . Absolute ,
VAnchor = VAnchor . Absolute ,
Height = 200 ,
Width = 200 ,
RenderLevelingData = true ,
RenderProbePath = false ,
SimplePoints = true ,
} ;
2020-11-12 07:52:34 -08:00
lastRow . AddChild ( probeWidget ) ;
2019-04-25 08:03:46 -07:00
}
2020-11-12 07:52:34 -08:00
else
2020-05-16 11:47:42 -07:00
{
2020-11-12 07:52:34 -08:00
column . AddChild ( lastRow ) ;
if ( ! printer . Settings . GetValue < bool > ( SettingsKey . print_leveling_required_to_print ) )
{
lastRow . AddChild ( new WrappedTextWidget (
@"Print Leveling is an optional feature for this printer that can help improve print quality. If the bed is uneven or cannot be mechanically leveled." . Localize ( ) ,
pointSize : theme . DefaultFontSize ,
textColor : theme . TextColor ) ) ;
}
else if ( printer . Settings . GetValue < bool > ( SettingsKey . validate_leveling ) )
{
lastRow . AddChild ( new WrappedTextWidget (
@"Print Leveling will run automatically at the start of each print." . Localize ( ) ,
pointSize : theme . DefaultFontSize ,
textColor : theme . TextColor ) ) ;
}
else
{
lastRow . AddChild ( new HorizontalSpacer ( ) ) ;
}
2020-05-16 11:47:42 -07:00
}
2020-11-12 21:56:20 -08:00
lastRow . AddChild ( new HorizontalSpacer ( ) ) ;
2020-11-12 07:52:34 -08:00
AddRunStageButton ( "Run Print Leveling" . Localize ( ) , theme , stage , lastRow ) ;
2020-05-16 11:47:42 -07:00
widget = column ;
2019-04-25 08:03:46 -07:00
}
2019-04-26 12:10:54 -07:00
if ( stage is XyCalibrationWizard xyWizard )
{
2020-08-12 18:08:35 -07:00
var row = CreateColumn ( theme ) ;
row . FlowDirection = FlowDirection . LeftToRight ;
2019-04-26 12:10:54 -07:00
var hotendOffset = printer . Settings . Helpers . ExtruderOffset ( 1 ) ;
var tool2Column = new FlowLayoutWidget ( FlowDirection . TopToBottom ) ;
2020-08-12 18:08:35 -07:00
row . AddChild ( tool2Column ) ;
2019-04-26 12:10:54 -07:00
tool2Column . AddChild (
new TextWidget ( "Tool" . Localize ( ) + " 2" , pointSize : theme . DefaultFontSize , textColor : theme . TextColor )
{
Margin = new BorderDouble ( bottom : 4 )
} ) ;
tool2Column . AddChild (
new ValueTag (
"X Offset" . Localize ( ) ,
hotendOffset . X . ToString ( "0.###" ) ,
new BorderDouble ( 12 , 5 , 2 , 5 ) ,
5 ,
11 )
{
Margin = new BorderDouble ( bottom : 4 ) ,
MinimumSize = new Vector2 ( 125 , 0 )
} ) ;
tool2Column . AddChild (
new ValueTag (
"Y Offset" . Localize ( ) ,
hotendOffset . Y . ToString ( "0.###" ) ,
new BorderDouble ( 12 , 5 , 2 , 5 ) ,
5 ,
11 )
{
MinimumSize = new Vector2 ( 125 , 0 )
} ) ;
2020-11-12 07:52:34 -08:00
row . AddChild ( new HorizontalSpacer ( ) ) ;
2020-08-13 11:15:30 -07:00
AddRunStageButton ( "Run Nozzle Alignment" . Localize ( ) , theme , stage , row ) ;
2020-08-12 18:08:35 -07:00
widget = row ;
2019-04-26 12:10:54 -07:00
}
2020-11-12 07:52:34 -08:00
if ( stage is LoadFilamentWizard filamentWizard )
2019-04-25 08:03:46 -07:00
{
2020-11-12 07:52:34 -08:00
widget . Margin = new BorderDouble ( left : theme . DefaultContainerPadding ) ;
}
2019-04-25 08:03:46 -07:00
2020-11-12 07:52:34 -08:00
var sectionName = stage . Title ;
if ( stage . SetupRequired )
{
sectionName + = " - " + "Required" . Localize ( ) ;
2019-04-25 08:03:46 -07:00
}
2020-11-12 07:52:34 -08:00
else if ( stage . Completed )
2019-05-15 16:00:07 -07:00
{
2020-11-12 07:52:34 -08:00
sectionName + = " - " + "Completed" . Localize ( ) ;
}
else
{
sectionName + = " - " + "Optional" . Localize ( ) ;
2019-05-15 16:00:07 -07:00
}
2019-04-25 08:03:46 -07:00
2020-11-12 07:52:34 -08:00
var section = new SectionWidget ( sectionName , widget , theme , rightAlignedContent : rightWidget , expandingContent : false ) ;
2019-04-25 08:03:46 -07:00
theme . ApplyBoxStyle ( section ) ;
section . Margin = section . Margin . Clone ( left : 0 ) ;
2019-04-26 13:03:35 -07:00
section . ShowExpansionIcon = false ;
2019-04-25 08:03:46 -07:00
if ( stage . SetupRequired )
{
section . BackgroundColor = Color . Red . WithAlpha ( 30 ) ;
}
contentRow . AddChild ( section ) ;
}
2019-04-04 17:18:12 -07:00
return homePage ;
} ;
}
2020-11-12 07:52:34 -08:00
private GuiWidget AddRunStageButton ( string title , ThemeConfig theme , ISetupWizard stage , FlowLayoutWidget leftToRight )
2019-05-15 17:42:42 -07:00
{
2020-08-13 11:15:30 -07:00
var runStage = leftToRight . AddChild ( new TextButton ( title , theme )
2019-05-15 17:42:42 -07:00
{
2020-11-12 21:56:20 -08:00
VAnchor = VAnchor . Bottom ,
2020-11-13 17:24:15 -08:00
Enabled = printer . Connection . IsConnected & & ! printer . Connection . Printing & & ! printer . Connection . Paused ,
2020-11-13 16:35:21 -08:00
BackgroundColor = theme . MinimalShade . WithAlpha ( 25 ) ,
2020-08-13 11:15:30 -07:00
} ) ;
2019-05-15 17:42:42 -07:00
2020-08-13 11:15:30 -07:00
runStage . Click + = ( s , e ) = >
2019-04-25 08:03:46 -07:00
{
2020-08-13 11:15:30 -07:00
// Only allow leftnav when not running SetupWizard
if ( StagedSetupWindow ? . ActiveStage = = null )
{
StagedSetupWindow . ActiveStage = stage ;
}
2019-04-25 08:03:46 -07:00
} ;
2020-11-12 07:52:34 -08:00
return runStage ;
2019-04-25 08:03:46 -07:00
}
2019-05-14 17:45:27 -07:00
public bool AutoAdvance { get ; set ; }
2020-08-13 11:15:30 -07:00
public Func < DialogPage > HomePageGenerator { get ; }
2019-04-04 17:18:12 -07:00
2020-08-13 11:15:30 -07:00
public bool ReturnedToHomePage { get ; set ; } = false ;
2019-04-04 17:18:12 -07:00
2020-08-13 11:15:30 -07:00
public StagedSetupWindow StagedSetupWindow { get ; set ; }
2019-04-04 17:18:12 -07:00
2020-08-13 11:15:30 -07:00
public IEnumerable < ISetupWizard > Stages { get ; }
2019-05-15 17:42:42 -07:00
2020-08-13 11:15:30 -07:00
public string Title { get ; } = "Printer Calibration" . Localize ( ) ;
2019-04-04 17:18:12 -07:00
2020-08-13 11:15:30 -07:00
public Vector2 WindowSize { get ; } = new Vector2 ( 1200 , 700 ) ;
2019-06-01 09:30:55 -07:00
2019-05-16 15:34:34 -07:00
public static bool SetupRequired ( PrinterConfig printer , bool requiresLoadedFilament )
2019-04-04 17:18:12 -07:00
{
2019-09-11 17:57:48 -07:00
return printer = = null
2020-12-05 07:32:10 -08:00
| | LevelingPlan . NeedsToBeRun ( printer ) // PrintLevelingWizard
2019-05-15 13:31:07 -07:00
| | ZCalibrationWizard . NeedsToBeRun ( printer )
2019-05-16 15:34:34 -07:00
| | ( requiresLoadedFilament & & LoadFilamentWizard . NeedsToBeRun0 ( printer ) )
| | ( requiresLoadedFilament & & LoadFilamentWizard . NeedsToBeRun1 ( printer ) )
2019-05-06 16:25:27 -07:00
| | XyCalibrationWizard . NeedsToBeRun ( printer ) ;
2019-04-04 17:18:12 -07:00
}
2020-08-13 11:15:30 -07:00
private static FlowLayoutWidget CreateColumn ( ThemeConfig theme )
{
return new FlowLayoutWidget ( FlowDirection . TopToBottom )
{
Margin = new BorderDouble ( theme . DefaultContainerPadding , theme . DefaultContainerPadding , theme . DefaultContainerPadding , 4 )
} ;
}
private void Settings_PrintLevelingEnabledChanged ( object sender , EventArgs e )
{
if ( printLevelingSwitch ! = null )
{
printLevelingSwitch . Checked = printer . Settings . GetValue < bool > ( SettingsKey . print_leveling_enabled ) ;
}
}
2019-04-04 17:18:12 -07:00
}
}