2017-05-23 19:03:30 -07:00
/ *
Copyright ( c ) 2017 , 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 .
* /
using System ;
2017-07-14 13:55:02 -07:00
using System.Threading ;
2017-05-23 19:03:30 -07:00
using MatterHackers.Agg ;
2017-06-04 14:02:56 -07:00
using MatterHackers.Agg.PlatformAbstract ;
2017-05-23 19:03:30 -07:00
using MatterHackers.Agg.UI ;
using MatterHackers.Localizations ;
using MatterHackers.MatterControl.ActionBar ;
2017-05-24 14:19:02 -07:00
using MatterHackers.MatterControl.CustomWidgets ;
2017-05-23 19:03:30 -07:00
using MatterHackers.MatterControl.EeProm ;
using MatterHackers.MatterControl.PrinterCommunication ;
2017-06-29 18:46:59 -07:00
using MatterHackers.MatterControl.SlicerConfiguration ;
2017-06-29 19:42:20 -07:00
using MatterHackers.MeshVisualizer ;
2017-05-23 19:03:30 -07:00
namespace MatterHackers.MatterControl.PartPreviewWindow
{
2017-06-09 08:16:46 -07:00
public class PrinterActionsBar : FlowLayoutWidget
2017-05-23 19:03:30 -07:00
{
2017-06-09 08:16:46 -07:00
private static EePromMarlinWindow openEePromMarlinWidget = null ;
private static EePromRepetierWindow openEePromRepetierWidget = null ;
private string noEepromMappingMessage = "Oops! There is no eeprom mapping for your printer's firmware." . Localize ( ) + "\n\n" + "You may need to wait a minute for your printer to finish initializing." . Localize ( ) ;
private string noEepromMappingTitle = "Warning - No EEProm Mapping" . Localize ( ) ;
private OverflowDropdown overflowDropdown ;
2017-06-29 19:42:20 -07:00
private SliceProgressReporter sliceProgressReporter ;
2017-07-14 13:55:02 -07:00
private CancellationTokenSource gcodeLoadCancellationTokenSource ;
2017-06-29 19:42:20 -07:00
public class SliceProgressReporter : IProgress < string >
{
private MeshViewerWidget meshViewer ;
public SliceProgressReporter ( MeshViewerWidget meshViewer )
{
this . meshViewer = meshViewer ;
}
public void StartReporting ( )
{
meshViewer . BeginProgressReporting ( "Slicing Part" ) ;
}
public void EndReporting ( )
{
meshViewer . EndProgressReporting ( ) ;
}
public void Report ( string value )
{
meshViewer . partProcessingInfo . centeredInfoDescription . Text = value ;
}
}
2017-07-06 12:22:56 -07:00
public PrinterActionsBar ( View3DWidget modelViewer , PrinterTabPage printerTabPage )
2017-05-23 19:03:30 -07:00
{
2017-06-09 08:16:46 -07:00
UndoBuffer undoBuffer = modelViewer . UndoBuffer ;
2017-05-23 19:03:30 -07:00
2017-07-11 16:12:57 -07:00
var defaultMargin = new BorderDouble ( 8 , 0 ) ;
2017-06-29 19:42:20 -07:00
sliceProgressReporter = new SliceProgressReporter ( modelViewer . meshViewerWidget ) ;
2017-06-09 08:16:46 -07:00
this . HAnchor = HAnchor . ParentLeftRight ;
this . VAnchor = VAnchor . FitToChildren ;
2017-05-27 17:48:32 -07:00
2017-06-09 08:16:46 -07:00
var buttonFactory = ApplicationController . Instance . Theme . BreadCrumbButtonFactory ;
2017-05-27 17:48:32 -07:00
2017-06-09 08:16:46 -07:00
this . AddChild ( new PrinterConnectButton ( buttonFactory ) ) ;
2017-05-23 19:03:30 -07:00
2017-07-11 16:12:57 -07:00
this . AddChild ( new PrintActionRow ( buttonFactory , this , defaultMargin ) ) ;
2017-05-24 19:11:51 -07:00
2017-06-09 08:16:46 -07:00
this . AddChild ( new HorizontalSpacer ( ) ) ;
2017-05-24 14:19:02 -07:00
2017-06-09 08:16:46 -07:00
var initialMargin = buttonFactory . Margin ;
2017-05-24 14:19:02 -07:00
2017-06-29 19:42:20 -07:00
var sliceButton = buttonFactory . Generate ( "Slice" . Localize ( ) ) ;
sliceButton . ToolTipText = "Slice Parts" . Localize ( ) ;
sliceButton . Name = "Generate Gcode Button" ;
2017-07-11 16:12:57 -07:00
sliceButton . Margin = defaultMargin ;
2017-06-29 19:42:20 -07:00
sliceButton . Click + = async ( s , e ) = >
{
if ( ActiveSliceSettings . Instance . PrinterSelected )
{
var printItem = ApplicationController . Instance . ActivePrintItem ;
if ( ActiveSliceSettings . Instance . IsValid ( ) & & printItem ! = null )
{
sliceButton . Enabled = false ;
try
{
sliceProgressReporter . StartReporting ( ) ;
// Save any pending changes before starting the print
await ApplicationController . Instance . ActiveView3DWidget . PersistPlateIfNeeded ( ) ;
await SlicingQueue . SliceFileAsync ( printItem , sliceProgressReporter ) ;
2017-07-14 13:55:02 -07:00
gcodeLoadCancellationTokenSource = new CancellationTokenSource ( ) ;
ApplicationController . Instance . Printer . BedPlate . LoadGCode ( printItem . GetGCodePathAndFileName ( ) , gcodeLoadCancellationTokenSource . Token , printerTabPage . modelViewer . gcodeViewer . LoadProgress_Changed ) ;
2017-06-29 19:42:20 -07:00
sliceProgressReporter . EndReporting ( ) ;
2017-07-07 06:18:58 -07:00
printerTabPage . ViewMode = PartViewMode . Layers3D ;
2017-06-29 19:42:20 -07:00
// HACK: directly fire method which previously ran on SlicingDone event on PrintItemWrapper
2017-07-10 14:00:27 -07:00
UiThread . RunOnIdle ( printerTabPage . modelViewer . gcodeViewer . CreateAndAddChildren ) ;
2017-06-29 19:42:20 -07:00
}
catch ( Exception ex )
{
Console . WriteLine ( "Error slicing file: " + ex . Message ) ;
}
sliceButton . Enabled = true ;
} ;
}
else
{
UiThread . RunOnIdle ( ( ) = >
{
StyledMessageBox . ShowMessageBox ( null , "Oops! Please select a printer in order to continue slicing." , "Select Printer" , StyledMessageBox . MessageType . OK ) ;
} ) ;
}
} ;
this . AddChild ( sliceButton ) ;
2017-06-29 18:46:59 -07:00
this . AddChild ( new TemperatureWidgetExtruder ( ApplicationController . Instance . Theme . MenuButtonFactory )
{
Margin = new BorderDouble ( right : 10 )
} ) ;
if ( ActiveSliceSettings . Instance . GetValue < bool > ( SettingsKey . has_heated_bed ) )
{
this . AddChild ( new TemperatureWidgetBed ( ) ) ;
}
2017-07-11 16:12:57 -07:00
buttonFactory . Margin = defaultMargin ;
2017-06-04 14:02:56 -07:00
2017-07-11 16:09:07 -07:00
Button configureEePromButton = buttonFactory . Generate ( "" , StaticData . Instance . LoadIcon ( "memory_16x16.png" , 16 , 16 ) ) ;
2017-06-09 08:16:46 -07:00
configureEePromButton . ToolTipText = "EEProm" ;
configureEePromButton . Click + = configureEePromButton_Click ;
this . AddChild ( configureEePromButton ) ;
2017-05-24 19:11:51 -07:00
2017-07-11 16:09:07 -07:00
Button undoButton = buttonFactory . Generate ( "" , StaticData . Instance . LoadIcon ( "Undo_grey_16x.png" , 16 , 16 ) ) ;
2017-06-09 08:16:46 -07:00
undoButton . Name = "3D View Undo" ;
undoButton . ToolTipText = "Undo" ;
undoButton . Enabled = false ;
2017-07-11 16:12:57 -07:00
undoButton . Margin = defaultMargin ;
2017-06-09 08:16:46 -07:00
undoButton . Click + = ( sender , e ) = >
{
undoBuffer . Undo ( ) ;
} ;
this . AddChild ( undoButton ) ;
undoButton . VAnchor = VAnchor . ParentCenter ;
2017-07-11 16:09:07 -07:00
Button redoButton = buttonFactory . Generate ( "" , StaticData . Instance . LoadIcon ( "Redo_grey_16x.png" , 16 , 16 ) ) ;
2017-06-09 08:16:46 -07:00
redoButton . Name = "3D View Redo" ;
redoButton . ToolTipText = "Redo" ;
redoButton . Enabled = false ;
redoButton . Click + = ( sender , e ) = >
{
undoBuffer . Redo ( ) ;
} ;
this . AddChild ( redoButton ) ;
redoButton . VAnchor = VAnchor . ParentCenter ;
2017-06-04 14:02:56 -07:00
2017-06-09 08:16:46 -07:00
buttonFactory . Margin = initialMargin ;
2017-06-04 14:02:56 -07:00
2017-06-09 08:16:46 -07:00
undoBuffer . Changed + = ( sender , e ) = >
{
undoButton . Enabled = undoBuffer . UndoCount > 0 ;
redoButton . Enabled = undoBuffer . RedoCount > 0 ;
} ;
2017-05-26 01:14:22 -07:00
2017-06-09 08:16:46 -07:00
overflowDropdown = new OverflowDropdown ( allowLightnessInvert : true )
{
AlignToRightEdge = true ,
2017-07-11 16:12:57 -07:00
Name = "Printer Overflow Menu" ,
Margin = defaultMargin
2017-06-09 08:16:46 -07:00
} ;
overflowDropdown . DynamicPopupContent = GeneratePrinterOverflowMenu ;
2017-06-02 13:17:30 -07:00
2017-06-09 08:16:46 -07:00
// Deregister on close
this . Closed + = ( s , e ) = >
{
2017-06-02 13:17:30 -07:00
overflowDropdown . DynamicPopupContent = GeneratePrinterOverflowMenu ;
2017-07-11 16:12:57 -07:00
} ;
2017-05-25 17:58:20 -07:00
2017-06-09 08:16:46 -07:00
this . AddChild ( overflowDropdown ) ;
}
2017-05-24 14:19:02 -07:00
2017-07-14 13:55:02 -07:00
public override void OnClosed ( ClosedEventArgs e )
{
gcodeLoadCancellationTokenSource ? . Cancel ( ) ;
base . OnClosed ( e ) ;
}
2017-06-09 08:16:46 -07:00
private GuiWidget GeneratePrinterOverflowMenu ( )
{
2017-07-27 14:25:21 -07:00
var printerSettings = ActiveSliceSettings . Instance ;
2017-07-28 08:19:22 -07:00
2017-07-27 14:25:21 -07:00
var widgetToPop = new FlowLayoutWidget ( FlowDirection . TopToBottom )
2017-05-24 14:19:02 -07:00
{
2017-06-09 08:16:46 -07:00
HAnchor = HAnchor . FitToChildren ,
VAnchor = VAnchor . FitToChildren ,
} ;
2017-05-24 14:19:02 -07:00
2017-07-28 08:19:22 -07:00
var menuActions = new NamedAction [ ]
2017-06-09 08:16:46 -07:00
{
2017-07-28 08:19:22 -07:00
new NamedAction ( )
2017-07-27 14:25:21 -07:00
{
2017-07-28 08:19:22 -07:00
Title = "Rename Printer" . Localize ( ) ,
Action = ( ) = >
2017-07-27 14:25:21 -07:00
{
2017-07-28 08:19:22 -07:00
var renameItemWindow = new RenameItemWindow (
"Rename Printer" . Localize ( ) + ":" ,
printerSettings . GetValue ( SettingsKey . printer_name ) ,
( newName ) = >
{
if ( ! string . IsNullOrEmpty ( newName ) )
{
printerSettings . SetValue ( SettingsKey . printer_name , newName ) ;
}
} ) ;
2017-07-27 14:25:21 -07:00
}
2017-07-28 08:19:22 -07:00
} ,
new NamedAction ( ) { Title = "----" } ,
new NamedAction ( )
2017-07-27 14:25:21 -07:00
{
2017-07-28 08:19:22 -07:00
Title = "Delete Printer" . Localize ( ) ,
Action = ( ) = >
2017-07-27 14:25:21 -07:00
{
2017-07-28 08:19:22 -07:00
StyledMessageBox . ShowMessageBox (
( doDelete ) = >
{
if ( doDelete )
{
ActiveSliceSettings . Instance . Helpers . SetMarkedForDelete ( true ) ;
}
} ,
"Are you sure you want to delete your currently selected printer?" . Localize ( ) ,
"Delete Printer?" . Localize ( ) ,
StyledMessageBox . MessageType . YES_NO ,
"Delete Printer" . Localize ( ) ) ;
2017-07-27 14:25:21 -07:00
}
2017-07-28 08:19:22 -07:00
}
2017-07-27 14:25:21 -07:00
} ;
2017-07-28 08:19:22 -07:00
// Create menu items in the DropList for each element in this.menuActions
foreach ( var menuAction in menuActions )
{
MenuItem menuItem ;
if ( menuAction . Title = = "----" )
{
menuItem = overflowDropdown . CreateHorizontalLine ( ) ;
}
else
{
menuItem = overflowDropdown . CreateMenuItem ( ( string ) menuAction . Title ) ;
menuItem . Name = $"{menuAction.Title} Menu Item" ;
}
menuItem . Enabled = menuAction . Action ! = null ;
menuItem . ClearRemovedFlag ( ) ;
if ( menuItem . Enabled )
{
menuItem . Click + = ( s , e ) = >
{
menuAction . Action ( ) ;
} ;
}
widgetToPop . AddChild ( menuItem ) ;
}
2017-05-23 19:03:30 -07:00
2017-06-09 08:16:46 -07:00
return widgetToPop ;
}
2017-05-23 19:03:30 -07:00
2017-06-09 08:16:46 -07:00
private void configureEePromButton_Click ( object sender , EventArgs mouseEvent )
{
UiThread . RunOnIdle ( ( ) = >
2017-05-23 19:03:30 -07:00
{
#if false // This is to force the creation of the repetier window for testing when we don't have repetier firmware.
new MatterHackers . MatterControl . EeProm . EePromRepetierWidget ( ) ;
#else
2017-06-13 17:22:49 -07:00
switch ( PrinterConnection . Instance . FirmwareType )
2017-06-09 08:16:46 -07:00
{
2017-06-13 17:32:38 -07:00
case FirmwareTypes . Repetier :
2017-06-09 08:16:46 -07:00
if ( openEePromRepetierWidget ! = null )
{
openEePromRepetierWidget . BringToFront ( ) ;
}
else
{
openEePromRepetierWidget = new EePromRepetierWindow ( ) ;
openEePromRepetierWidget . Closed + = ( RepetierWidget , RepetierEvent ) = >
2017-05-23 19:03:30 -07:00
{
2017-06-09 08:16:46 -07:00
openEePromRepetierWidget = null ;
} ;
}
break ;
2017-06-13 17:32:38 -07:00
case FirmwareTypes . Marlin :
2017-06-09 08:16:46 -07:00
if ( openEePromMarlinWidget ! = null )
{
openEePromMarlinWidget . BringToFront ( ) ;
}
else
{
openEePromMarlinWidget = new EePromMarlinWindow ( ) ;
openEePromMarlinWidget . Closed + = ( marlinWidget , marlinEvent ) = >
2017-05-23 19:03:30 -07:00
{
2017-06-09 08:16:46 -07:00
openEePromMarlinWidget = null ;
} ;
}
break ;
default :
2017-06-13 17:22:49 -07:00
PrinterConnection . Instance . SendLineToPrinterNow ( "M115" ) ;
2017-06-09 08:16:46 -07:00
StyledMessageBox . ShowMessageBox ( null , noEepromMappingMessage , noEepromMappingTitle , StyledMessageBox . MessageType . OK ) ;
break ;
}
2017-05-23 19:03:30 -07:00
#endif
} ) ;
}
}
}