commit
a1f2d2e94a
35 changed files with 1030 additions and 899 deletions
|
|
@ -139,7 +139,7 @@ namespace MatterHackers.MatterControl
|
|||
linkButton.OriginRelativeParent = new VectorMath.Vector2(linkButton.OriginRelativeParent.X, linkButton.OriginRelativeParent.Y + descentInPixels);
|
||||
linkButton.Click += (sender, mouseEvent) =>
|
||||
{
|
||||
MatterControlApplication.Instance.LaunchBrowser(elementState.Href);
|
||||
ApplicationController.Instance.LaunchBrowser(elementState.Href);
|
||||
};
|
||||
elementsUnderConstruction.Peek().AddChild(linkButton);
|
||||
}
|
||||
|
|
@ -196,7 +196,7 @@ namespace MatterHackers.MatterControl
|
|||
linkButton.Cursor = Cursors.Hand;
|
||||
linkButton.Click += (sender, mouseEvent) =>
|
||||
{
|
||||
MatterControlApplication.Instance.LaunchBrowser(elementState.Href);
|
||||
ApplicationController.Instance.LaunchBrowser(elementState.Href);
|
||||
};
|
||||
elementsUnderConstruction.Peek().AddChild(linkButton);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ namespace MatterHackers.MatterControl
|
|||
{
|
||||
InitiateUpdateDownload();
|
||||
// Switch to the about page so we can see the download progress.
|
||||
GuiWidget aboutTabWidget = FindNamedWidgetRecursive(ApplicationController.Instance.MainView, "About Tab");
|
||||
GuiWidget aboutTabWidget = ApplicationController.Instance.MainView.FindNamedChildRecursive("About Tab");
|
||||
|
||||
if (aboutTabWidget is Tab aboutTab)
|
||||
{
|
||||
|
|
@ -248,25 +248,6 @@ namespace MatterHackers.MatterControl
|
|||
}
|
||||
}
|
||||
|
||||
private static GuiWidget FindNamedWidgetRecursive(GuiWidget root, string name)
|
||||
{
|
||||
foreach (GuiWidget child in root.Children)
|
||||
{
|
||||
if (child.Name == name)
|
||||
{
|
||||
return child;
|
||||
}
|
||||
|
||||
GuiWidget foundWidget = FindNamedWidgetRecursive(child, name);
|
||||
if (foundWidget != null)
|
||||
{
|
||||
return foundWidget;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void onVersionRequestFailed(object sender, ResponseErrorEventArgs e)
|
||||
{
|
||||
SetUpdateStatus(UpdateStatusStates.UpToDate);
|
||||
|
|
@ -455,7 +436,7 @@ namespace MatterHackers.MatterControl
|
|||
installUpdate.Start();
|
||||
|
||||
//Attempt to close current application
|
||||
SystemWindow topSystemWindow = MatterControlApplication.Instance as SystemWindow;
|
||||
SystemWindow topSystemWindow = AppContext.RootSystemWindow;
|
||||
if (topSystemWindow != null)
|
||||
{
|
||||
topSystemWindow.CloseOnIdle();
|
||||
|
|
|
|||
|
|
@ -69,6 +69,21 @@ namespace MatterHackers.MatterControl
|
|||
using MatterHackers.VectorMath;
|
||||
using SettingsManagement;
|
||||
|
||||
public class AppContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Native platform features
|
||||
/// </summary>
|
||||
public static INativePlatformFeatures Platform { get; set; }
|
||||
|
||||
public static bool IsLoading { get; internal set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// The root SystemWindow
|
||||
/// </summary>
|
||||
public static SystemWindow RootSystemWindow { get; internal set; }
|
||||
}
|
||||
|
||||
public class ApplicationController
|
||||
{
|
||||
public ThemeConfig Theme { get; set; } = new ThemeConfig();
|
||||
|
|
@ -109,10 +124,7 @@ namespace MatterHackers.MatterControl
|
|||
public const string EnvironmentName = "";
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Allows application components to hook initial SystemWindow Load event without an existing Widget instance
|
||||
/// </summary>
|
||||
public static event EventHandler Load;
|
||||
public bool ApplicationExiting { get; internal set; } = false;
|
||||
|
||||
public static Func<string, Task<Dictionary<string, string>>> GetProfileHistory;
|
||||
|
||||
|
|
@ -145,7 +157,7 @@ namespace MatterHackers.MatterControl
|
|||
// HACK: short term solution to resolve printer reference for non-printer related contexts
|
||||
DragDropData.Printer = printer;
|
||||
|
||||
if (!MatterControlApplication.IsLoading)
|
||||
if (!AppContext.IsLoading)
|
||||
{
|
||||
// Fire printer changed event
|
||||
}
|
||||
|
|
@ -161,7 +173,7 @@ namespace MatterHackers.MatterControl
|
|||
ActiveSliceSettings.OnActivePrinterChanged(null);
|
||||
}
|
||||
|
||||
if (!MatterControlApplication.IsLoading
|
||||
if (!AppContext.IsLoading
|
||||
&& printer.Settings.PrinterSelected
|
||||
&& printer.Settings.GetValue<bool>(SettingsKey.auto_connect))
|
||||
{
|
||||
|
|
@ -178,6 +190,13 @@ namespace MatterHackers.MatterControl
|
|||
{
|
||||
await this.SetActivePrinter(emptyPrinter);
|
||||
}
|
||||
public void LaunchBrowser(string targetUri)
|
||||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
Process.Start(targetUri);
|
||||
});
|
||||
}
|
||||
|
||||
public void RefreshActiveInstance(PrinterSettings updatedPrinterSettings)
|
||||
{
|
||||
|
|
@ -224,7 +243,7 @@ namespace MatterHackers.MatterControl
|
|||
{
|
||||
Thread.CurrentThread.Name = $"ThumbnailGeneration";
|
||||
|
||||
while(!MatterControlApplication.Instance.ApplicationExiting)
|
||||
while(!this.ApplicationExiting)
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
|
||||
|
|
@ -273,7 +292,7 @@ namespace MatterHackers.MatterControl
|
|||
|
||||
public SlicePresetsWindow EditQualityPresetsWindow { get; set; }
|
||||
|
||||
public ApplicationView MainView;
|
||||
public GuiWidget MainView;
|
||||
|
||||
private EventHandler unregisterEvents;
|
||||
|
||||
|
|
@ -476,19 +495,18 @@ namespace MatterHackers.MatterControl
|
|||
ScrollBar.ScrollBarWidth = 8 * GuiWidget.DeviceScale;
|
||||
ScrollBar.GrowThumbBy = 2;
|
||||
|
||||
// Initialize statics
|
||||
DefaultThumbBackground.DefaultBackgroundColor = Color.Transparent;
|
||||
|
||||
Object3D.AssetsPath = ApplicationDataStorage.Instance.LibraryAssetsPath;
|
||||
|
||||
this.Library = new LibraryConfig();
|
||||
this.Library.ContentProviders.Add(new[] { "stl", "obj", "amf", "mcx" }, new MeshContentProvider());
|
||||
|
||||
this.Library.ContentProviders.Add("gcode", new GCodeContentProvider());
|
||||
|
||||
// Name = "MainSlidePanel";
|
||||
ActiveTheme.ThemeChanged.RegisterEvent((s, e) =>
|
||||
{
|
||||
if (!MatterControlApplication.IsLoading)
|
||||
if (!AppContext.IsLoading)
|
||||
{
|
||||
ReloadAll();
|
||||
}
|
||||
|
|
@ -679,7 +697,7 @@ namespace MatterHackers.MatterControl
|
|||
VAnchor = VAnchor.Center
|
||||
});
|
||||
|
||||
MatterControlApplication.Instance.AddChild(reloadingOverlay);
|
||||
AppContext.RootSystemWindow.AddChild(reloadingOverlay);
|
||||
|
||||
this.IsReloading = true;
|
||||
|
||||
|
|
@ -687,19 +705,17 @@ namespace MatterHackers.MatterControl
|
|||
{
|
||||
using (new QuickTimer($"ReloadAll_{reloadCount++}:"))
|
||||
{
|
||||
MainView?.CloseAllChildren();
|
||||
using (new QuickTimer("ReloadAll_AddElements"))
|
||||
{
|
||||
// Actual ReloadAll implementation
|
||||
MainView?.CreateAndAddChildren();
|
||||
}
|
||||
MainView = new WidescreenPanel();
|
||||
this.DoneReloadingAll?.CallEvents(null, null);
|
||||
|
||||
using (new QuickTimer("Time to AddMainview: "))
|
||||
{
|
||||
AppContext.RootSystemWindow.CloseAllChildren();
|
||||
AppContext.RootSystemWindow.AddChild(MainView);
|
||||
}
|
||||
}
|
||||
|
||||
this.IsReloading = false;
|
||||
|
||||
MatterControlApplication.Instance.RemoveChild(reloadingOverlay);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -720,7 +736,7 @@ namespace MatterHackers.MatterControl
|
|||
ApplicationSettings.Instance.ReleaseClientToken();
|
||||
}
|
||||
|
||||
static void LoadOemOrDefaultTheme()
|
||||
internal static void LoadOemOrDefaultTheme()
|
||||
{
|
||||
// if not check for the oem color and use it if set
|
||||
// else default to "Blue - Light"
|
||||
|
|
@ -741,26 +757,15 @@ namespace MatterHackers.MatterControl
|
|||
{
|
||||
if (globalInstance == null)
|
||||
{
|
||||
//using (new PerformanceTimer("Startup", "AppController Instance"))
|
||||
globalInstance = new ApplicationController();
|
||||
|
||||
ActiveSliceSettings.ActivePrinterChanged.RegisterEvent((s, e) =>
|
||||
{
|
||||
globalInstance = new ApplicationController();
|
||||
|
||||
// Set the default theme colors
|
||||
LoadOemOrDefaultTheme();
|
||||
|
||||
// Accessing any property on ProfileManager will run the static constructor and spin up the ProfileManager instance
|
||||
bool na = ProfileManager.Instance.IsGuestProfile;
|
||||
|
||||
globalInstance.MainView = new DesktopView();
|
||||
|
||||
ActiveSliceSettings.ActivePrinterChanged.RegisterEvent((s, e) =>
|
||||
if (!AppContext.IsLoading)
|
||||
{
|
||||
if (!MatterControlApplication.IsLoading)
|
||||
{
|
||||
ApplicationController.Instance.ReloadAll();
|
||||
}
|
||||
}, ref globalInstance.unregisterEvents);
|
||||
}
|
||||
ApplicationController.Instance.ReloadAll();
|
||||
}
|
||||
}, ref globalInstance.unregisterEvents);
|
||||
}
|
||||
return globalInstance;
|
||||
}
|
||||
|
|
@ -781,6 +786,12 @@ namespace MatterHackers.MatterControl
|
|||
return string.IsNullOrEmpty(libraryItem.ID) ? null : ApplicationController.CacheablePath("ItemThumbnails", $"{libraryItem.ID}.png");
|
||||
}
|
||||
|
||||
public string ThumbnailCachePath(ILibraryItem libraryItem, int width, int height)
|
||||
{
|
||||
// TODO: Use content SHA
|
||||
return string.IsNullOrEmpty(libraryItem.ID) ? null : ApplicationController.CacheablePath("ItemThumbnails", $"{libraryItem.ID}-{width}x{height}.png");
|
||||
}
|
||||
|
||||
public void SwitchToPurchasedLibrary()
|
||||
{
|
||||
var purchasedContainer = Library.RootLibaryContainer.ChildContainers.Where(c => c.ID == "LibraryProviderPurchasedKey").FirstOrDefault();
|
||||
|
|
@ -791,6 +802,72 @@ namespace MatterHackers.MatterControl
|
|||
}
|
||||
}
|
||||
|
||||
public void OnLoadActions()
|
||||
{
|
||||
// TODO: Calling UserChanged seems wrong. Load the right user before we spin up controls, rather than after
|
||||
// Pushing this after load fixes that empty printer list
|
||||
/////////////////////ApplicationController.Instance.UserChanged();
|
||||
|
||||
bool showAuthWindow = PrinterSetup.ShouldShowAuthPanel?.Invoke() ?? false;
|
||||
if (showAuthWindow)
|
||||
{
|
||||
if (ApplicationSettings.Instance.get(ApplicationSettingsKey.SuppressAuthPanel) != "True")
|
||||
{
|
||||
//Launch window to prompt user to sign in
|
||||
UiThread.RunOnIdle(() => DialogWindow.Show(PrinterSetup.GetBestStartPage()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//If user in logged in sync before checking to prompt to create printer
|
||||
if (ApplicationController.SyncPrinterProfiles == null)
|
||||
{
|
||||
RunSetupIfRequired();
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplicationController.SyncPrinterProfiles.Invoke("ApplicationController.OnLoadActions()", null).ContinueWith((task) =>
|
||||
{
|
||||
RunSetupIfRequired();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This should be moved into the splash screen and shown instead of MainView
|
||||
if (AggContext.OperatingSystem == OSType.Android)
|
||||
{
|
||||
// show this last so it is on top
|
||||
if (UserSettings.Instance.get("SoftwareLicenseAccepted") != "true")
|
||||
{
|
||||
UiThread.RunOnIdle(() => DialogWindow.Show<LicenseAgreementPage>());
|
||||
}
|
||||
}
|
||||
|
||||
if (ApplicationController.Instance.ActivePrinter is PrinterConfig printer
|
||||
&& printer.Settings.PrinterSelected
|
||||
&& printer.Settings.GetValue<bool>(SettingsKey.auto_connect))
|
||||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
//PrinterConnectionAndCommunication.Instance.HaltConnectionThread();
|
||||
printer.Connection.Connect();
|
||||
}, 2);
|
||||
}
|
||||
|
||||
//HtmlWindowTest();
|
||||
|
||||
AppContext.IsLoading = false;
|
||||
}
|
||||
|
||||
private static void RunSetupIfRequired()
|
||||
{
|
||||
if (!ProfileManager.Instance.ActiveProfiles.Any())
|
||||
{
|
||||
// Start the setup wizard if no profiles exist
|
||||
UiThread.RunOnIdle(() => DialogWindow.Show(PrinterSetup.GetBestStartPage()));
|
||||
}
|
||||
}
|
||||
|
||||
public void SwitchToSharedLibrary()
|
||||
{
|
||||
// Switch to the shared library
|
||||
|
|
@ -840,67 +917,6 @@ namespace MatterHackers.MatterControl
|
|||
}
|
||||
}
|
||||
|
||||
public void OnLoadActions()
|
||||
{
|
||||
Load?.Invoke(this, null);
|
||||
|
||||
// Pushing this after load fixes that empty printer list
|
||||
ApplicationController.Instance.UserChanged();
|
||||
|
||||
bool showAuthWindow = PrinterSetup.ShouldShowAuthPanel?.Invoke() ?? false;
|
||||
if (showAuthWindow)
|
||||
{
|
||||
if (ApplicationSettings.Instance.get(ApplicationSettingsKey.SuppressAuthPanel) != "True")
|
||||
{
|
||||
//Launch window to prompt user to sign in
|
||||
UiThread.RunOnIdle(() => DialogWindow.Show(PrinterSetup.GetBestStartPage()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//If user in logged in sync before checking to prompt to create printer
|
||||
if (ApplicationController.SyncPrinterProfiles == null)
|
||||
{
|
||||
RunSetupIfRequired();
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplicationController.SyncPrinterProfiles.Invoke("ApplicationController.OnLoadActions()", null).ContinueWith((task) =>
|
||||
{
|
||||
RunSetupIfRequired();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (AggContext.OperatingSystem == OSType.Android)
|
||||
{
|
||||
// show this last so it is on top
|
||||
if (UserSettings.Instance.get("SoftwareLicenseAccepted") != "true")
|
||||
{
|
||||
UiThread.RunOnIdle(() => DialogWindow.Show<LicenseAgreementPage>());
|
||||
}
|
||||
}
|
||||
|
||||
if (this.ActivePrinter.Settings.PrinterSelected
|
||||
&& this.ActivePrinter.Settings.GetValue<bool>(SettingsKey.auto_connect))
|
||||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
//PrinterConnectionAndCommunication.Instance.HaltConnectionThread();
|
||||
this.ActivePrinter.Connection.Connect();
|
||||
}, 2);
|
||||
}
|
||||
}
|
||||
|
||||
private static void RunSetupIfRequired()
|
||||
{
|
||||
if (!ProfileManager.Instance.ActiveProfiles.Any())
|
||||
{
|
||||
// Start the setup wizard if no profiles exist
|
||||
UiThread.RunOnIdle(() => DialogWindow.Show(PrinterSetup.GetBestStartPage()));
|
||||
}
|
||||
}
|
||||
|
||||
private EventHandler unregisterEvent;
|
||||
|
||||
public Stream LoadHttpAsset(string url)
|
||||
|
|
@ -1466,4 +1482,186 @@ namespace MatterHackers.MatterControl
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
public enum ReportSeverity2 { Warning, Error }
|
||||
|
||||
public interface INativePlatformFeatures
|
||||
{
|
||||
event EventHandler PictureTaken;
|
||||
void TakePhoto(string imageFileName);
|
||||
void OpenCameraPreview();
|
||||
void PlaySound(string fileName);
|
||||
void ConfigureWifi();
|
||||
bool CameraInUseByExternalProcess { get; set; }
|
||||
bool IsNetworkConnected();
|
||||
void FindAndInstantiatePlugins(SystemWindow systemWindow);
|
||||
void ProcessCommandline();
|
||||
void ReportException(Exception e, string key = "", string value = "", ReportSeverity2 warningLevel = ReportSeverity2.Warning);
|
||||
void PlatformInit(Action<string> reporter);
|
||||
}
|
||||
|
||||
public static class Application
|
||||
{
|
||||
private static ProgressBar progressBar;
|
||||
private static TextWidget statusText;
|
||||
private static FlowLayoutWidget progressPanel;
|
||||
private static string lastSection = "";
|
||||
private static Stopwatch timer;
|
||||
|
||||
public static string PlatformFeaturesProvider { get; set; } = "MatterHackers.MatterControl.WindowsPlatformsFeatures, MatterControl";
|
||||
|
||||
public static SystemWindow LoadRootWindow(int width, int height)
|
||||
{
|
||||
timer = Stopwatch.StartNew();
|
||||
|
||||
var systemWindow = new RootSystemWindow(width, height)
|
||||
{
|
||||
BackgroundColor = Color.DarkGray
|
||||
};
|
||||
|
||||
var overlay = new GuiWidget();
|
||||
overlay.AnchorAll();
|
||||
|
||||
systemWindow.AddChild(overlay);
|
||||
|
||||
progressPanel = new FlowLayoutWidget(FlowDirection.TopToBottom)
|
||||
{
|
||||
HAnchor = HAnchor.Center,
|
||||
VAnchor = VAnchor.Center,
|
||||
MinimumSize = new VectorMath.Vector2(400, 100),
|
||||
};
|
||||
overlay.AddChild(progressPanel);
|
||||
|
||||
progressPanel.AddChild(statusText = new TextWidget("", textColor: new Color("#bbb"))
|
||||
{
|
||||
MinimumSize = new VectorMath.Vector2(200, 30)
|
||||
});
|
||||
|
||||
progressPanel.AddChild(progressBar = new ProgressBar()
|
||||
{
|
||||
FillColor = new Color("#3D4B72"),
|
||||
BorderColor = new Color("#777"),
|
||||
Height = 11,
|
||||
Width = 300,
|
||||
HAnchor = HAnchor.Absolute,
|
||||
VAnchor = VAnchor.Absolute
|
||||
});
|
||||
|
||||
AppContext.RootSystemWindow = systemWindow;
|
||||
|
||||
// Hook SystemWindow load and spin up MatterControl once we've hit first draw
|
||||
systemWindow.Load += (s, e) =>
|
||||
{
|
||||
ReportStartupProgress(0.02, "First draw->RunOnIdle");
|
||||
|
||||
//UiThread.RunOnIdle(() =>
|
||||
Task.Run(() =>
|
||||
{
|
||||
ReportStartupProgress(0.1, "Datastore");
|
||||
Datastore.Instance.Initialize();
|
||||
|
||||
ReportStartupProgress(0.15, "MatterControlApplication.Initialize");
|
||||
var mainView = Initialize(systemWindow, (progress0To1, status) =>
|
||||
{
|
||||
ReportStartupProgress(0.2 + progress0To1 * 0.7, status);
|
||||
});
|
||||
|
||||
ReportStartupProgress(0.9, "AddChild->MainView");
|
||||
systemWindow.AddChild(mainView, 0);
|
||||
|
||||
ReportStartupProgress(1, "");
|
||||
systemWindow.BackgroundColor = Color.Transparent;
|
||||
overlay.Close();
|
||||
|
||||
// TODO: Still can't figure out the delay between concluding this block and the first actual render with MainView content. Current
|
||||
// best guess is delays between widget construction and OpenGL texture creation
|
||||
});
|
||||
};
|
||||
|
||||
// Block indefinitely
|
||||
ReportStartupProgress(0, "ShowAsSystemWindow");
|
||||
|
||||
return systemWindow;
|
||||
}
|
||||
|
||||
public static GuiWidget Initialize(SystemWindow systemWindow, Action<double, string> reporter)
|
||||
{
|
||||
AppContext.Platform = AggContext.CreateInstanceFrom<INativePlatformFeatures>(PlatformFeaturesProvider);
|
||||
|
||||
reporter?.Invoke(0.01, "PlatformInit");
|
||||
AppContext.Platform.PlatformInit((status) =>
|
||||
{
|
||||
reporter?.Invoke(0.01, status);
|
||||
});
|
||||
|
||||
// TODO: Appears to be unused and should be removed
|
||||
// set this at startup so that we can tell next time if it got set to true in close
|
||||
UserSettings.Instance.Fields.StartCount = UserSettings.Instance.Fields.StartCount + 1;
|
||||
|
||||
reporter?.Invoke(0.05, "ApplicationController");
|
||||
var na = ApplicationController.Instance;
|
||||
|
||||
// Set the default theme colors
|
||||
reporter?.Invoke(0.1, "LoadOemOrDefaultTheme");
|
||||
ApplicationController.LoadOemOrDefaultTheme();
|
||||
|
||||
// Accessing any property on ProfileManager will run the static constructor and spin up the ProfileManager instance
|
||||
reporter?.Invoke(0.2, "ProfileManager");
|
||||
bool na2 = ProfileManager.Instance.IsGuestProfile;
|
||||
|
||||
reporter?.Invoke(0.3, "MainView");
|
||||
ApplicationController.Instance.MainView = new WidescreenPanel();
|
||||
|
||||
// now that we are all set up lets load our plugins and allow them their chance to set things up
|
||||
reporter?.Invoke(0.8, "Plugins");
|
||||
AppContext.Platform.FindAndInstantiatePlugins(systemWindow);
|
||||
if (ApplicationController.Instance.PluginsLoaded != null)
|
||||
{
|
||||
ApplicationController.Instance.PluginsLoaded.CallEvents(null, null);
|
||||
}
|
||||
|
||||
reporter?.Invoke(0.9, "Process Commandline");
|
||||
AppContext.Platform.ProcessCommandline();
|
||||
|
||||
reporter?.Invoke(0.91, "OnLoadActions");
|
||||
ApplicationController.Instance.OnLoadActions();
|
||||
|
||||
UiThread.RunOnIdle(CheckOnPrinter);
|
||||
|
||||
return ApplicationController.Instance.MainView;
|
||||
}
|
||||
|
||||
private static void ReportStartupProgress(double progress0To1, string section)
|
||||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
statusText.Text = section;
|
||||
progressBar.RatioComplete = progress0To1;
|
||||
progressPanel.Invalidate();
|
||||
|
||||
Console.WriteLine($"Time to '{lastSection}': {timer.ElapsedMilliseconds}");
|
||||
timer.Restart();
|
||||
|
||||
lastSection = section;
|
||||
});
|
||||
}
|
||||
|
||||
private static void CheckOnPrinter()
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO: UiThread should not be driving anything in Printer.Connection
|
||||
ApplicationController.Instance.ActivePrinter.Connection.OnIdle();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Print(e.Message);
|
||||
GuiWidget.BreakInDebugger();
|
||||
#if DEBUG
|
||||
throw e;
|
||||
#endif
|
||||
}
|
||||
UiThread.RunOnIdle(CheckOnPrinter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (c) 2015, Lars Brubaker
|
||||
Copyright (c) 2017, Lars Brubaker, John Lewin
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -28,13 +28,7 @@ either expressed or implied, of the FreeBSD Project.
|
|||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.MatterControl.CustomWidgets;
|
||||
using MatterHackers.MatterControl.PrinterCommunication;
|
||||
using MatterHackers.MatterControl.SlicerConfiguration;
|
||||
using MatterHackers.VectorMath;
|
||||
using System;
|
||||
|
||||
namespace MatterHackers.MatterControl
|
||||
{
|
||||
|
|
@ -49,40 +43,4 @@ namespace MatterHackers.MatterControl
|
|||
public string ShortProfileID { get; set; }
|
||||
public string CacheKey => this.ShortProfileID + ProfileManager.ProfileExtension;
|
||||
}
|
||||
|
||||
public abstract class ApplicationView : GuiWidget
|
||||
{
|
||||
public abstract void CreateAndAddChildren();
|
||||
}
|
||||
|
||||
public class DesktopView : ApplicationView
|
||||
{
|
||||
private WidescreenPanel widescreenPanel;
|
||||
|
||||
public DesktopView()
|
||||
{
|
||||
CreateAndAddChildren();
|
||||
this.AnchorAll();
|
||||
}
|
||||
|
||||
public override void CreateAndAddChildren()
|
||||
{
|
||||
this.BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor;
|
||||
|
||||
var container = new FlowLayoutWidget(FlowDirection.TopToBottom);
|
||||
container.AnchorAll();
|
||||
|
||||
GuiWidget.TouchScreenMode = UserSettings.Instance.IsTouchScreen;
|
||||
|
||||
container.AddChild(new HorizontalLine(alpha:50));
|
||||
|
||||
widescreenPanel = new WidescreenPanel();
|
||||
container.AddChild(widescreenPanel);
|
||||
|
||||
using (new PerformanceTimer("ReloadAll", "AddChild"))
|
||||
{
|
||||
this.AddChild(container);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -439,7 +439,7 @@ namespace MatterHackers.MatterControl
|
|||
if (this.Scene.Persistable)
|
||||
{
|
||||
this.Scene.PersistAssets(ApplicationDataStorage.Instance.ApplicationLibraryDataPath, progress);
|
||||
this.EditContext.Save();
|
||||
this.EditContext?.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ namespace MatterHackers.MatterControl
|
|||
|
||||
this.AnchorAll();
|
||||
this.Name = "WidescreenPanel";
|
||||
this.BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor;
|
||||
|
||||
var theme = ApplicationController.Instance.Theme;
|
||||
|
||||
|
|
|
|||
179
ApplicationView/WindowsPlatformsFeatures.cs
Normal file
179
ApplicationView/WindowsPlatformsFeatures.cs
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
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;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.UI;
|
||||
|
||||
namespace MatterHackers.MatterControl
|
||||
{
|
||||
using Agg.Image;
|
||||
using MatterHackers.Agg.Platform;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.MatterControl.DataStorage;
|
||||
using MatterHackers.MatterControl.PluginSystem;
|
||||
using MatterHackers.MatterControl.PrintQueue;
|
||||
using MatterHackers.RenderOpenGl.OpenGl;
|
||||
|
||||
public class WindowsPlatformsFeatures : INativePlatformFeatures
|
||||
{
|
||||
public bool CameraInUseByExternalProcess { get; set; } = false;
|
||||
|
||||
public event EventHandler PictureTaken;
|
||||
|
||||
public void TakePhoto(string imageFileName)
|
||||
{
|
||||
ImageBuffer noCameraImage = new ImageBuffer(640, 480);
|
||||
Graphics2D graphics = noCameraImage.NewGraphics2D();
|
||||
graphics.Clear(Color.White);
|
||||
graphics.DrawString("No Camera Detected", 320, 240, pointSize: 24, justification: Agg.Font.Justification.Center);
|
||||
graphics.DrawString(DateTime.Now.ToString(), 320, 200, pointSize: 12, justification: Agg.Font.Justification.Center);
|
||||
AggContext.ImageIO.SaveImageData(imageFileName, noCameraImage);
|
||||
|
||||
PictureTaken?.Invoke(null, null);
|
||||
}
|
||||
|
||||
public void OpenCameraPreview()
|
||||
{
|
||||
//Camera launcher placeholder (KP)
|
||||
if (ApplicationSettings.Instance.get(ApplicationSettingsKey.HardwareHasCamera) == "true")
|
||||
{
|
||||
//Do something
|
||||
}
|
||||
else
|
||||
{
|
||||
//Do something else (like show warning message)
|
||||
}
|
||||
}
|
||||
|
||||
public void PlaySound(string fileName)
|
||||
{
|
||||
if (AggContext.OperatingSystem == OSType.Windows)
|
||||
{
|
||||
using (var mediaStream = AggContext.StaticData.OpenSteam(Path.Combine("Sounds", fileName)))
|
||||
{
|
||||
(new System.Media.SoundPlayer(mediaStream)).Play();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsNetworkConnected()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ConfigureWifi()
|
||||
{
|
||||
}
|
||||
|
||||
public void FindAndInstantiatePlugins(SystemWindow systemWindow)
|
||||
{
|
||||
string oemName = ApplicationSettings.Instance.GetOEMName();
|
||||
foreach (MatterControlPlugin plugin in PluginFinder.CreateInstancesOf<MatterControlPlugin>())
|
||||
{
|
||||
string pluginInfo = plugin.GetPluginInfoJSon();
|
||||
Dictionary<string, string> nameValuePairs = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(pluginInfo);
|
||||
|
||||
if (nameValuePairs != null && nameValuePairs.ContainsKey("OEM"))
|
||||
{
|
||||
if (nameValuePairs["OEM"] == oemName)
|
||||
{
|
||||
plugin.Initialize(systemWindow);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
plugin.Initialize(systemWindow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ProcessCommandline()
|
||||
{
|
||||
var commandLineArgs = Environment.GetCommandLineArgs();
|
||||
|
||||
for (int currentCommandIndex = 0; currentCommandIndex < commandLineArgs.Length; currentCommandIndex++)
|
||||
{
|
||||
string command = commandLineArgs[currentCommandIndex];
|
||||
string commandUpper = command.ToUpper();
|
||||
switch (commandUpper)
|
||||
{
|
||||
case "FORCE_SOFTWARE_RENDERING":
|
||||
GL.HardwareAvailable = false;
|
||||
break;
|
||||
|
||||
case "CLEAR_CACHE":
|
||||
AboutWidget.DeleteCacheData(0);
|
||||
break;
|
||||
|
||||
case "SHOW_MEMORY":
|
||||
RootSystemWindow.ShowMemoryUsed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Do we still want to support command line arguments for adding to the queue?
|
||||
foreach (string arg in commandLineArgs)
|
||||
{
|
||||
string argExtension = Path.GetExtension(arg).ToUpper();
|
||||
if (argExtension.Length > 1
|
||||
&& MeshFileIo.ValidFileExtensions().Contains(argExtension))
|
||||
{
|
||||
QueueData.Instance.AddItem(new PrintItemWrapper(new PrintItem(Path.GetFileName(arg), Path.GetFullPath(arg))));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void ReportException(Exception e, string key = "", string value = "", ReportSeverity2 warningLevel = ReportSeverity2.Warning)
|
||||
{
|
||||
}
|
||||
|
||||
public void PlatformInit(Action<string> reporter)
|
||||
{
|
||||
if (AggContext.OperatingSystem == OSType.Mac && AggContext.StaticData == null)
|
||||
{
|
||||
// Set working directory - this duplicates functionality in Main but is necessary on OSX as Main fires much later (after the constructor in this case)
|
||||
// resulting in invalid paths due to path tests running before the working directory has been overridden. Setting the value before initializing StaticData
|
||||
// works around this architectural difference.
|
||||
Directory.SetCurrentDirectory(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location));
|
||||
}
|
||||
|
||||
// Initialize a standard file system backed StaticData provider
|
||||
if (AggContext.StaticData == null) // it may already be initialized by tests
|
||||
{
|
||||
AggContext.StaticData = new FileSystemStaticData();
|
||||
}
|
||||
|
||||
ApplicationSettings.Instance.set("HardwareHasCamera", "false");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -68,7 +68,7 @@ namespace MatterHackers.MatterControl.ConfigurationPage
|
|||
var previewButton = buttonFactory.Generate("Preview".Localize().ToUpper());
|
||||
previewButton.Click += (s, e) =>
|
||||
{
|
||||
MatterControlApplication.Instance.OpenCameraPreview();
|
||||
AppContext.Platform.OpenCameraPreview();
|
||||
};
|
||||
|
||||
this.AddSettingsRow(
|
||||
|
|
@ -286,11 +286,11 @@ namespace MatterHackers.MatterControl.ConfigurationPage
|
|||
}
|
||||
#endif
|
||||
|
||||
AddMenuItem("Forums".Localize(), () => MatterControlApplication.Instance.LaunchBrowser("https://forums.matterhackers.com/category/20/mattercontrol"));
|
||||
AddMenuItem("Wiki".Localize(), () => MatterControlApplication.Instance.LaunchBrowser("http://wiki.mattercontrol.com"));
|
||||
AddMenuItem("Guides and Articles".Localize(), () => MatterControlApplication.Instance.LaunchBrowser("http://www.matterhackers.com/topic/mattercontrol"));
|
||||
AddMenuItem("Release Notes".Localize(), () => MatterControlApplication.Instance.LaunchBrowser("http://wiki.mattercontrol.com/Release_Notes"));
|
||||
AddMenuItem("Report a Bug".Localize(), () => MatterControlApplication.Instance.LaunchBrowser("https://github.com/MatterHackers/MatterControl/issues"));
|
||||
AddMenuItem("Forums".Localize(), () => ApplicationController.Instance.LaunchBrowser("https://forums.matterhackers.com/category/20/mattercontrol"));
|
||||
AddMenuItem("Wiki".Localize(), () => ApplicationController.Instance.LaunchBrowser("http://wiki.mattercontrol.com"));
|
||||
AddMenuItem("Guides and Articles".Localize(), () => ApplicationController.Instance.LaunchBrowser("http://www.matterhackers.com/topic/mattercontrol"));
|
||||
AddMenuItem("Release Notes".Localize(), () => ApplicationController.Instance.LaunchBrowser("http://wiki.mattercontrol.com/Release_Notes"));
|
||||
AddMenuItem("Report a Bug".Localize(), () => ApplicationController.Instance.LaunchBrowser("https://github.com/MatterHackers/MatterControl/issues"));
|
||||
|
||||
var updateMatterControl = new SettingsItem("Check For Update".Localize());
|
||||
updateMatterControl.Click += (s, e) =>
|
||||
|
|
@ -427,32 +427,6 @@ namespace MatterHackers.MatterControl.ConfigurationPage
|
|||
private string rebuildThumbnailsMessage = "You are switching to a different thumbnail rendering mode. If you want, your current thumbnails can be removed and recreated in the new style. You can switch back and forth at any time. There will be some processing overhead while the new thumbnails are created.\n\nDo you want to rebuild your existing thumbnails now?".Localize();
|
||||
private string rebuildThumbnailsTitle = "Rebuild Thumbnails Now".Localize();
|
||||
|
||||
private void RestartApplication()
|
||||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
// Iterate to the top SystemWindow
|
||||
GuiWidget parent = this;
|
||||
while (parent.Parent != null)
|
||||
{
|
||||
parent = parent.Parent;
|
||||
}
|
||||
|
||||
// MatterControlApplication is the root child on the SystemWindow object
|
||||
MatterControlApplication app = parent.Children[0] as MatterControlApplication;
|
||||
#if !__ANDROID__
|
||||
app.RestartOnClose = true;
|
||||
app.Close();
|
||||
#else
|
||||
// Re-initialize and load
|
||||
LocalizedString.ResetTranslationMap();
|
||||
ApplicationController.Instance.MainView = new DesktopView();
|
||||
app.RemoveAllChildren();
|
||||
app.AnchorAll();
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
private void GenerateLocalizationValidationFile()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
|
|||
{
|
||||
if (listView.ActiveContainer.Parent != null)
|
||||
{
|
||||
UiThread.RunOnIdle(() => listView.LoadContainer(listView.ActiveContainer.Parent));
|
||||
UiThread.RunOnIdle(() => listView.SetActiveContainer(listView.ActiveContainer.Parent));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -119,7 +119,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
|
|||
gotoProviderButton.Margin = new BorderDouble(right: 5);
|
||||
gotoProviderButton.Click += (s, e) =>
|
||||
{
|
||||
UiThread.RunOnIdle(() => listView.LoadContainer(container));
|
||||
UiThread.RunOnIdle(() => listView.SetActiveContainer(container));
|
||||
};
|
||||
this.AddChild(gotoProviderButton);
|
||||
|
||||
|
|
|
|||
|
|
@ -127,10 +127,16 @@ namespace MatterHackers.MatterControl
|
|||
|
||||
if (thumbnail != null)
|
||||
{
|
||||
// Cache big render
|
||||
string cachePath = ApplicationController.Instance.ThumbnailCachePath(item);
|
||||
AggContext.ImageIO.SaveImageData(cachePath, thumbnail);
|
||||
|
||||
if(ApplicationController.Instance.Library.ActiveContainer is ILibraryWritableContainer writableContainer)
|
||||
// Cache at requested size
|
||||
cachePath = ApplicationController.Instance.ThumbnailCachePath(item, width, height);
|
||||
thumbnail = LibraryProviderHelpers.ResizeImage(thumbnail, width, height);
|
||||
AggContext.ImageIO.SaveImageData(cachePath, thumbnail);
|
||||
|
||||
if (ApplicationController.Instance.Library.ActiveContainer is ILibraryWritableContainer writableContainer)
|
||||
{
|
||||
writableContainer.SetThumbnail(item, thumbnail.Width, thumbnail.Height, thumbnail);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,9 @@ namespace MatterHackers.MatterControl.Library
|
|||
|
||||
protected void OnContentChanged()
|
||||
{
|
||||
// Reload the container when new contents are available
|
||||
this.Load();
|
||||
|
||||
this.ContentChanged?.Invoke(this, null);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -160,12 +160,6 @@ namespace MatterHackers.MatterControl.CustomWidgets
|
|||
var itemsContentView = contentView as IListContentView;
|
||||
itemsContentView.ClearItems();
|
||||
|
||||
// Wait for the container to load
|
||||
await Task.Run(() =>
|
||||
{
|
||||
sourceContainer.Load();
|
||||
});
|
||||
|
||||
int width = itemsContentView.ThumbWidth;
|
||||
int height = itemsContentView.ThumbHeight;
|
||||
|
||||
|
|
@ -221,7 +215,6 @@ namespace MatterHackers.MatterControl.CustomWidgets
|
|||
if (firstItem != null)
|
||||
{
|
||||
firstItem.ViewWidget.LoadItemThumbnail().ConfigureAwait(false);
|
||||
firstItem.ViewWidget.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -264,23 +257,57 @@ namespace MatterHackers.MatterControl.CustomWidgets
|
|||
}
|
||||
}
|
||||
|
||||
internal ImageBuffer LoadCachedImage(ListViewItem listViewItem)
|
||||
internal ImageBuffer LoadCachedImage(ListViewItem listViewItem, int width, int height)
|
||||
{
|
||||
string cachePath = ApplicationController.Instance.ThumbnailCachePath(listViewItem.Model);
|
||||
|
||||
bool isCached = !string.IsNullOrEmpty(cachePath) && File.Exists(cachePath);
|
||||
if (isCached)
|
||||
ImageBuffer cachedItem = LoadImage(ApplicationController.Instance.ThumbnailCachePath(listViewItem.Model, width, height));
|
||||
if (cachedItem != null)
|
||||
{
|
||||
ImageBuffer thumbnail = new ImageBuffer();
|
||||
AggContext.ImageIO.LoadImageData(cachePath, thumbnail);
|
||||
thumbnail.SetRecieveBlender(new BlenderPreMultBGRA());
|
||||
return cachedItem;
|
||||
}
|
||||
|
||||
return thumbnail;
|
||||
// Check for big render, resize, cache and return
|
||||
var bigRender = LoadImage(ApplicationController.Instance.ThumbnailCachePath(listViewItem.Model));
|
||||
if (bigRender != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var thumbnail = LibraryProviderHelpers.ResizeImage(bigRender, width, height);
|
||||
|
||||
// Cache at requested size
|
||||
AggContext.ImageIO.SaveImageData(
|
||||
ApplicationController.Instance.ThumbnailCachePath(listViewItem.Model, width, height),
|
||||
thumbnail);
|
||||
|
||||
return thumbnail;
|
||||
}
|
||||
catch { } // suppress and return null on errors
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private ImageBuffer LoadImage(string filePath)
|
||||
{
|
||||
ImageBuffer thumbnail = null;
|
||||
|
||||
try
|
||||
{
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
var temp = new ImageBuffer();
|
||||
AggContext.ImageIO.LoadImageData(filePath, temp);
|
||||
temp.SetRecieveBlender(new BlenderPreMultBGRA());
|
||||
|
||||
thumbnail = temp;
|
||||
}
|
||||
|
||||
return thumbnail;
|
||||
}
|
||||
catch { } // Suppress exceptions, return null on any errors
|
||||
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
// TODO: ResizeCanvas is also colorizing thumbnails as a proof of concept
|
||||
public ImageBuffer ResizeCanvas(ImageBuffer originalImage, int width, int height)
|
||||
{
|
||||
|
|
@ -308,7 +335,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
|
|||
|
||||
private void listViewItem_DoubleClick(object sender, MouseEventArgs e)
|
||||
{
|
||||
UiThread.RunOnIdle((Action)(async () =>
|
||||
UiThread.RunOnIdle(async () =>
|
||||
{
|
||||
var listViewItem = sender as ListViewItem;
|
||||
var itemModel = listViewItem.Model;
|
||||
|
|
@ -320,10 +347,15 @@ namespace MatterHackers.MatterControl.CustomWidgets
|
|||
if (containerLink != null)
|
||||
{
|
||||
var container = await containerLink.GetContainer(null);
|
||||
await Task.Run(() =>
|
||||
{
|
||||
container.Load();
|
||||
});
|
||||
|
||||
if (container != null)
|
||||
{
|
||||
container.Parent = ActiveContainer;
|
||||
LoadContainer(container);
|
||||
SetActiveContainer(container);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -366,12 +398,12 @@ namespace MatterHackers.MatterControl.CustomWidgets
|
|||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
public void LoadContainer(ILibraryContainer temp)
|
||||
public void SetActiveContainer(ILibraryContainer container)
|
||||
{
|
||||
this.LibraryContext.ActiveContainer = temp;
|
||||
this.LibraryContext.ActiveContainer = container;
|
||||
}
|
||||
|
||||
public ObservableCollection<ListViewItem> SelectedItems { get; } = new ObservableCollection<ListViewItem>();
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ namespace MatterHackers.MatterControl.CustomWidgets
|
|||
{
|
||||
var listView = listViewItem.ListView;
|
||||
|
||||
var thumbnail = listView.LoadCachedImage(listViewItem);
|
||||
var thumbnail = listView.LoadCachedImage(listViewItem, thumbWidth, thumbHeight);
|
||||
if (thumbnail != null)
|
||||
{
|
||||
SetItemThumbnail(thumbnail);
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@
|
|||
<Compile Include="ActionBar\PrinterSelector.cs" />
|
||||
<Compile Include="ActionBar\ResetButton.cs" />
|
||||
<Compile Include="ActionBar\TemperatureWidgetBed.cs" />
|
||||
<Compile Include="ApplicationView\OemProfileDictionary.cs" />
|
||||
<Compile Include="ApplicationView\WindowsPlatformsFeatures.cs" />
|
||||
<Compile Include="PartPreviewWindow\View3D\PrinterBar\PrintPopupMenu.cs" />
|
||||
<Compile Include="PartPreviewWindow\View3D\PrinterBar\SliceButton.cs" />
|
||||
<Compile Include="PartPreviewWindow\View3D\PrinterBar\PrinterConnectButton.cs" />
|
||||
|
|
@ -149,6 +151,7 @@
|
|||
<Compile Include="PrinterControls\MacroDetailPage.cs" />
|
||||
<Compile Include="PrinterControls\MacroListPage.cs" />
|
||||
<Compile Include="PrinterControls\PrinterConnections\PrinterSetup.cs" />
|
||||
<Compile Include="RootSystemWindow.cs" />
|
||||
<Compile Include="SetupWizard\DialogWindow.cs" />
|
||||
<Compile Include="Utilities\InspectForm.cs" Condition="'$(Configuration)' == 'Debug'">
|
||||
<SubType>Form</SubType>
|
||||
|
|
@ -374,7 +377,6 @@
|
|||
<Compile Include="DataStorage\Datastore.cs" />
|
||||
<Compile Include="DataStorage\SQLiteUnix.cs" />
|
||||
<Compile Include="DataStorage\SQLiteAsync.cs" />
|
||||
<Compile Include="ApplicationView\MainApplicationWidget.cs" />
|
||||
<Compile Include="Utilities\ManifestFileHandler.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
|
|
|||
|
|
@ -33,631 +33,33 @@ using System.Diagnostics;
|
|||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Image;
|
||||
using MatterHackers.Agg.Platform;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.ImageProcessing;
|
||||
using MatterHackers.Localizations;
|
||||
using MatterHackers.MatterControl.DataStorage;
|
||||
using MatterHackers.MatterControl.PartPreviewWindow;
|
||||
using MatterHackers.MatterControl.PluginSystem;
|
||||
using MatterHackers.MatterControl.PrinterCommunication;
|
||||
using MatterHackers.MatterControl.PrinterControls.PrinterConnections;
|
||||
using MatterHackers.MatterControl.PrintQueue;
|
||||
using MatterHackers.MatterControl.SettingsManagement;
|
||||
using MatterHackers.MatterControl.SlicerConfiguration;
|
||||
using MatterHackers.PolygonMesh.Processors;
|
||||
using MatterHackers.RenderOpenGl.OpenGl;
|
||||
using MatterHackers.VectorMath;
|
||||
using Mindscape.Raygun4Net;
|
||||
|
||||
namespace MatterHackers.MatterControl
|
||||
{
|
||||
public class MatterControlApplication : SystemWindow
|
||||
public static class MatterControlApplication
|
||||
{
|
||||
|
||||
#if DEBUG
|
||||
|
||||
//public static string MCWSBaseUri { get; } = "http://192.168.2.129:9206";
|
||||
public static string MCWSBaseUri { get; } = "https://mattercontrol-test.appspot.com";
|
||||
|
||||
#else
|
||||
public static string MCWSBaseUri { get; } = "https://mattercontrol.appspot.com";
|
||||
#endif
|
||||
|
||||
public static bool CameraInUseByExternalProcess { get; set; } = false;
|
||||
public bool RestartOnClose = false;
|
||||
private static MatterControlApplication instance;
|
||||
private string[] commandLineArgs = null;
|
||||
private bool DoCGCollectEveryDraw = false;
|
||||
private int drawCount = 0;
|
||||
private AverageMillisecondTimer millisecondTimer = new AverageMillisecondTimer();
|
||||
private bool ShowMemoryUsed = false;
|
||||
|
||||
public void ConfigureWifi()
|
||||
{
|
||||
}
|
||||
|
||||
private Stopwatch totalDrawTime = new Stopwatch();
|
||||
|
||||
public static bool IsLoading { get; private set; } = true;
|
||||
|
||||
public static void RequestPowerShutDown()
|
||||
{
|
||||
// does nothing on windows
|
||||
}
|
||||
|
||||
static MatterControlApplication()
|
||||
{
|
||||
if (AggContext.OperatingSystem == OSType.Mac && AggContext.StaticData == null)
|
||||
{
|
||||
// Set working directory - this duplicates functionality in Main but is necessary on OSX as Main fires much later (after the constructor in this case)
|
||||
// resulting in invalid paths due to path tests running before the working directory has been overridden. Setting the value before initializing StaticData
|
||||
// works around this architectural difference.
|
||||
Directory.SetCurrentDirectory(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location));
|
||||
}
|
||||
|
||||
// Because fields on this class call localization methods and because those methods depend on the StaticData provider and because the field
|
||||
// initializers run before the class constructor, we need to init the platform specific provider in the static constructor (or write a custom initializer method)
|
||||
//
|
||||
// Initialize a standard file system backed StaticData provider
|
||||
if (AggContext.StaticData == null) // it may already be initialized by tests
|
||||
{
|
||||
AggContext.StaticData = new MatterHackers.Agg.FileSystemStaticData();
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
WinformsSystemWindow.InspectorCreator = (systemWindow) =>
|
||||
{
|
||||
if (systemWindow == Instance)
|
||||
{
|
||||
// If systemWindow is MatterControlApplication, include Scene
|
||||
var partContext = ApplicationController.Instance.DragDropData;
|
||||
return new InspectForm(systemWindow, partContext.SceneContext.Scene, partContext.View3DWidget);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, exclude Scene
|
||||
return new InspectForm(systemWindow);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
private MatterControlApplication(double width, double height)
|
||||
: base(width, height)
|
||||
{
|
||||
ApplicationSettings.Instance.set("HardwareHasCamera", "false");
|
||||
|
||||
Name = "MatterControl";
|
||||
|
||||
// set this at startup so that we can tell next time if it got set to true in close
|
||||
UserSettings.Instance.Fields.StartCount = UserSettings.Instance.Fields.StartCount + 1;
|
||||
|
||||
this.commandLineArgs = Environment.GetCommandLineArgs();
|
||||
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
|
||||
|
||||
for (int currentCommandIndex = 0; currentCommandIndex < commandLineArgs.Length; currentCommandIndex++)
|
||||
{
|
||||
string command = commandLineArgs[currentCommandIndex];
|
||||
string commandUpper = command.ToUpper();
|
||||
switch (commandUpper)
|
||||
{
|
||||
case "FORCE_SOFTWARE_RENDERING":
|
||||
GL.HardwareAvailable = false;
|
||||
break;
|
||||
|
||||
case "CLEAR_CACHE":
|
||||
AboutWidget.DeleteCacheData(0);
|
||||
break;
|
||||
|
||||
case "SHOW_MEMORY":
|
||||
ShowMemoryUsed = true;
|
||||
break;
|
||||
|
||||
case "DO_GC_COLLECT_EVERY_DRAW":
|
||||
ShowMemoryUsed = true;
|
||||
DoCGCollectEveryDraw = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (MeshFileIo.ValidFileExtensions().Contains(Path.GetExtension(command).ToUpper()))
|
||||
{
|
||||
// If we are the only instance running then do nothing.
|
||||
// Else send these to the running instance so it can load them.
|
||||
}
|
||||
}
|
||||
|
||||
#if IS_WINDOWS_FORMS
|
||||
if (!Clipboard.IsInitialized)
|
||||
{
|
||||
Clipboard.SetSystemClipboard(new WindowsFormsClipboard());
|
||||
}
|
||||
#endif
|
||||
|
||||
GuiWidget.DefaultEnforceIntegerBounds = true;
|
||||
|
||||
if (UserSettings.Instance.IsTouchScreen)
|
||||
{
|
||||
GuiWidget.DeviceScale = 1.3;
|
||||
SystemWindow.ShareSingleOsWindow = true;
|
||||
}
|
||||
|
||||
string textSizeMode = UserSettings.Instance.get(UserSettingsKey.ApplicationTextSize);
|
||||
if (!string.IsNullOrEmpty(textSizeMode))
|
||||
{
|
||||
double textSize = 1.0;
|
||||
if(double.TryParse(textSizeMode, out textSize))
|
||||
{
|
||||
GuiWidget.DeviceScale = textSize;
|
||||
}
|
||||
}
|
||||
|
||||
//GuiWidget.DeviceScale = 2;
|
||||
|
||||
using (new PerformanceTimer("Startup", "MainView"))
|
||||
{
|
||||
this.AddChild(ApplicationController.Instance.MainView);
|
||||
}
|
||||
this.MinimumSize = minSize;
|
||||
this.Padding = new BorderDouble(0); //To be re-enabled once native borders are turned off
|
||||
|
||||
#if false // this is to test freeing gcodefile memory
|
||||
Button test = new Button("test");
|
||||
test.Click += (sender, e) =>
|
||||
{
|
||||
//MatterHackers.GCodeVisualizer.GCodeFile gcode = new GCodeVisualizer.GCodeFile();
|
||||
//gcode.Load(@"C:\Users\lbrubaker\Downloads\drive assy.gcode");
|
||||
SystemWindow window = new SystemWindow(100, 100);
|
||||
window.ShowAsSystemWindow();
|
||||
};
|
||||
allControls.AddChild(test);
|
||||
#endif
|
||||
this.AnchorAll();
|
||||
|
||||
if (GL.HardwareAvailable)
|
||||
{
|
||||
UseOpenGL = true;
|
||||
}
|
||||
string version = "2.0";
|
||||
|
||||
Title = "MatterHackers: MatterControl {0}".FormatWith(version);
|
||||
if (OemSettings.Instance.WindowTitleExtra != null && OemSettings.Instance.WindowTitleExtra.Trim().Length > 0)
|
||||
{
|
||||
Title = Title + " - {1}".FormatWith(version, OemSettings.Instance.WindowTitleExtra);
|
||||
}
|
||||
|
||||
Title = IntPtr.Size == 4 ? Title + " - 32Bit" : Title = Title + " - 64Bit";
|
||||
|
||||
UiThread.RunOnIdle(CheckOnPrinter);
|
||||
|
||||
string desktopPosition = ApplicationSettings.Instance.get(ApplicationSettingsKey.DesktopPosition);
|
||||
if (!string.IsNullOrEmpty(desktopPosition))
|
||||
{
|
||||
string[] sizes = desktopPosition.Split(',');
|
||||
|
||||
//If the desktop position is less than -10,-10, override
|
||||
int xpos = Math.Max(int.Parse(sizes[0]), -10);
|
||||
int ypos = Math.Max(int.Parse(sizes[1]), -10);
|
||||
|
||||
this.InitialDesktopPosition = new Point2D(xpos, ypos);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.InitialDesktopPosition = new Point2D(-1, -1);
|
||||
}
|
||||
|
||||
this.Maximized = ApplicationSettings.Instance.get(ApplicationSettingsKey.MainWindowMaximized) == "true";
|
||||
}
|
||||
|
||||
public void TakePhoto(string imageFileName)
|
||||
{
|
||||
ImageBuffer noCameraImage = new ImageBuffer(640, 480);
|
||||
Graphics2D graphics = noCameraImage.NewGraphics2D();
|
||||
graphics.Clear(Color.White);
|
||||
graphics.DrawString("No Camera Detected", 320, 240, pointSize: 24, justification: Agg.Font.Justification.Center);
|
||||
graphics.DrawString(DateTime.Now.ToString(), 320, 200, pointSize: 12, justification: Agg.Font.Justification.Center);
|
||||
AggContext.ImageIO.SaveImageData(imageFileName, noCameraImage);
|
||||
|
||||
PictureTaken?.Invoke(null, null);
|
||||
}
|
||||
|
||||
private bool dropWasOnChild = true;
|
||||
|
||||
private EventHandler unregisterEvent;
|
||||
|
||||
public static MatterControlApplication Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = CreateInstance();
|
||||
instance.ShowAsSystemWindow();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler PictureTaken;
|
||||
|
||||
private static Vector2 minSize { get; set; } = new Vector2(600, 600);
|
||||
|
||||
public static MatterControlApplication CreateInstance(int overrideWidth = -1, int overrideHeight = -1)
|
||||
{
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
if (UserSettings.Instance.IsTouchScreen)
|
||||
{
|
||||
minSize = new Vector2(800, 480);
|
||||
}
|
||||
|
||||
// check if the app has a size already set
|
||||
string windowSize = ApplicationSettings.Instance.get(ApplicationSettingsKey.WindowSize);
|
||||
if (windowSize != null && windowSize != "")
|
||||
{
|
||||
// try and open our window matching the last size that we had for it.
|
||||
string[] sizes = windowSize.Split(',');
|
||||
|
||||
width = Math.Max(int.Parse(sizes[0]), (int)minSize.X + 1);
|
||||
height = Math.Max(int.Parse(sizes[1]), (int)minSize.Y + 1);
|
||||
}
|
||||
else // try to set it to a big size or the min size
|
||||
{
|
||||
Point2D desktopSize = AggContext.DesktopSize;
|
||||
|
||||
if (overrideWidth != -1)
|
||||
{
|
||||
width = overrideWidth;
|
||||
}
|
||||
else // try to set it to a good size
|
||||
{
|
||||
if (width < desktopSize.x)
|
||||
{
|
||||
width = 1280;
|
||||
}
|
||||
}
|
||||
|
||||
if (overrideHeight != -1)
|
||||
{
|
||||
// Height should be constrained to actual
|
||||
height = Math.Min(overrideHeight, desktopSize.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (height < desktopSize.y)
|
||||
{
|
||||
height = 720;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using (new PerformanceTimer("Startup", "Total"))
|
||||
{
|
||||
instance = new MatterControlApplication(width, height);
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void LaunchBrowser(string targetUri)
|
||||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
System.Diagnostics.Process.Start(targetUri);
|
||||
});
|
||||
}
|
||||
|
||||
public override void OnClosed(ClosedEventArgs e)
|
||||
{
|
||||
UserSettings.Instance.Fields.StartCountDurringExit = UserSettings.Instance.Fields.StartCount;
|
||||
|
||||
if (ApplicationController.Instance.ActivePrinter.Connection.CommunicationState != CommunicationStates.PrintingFromSd)
|
||||
{
|
||||
ApplicationController.Instance.ActivePrinter.Connection.Disable();
|
||||
}
|
||||
//Close connection to the local datastore
|
||||
ApplicationController.Instance.ActivePrinter.Connection.HaltConnectionThread();
|
||||
ApplicationController.Instance.OnApplicationClosed();
|
||||
|
||||
Datastore.Instance.Exit();
|
||||
|
||||
if (RestartOnClose)
|
||||
{
|
||||
string appPathAndFile = System.Reflection.Assembly.GetExecutingAssembly().Location;
|
||||
string pathToAppFolder = Path.GetDirectoryName(appPathAndFile);
|
||||
|
||||
ProcessStartInfo runAppLauncherStartInfo = new ProcessStartInfo();
|
||||
runAppLauncherStartInfo.Arguments = "\"{0}\" \"{1}\"".FormatWith(appPathAndFile, 1000);
|
||||
runAppLauncherStartInfo.FileName = Path.Combine(pathToAppFolder, "Launcher.exe");
|
||||
runAppLauncherStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
||||
runAppLauncherStartInfo.CreateNoWindow = true;
|
||||
|
||||
Process.Start(runAppLauncherStartInfo);
|
||||
}
|
||||
base.OnClosed(e);
|
||||
}
|
||||
|
||||
public override void OnClosing(ClosingEventArgs eventArgs)
|
||||
{
|
||||
if (this.HasBeenClosed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// save the last size of the window so we can restore it next time.
|
||||
ApplicationSettings.Instance.set(ApplicationSettingsKey.MainWindowMaximized, this.Maximized.ToString().ToLower());
|
||||
|
||||
if (!this.Maximized)
|
||||
{
|
||||
ApplicationSettings.Instance.set(ApplicationSettingsKey.WindowSize, string.Format("{0},{1}", Width, Height));
|
||||
ApplicationSettings.Instance.set(ApplicationSettingsKey.DesktopPosition, string.Format("{0},{1}", DesktopPosition.x, DesktopPosition.y));
|
||||
}
|
||||
|
||||
//Save a snapshot of the prints in queue
|
||||
QueueData.Instance.SaveDefaultQueue();
|
||||
|
||||
// If we are waiting for a response and get another request, just cancel the close until we get a response.
|
||||
if(exitDialogOpen)
|
||||
{
|
||||
eventArgs.Cancel = true;
|
||||
}
|
||||
|
||||
string caption = null;
|
||||
string message = null;
|
||||
|
||||
if (!ApplicationExiting
|
||||
&& !exitDialogOpen
|
||||
&& ApplicationController.Instance.ActivePrinter.Connection.PrinterIsPrinting)
|
||||
{
|
||||
if (ApplicationController.Instance.ActivePrinter.Connection.CommunicationState != CommunicationStates.PrintingFromSd)
|
||||
{
|
||||
caption = "Abort Print".Localize();
|
||||
message = "Are you sure you want to abort the current print and close MatterControl?".Localize();
|
||||
}
|
||||
else
|
||||
{
|
||||
caption = "Exit while printing".Localize();
|
||||
message = "Are you sure you want exit while a print is running from SD Card?\n\nNote: If you exit, it is recommended you wait until the print is completed before running MatterControl again.".Localize();
|
||||
}
|
||||
}
|
||||
else if (PartsSheet.IsSaving())
|
||||
{
|
||||
caption = "Confirm Exit".Localize();
|
||||
message = "You are currently saving a parts sheet, are you sure you want to exit?".Localize();
|
||||
}
|
||||
|
||||
if (caption != null)
|
||||
{
|
||||
// Record that we are waiting for a response to the request to close
|
||||
exitDialogOpen = true;
|
||||
|
||||
// We need to show an interactive dialog to determine if the original Close request should be honored, thus cancel the current Close request
|
||||
eventArgs.Cancel = true;
|
||||
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
StyledMessageBox.ShowMessageBox(
|
||||
(exitConfirmed) =>
|
||||
{
|
||||
// Record that the exitDialog has closed
|
||||
exitDialogOpen = false;
|
||||
|
||||
// Continue with the original shutdown request if exit confirmed by user
|
||||
if (exitConfirmed)
|
||||
{
|
||||
this.ApplicationExiting = true;
|
||||
|
||||
ApplicationController.Instance.Shutdown();
|
||||
|
||||
// Always call PrinterConnection.Disable on exit unless PrintingFromSd
|
||||
PrinterConnection printerConnection = ApplicationController.Instance.ActivePrinter.Connection;
|
||||
switch (printerConnection.CommunicationState)
|
||||
{
|
||||
case CommunicationStates.PrintingFromSd:
|
||||
case CommunicationStates.Paused when printerConnection.PrePauseCommunicationState == CommunicationStates.PrintingFromSd:
|
||||
break;
|
||||
|
||||
default:
|
||||
printerConnection.Disable();
|
||||
break;
|
||||
}
|
||||
|
||||
MatterControlApplication.instance.CloseOnIdle();
|
||||
|
||||
this.RestartOnClose = false;
|
||||
}
|
||||
},
|
||||
message,
|
||||
caption,
|
||||
StyledMessageBox.MessageType.YES_NO);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ApplicationExiting = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ApplicationExiting { get; private set; } = false;
|
||||
|
||||
private bool exitDialogOpen = false;
|
||||
|
||||
public override void OnDraw(Graphics2D graphics2D)
|
||||
{
|
||||
totalDrawTime.Restart();
|
||||
GuiWidget.DrawCount = 0;
|
||||
using (new PerformanceTimer("Draw Timer", "MC Draw"))
|
||||
{
|
||||
base.OnDraw(graphics2D);
|
||||
}
|
||||
totalDrawTime.Stop();
|
||||
|
||||
millisecondTimer.Update((int)totalDrawTime.ElapsedMilliseconds);
|
||||
|
||||
if (ShowMemoryUsed)
|
||||
{
|
||||
long memory = GC.GetTotalMemory(false);
|
||||
this.Title = "Allocated = {0:n0} : {1:000}ms, d{2} Size = {3}x{4}, onIdle = {5:00}:{6:00}, widgetsDrawn = {7}".FormatWith(memory, millisecondTimer.GetAverage(), drawCount++, this.Width, this.Height, UiThread.CountExpired, UiThread.Count, GuiWidget.DrawCount);
|
||||
if (DoCGCollectEveryDraw)
|
||||
{
|
||||
GC.Collect();
|
||||
}
|
||||
}
|
||||
|
||||
//msGraph.AddData("ms", totalDrawTime.ElapsedMilliseconds);
|
||||
//msGraph.Draw(MatterHackers.Agg.Transform.Affine.NewIdentity(), graphics2D);
|
||||
}
|
||||
|
||||
public override void OnLoad(EventArgs args)
|
||||
{
|
||||
// Moved from OnParentChanged
|
||||
if (File.Exists("RunUnitTests.txt"))
|
||||
{
|
||||
//DiagnosticWidget diagnosticView = new DiagnosticWidget(this);
|
||||
}
|
||||
|
||||
// now that we are all set up lets load our plugins and allow them their chance to set things up
|
||||
FindAndInstantiatePlugins();
|
||||
|
||||
if (ApplicationController.Instance.PluginsLoaded != null)
|
||||
{
|
||||
ApplicationController.Instance.PluginsLoaded.CallEvents(null, null);
|
||||
}
|
||||
|
||||
foreach (string arg in commandLineArgs)
|
||||
{
|
||||
string argExtension = Path.GetExtension(arg).ToUpper();
|
||||
if (argExtension.Length > 1
|
||||
&& MeshFileIo.ValidFileExtensions().Contains(argExtension))
|
||||
{
|
||||
QueueData.Instance.AddItem(new PrintItemWrapper(new PrintItem(Path.GetFileName(arg), Path.GetFullPath(arg))));
|
||||
}
|
||||
}
|
||||
|
||||
ApplicationController.Instance.OnLoadActions();
|
||||
|
||||
//HtmlWindowTest();
|
||||
|
||||
IsLoading = false;
|
||||
|
||||
base.OnLoad(args);
|
||||
}
|
||||
|
||||
public override void OnMouseMove(MouseEventArgs mouseEvent)
|
||||
{
|
||||
// run this first to make sure a child has the chance to take the drag drop event
|
||||
base.OnMouseMove(mouseEvent);
|
||||
|
||||
if (!mouseEvent.AcceptDrop && mouseEvent.DragFiles != null)
|
||||
{
|
||||
// no child has accepted the drop
|
||||
foreach (string file in mouseEvent.DragFiles)
|
||||
{
|
||||
string extension = Path.GetExtension(file).ToUpper();
|
||||
if ((extension != "" && MeshFileIo.ValidFileExtensions().Contains(extension))
|
||||
|| extension == ".GCODE"
|
||||
|| extension == ".ZIP")
|
||||
{
|
||||
//mouseEvent.AcceptDrop = true;
|
||||
}
|
||||
}
|
||||
dropWasOnChild = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
dropWasOnChild = true;
|
||||
}
|
||||
|
||||
if (GuiWidget.DebugBoundsUnderMouse)
|
||||
{
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void OpenCameraPreview()
|
||||
{
|
||||
//Camera launcher placeholder (KP)
|
||||
if (ApplicationSettings.Instance.get(ApplicationSettingsKey.HardwareHasCamera) == "true")
|
||||
{
|
||||
//Do something
|
||||
}
|
||||
else
|
||||
{
|
||||
//Do something else (like show warning message)
|
||||
}
|
||||
}
|
||||
|
||||
public void PlaySound(string fileName)
|
||||
{
|
||||
if (AggContext.OperatingSystem == OSType.Windows)
|
||||
{
|
||||
using (var mediaStream = AggContext.StaticData.OpenSteam(Path.Combine("Sounds", fileName)))
|
||||
{
|
||||
(new System.Media.SoundPlayer(mediaStream)).Play();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckOnPrinter()
|
||||
{
|
||||
try
|
||||
{
|
||||
ApplicationController.Instance.ActivePrinter.Connection.OnIdle();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Print(e.Message);
|
||||
GuiWidget.BreakInDebugger();
|
||||
#if DEBUG
|
||||
throw e;
|
||||
#endif
|
||||
}
|
||||
UiThread.RunOnIdle(CheckOnPrinter);
|
||||
}
|
||||
|
||||
private void FindAndInstantiatePlugins()
|
||||
{
|
||||
#if false
|
||||
string pluginDirectory = Path.Combine("..", "..", "..", "MatterControlPlugins", "bin");
|
||||
#if DEBUG
|
||||
pluginDirectory = Path.Combine(pluginDirectory, "Debug");
|
||||
#else
|
||||
pluginDirectory = Path.Combine(pluginDirectory, "Release");
|
||||
#endif
|
||||
if (!Directory.Exists(pluginDirectory))
|
||||
{
|
||||
string dataPath = ApplicationDataStorage.Instance.ApplicationUserDataPath;
|
||||
pluginDirectory = Path.Combine(dataPath, "Plugins");
|
||||
}
|
||||
// TODO: this should look in a plugin folder rather than just the application directory (we probably want it in the user folder).
|
||||
PluginFinder<MatterControlPlugin> pluginFinder = new PluginFinder<MatterControlPlugin>(pluginDirectory);
|
||||
#endif
|
||||
|
||||
string oemName = ApplicationSettings.Instance.GetOEMName();
|
||||
foreach (MatterControlPlugin plugin in PluginFinder.CreateInstancesOf<MatterControlPlugin>())
|
||||
{
|
||||
string pluginInfo = plugin.GetPluginInfoJSon();
|
||||
Dictionary<string, string> nameValuePairs = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(pluginInfo);
|
||||
|
||||
if (nameValuePairs != null && nameValuePairs.ContainsKey("OEM"))
|
||||
{
|
||||
if (nameValuePairs["OEM"] == oemName)
|
||||
{
|
||||
plugin.Initialize(this);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
plugin.Initialize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void AssertDebugNotDefined()
|
||||
{
|
||||
#if DEBUG
|
||||
|
|
@ -679,10 +81,5 @@ namespace MatterHackers.MatterControl
|
|||
MatterHackers.MeshVisualizer.MeshViewerWidget.AssertDebugNotDefined();
|
||||
MatterHackers.RenderOpenGl.GLMeshTrianglePlugin.AssertDebugNotDefined();
|
||||
}
|
||||
|
||||
public bool IsNetworkConnected()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,11 +81,11 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab
|
|||
{
|
||||
if (item.url != null)
|
||||
{
|
||||
MatterControlApplication.Instance.LaunchBrowser("http://www.matterhackers.com/" + item.url);
|
||||
ApplicationController.Instance.LaunchBrowser("http://www.matterhackers.com/" + item.url);
|
||||
}
|
||||
else if (item.link != null)
|
||||
{
|
||||
MatterControlApplication.Instance.LaunchBrowser(item.link);
|
||||
ApplicationController.Instance.LaunchBrowser(item.link);
|
||||
}
|
||||
|
||||
base.OnClick(mouseEvent);
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.PlusTab
|
|||
imageWidget.Cursor = Cursors.Hand;
|
||||
imageWidget.Click += (s, e) =>
|
||||
{
|
||||
MatterControlApplication.Instance.LaunchBrowser(content.link);
|
||||
ApplicationController.Instance.LaunchBrowser(content.link);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -534,8 +534,11 @@ namespace MatterHackers.MatterControl.PartPreviewWindow
|
|||
// When GCode changes, switch to the 3D layer view
|
||||
printer.ViewState.ViewMode = PartViewMode.Layers3D;
|
||||
|
||||
// HACK: directly fire method which previously ran on SlicingDone event on PrintItemWrapper
|
||||
UiThread.RunOnIdle(() => printerTabPage.gcode3DWidget.CreateAndAddChildren(printer));
|
||||
if (printerTabPage.gcode3DWidget != null)
|
||||
{
|
||||
// HACK: directly fire method which previously ran on SlicingDone event on PrintItemWrapper
|
||||
UiThread.RunOnIdle(() => printerTabPage.gcode3DWidget.CreateAndAddChildren(printer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io
|
|||
break;
|
||||
|
||||
case "ding":
|
||||
MatterControlApplication.Instance.PlaySound("timer-done.wav");
|
||||
AppContext.Platform.PlaySound("timer-done.wav");
|
||||
break;
|
||||
|
||||
case "show_message":
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ namespace MatterHackers.MatterControl.PrinterControls.PrinterConnections
|
|||
public static DialogPage GetBestStartPage(StartPageOptions options = StartPageOptions.Default)
|
||||
{
|
||||
// Do the printer setup logic
|
||||
bool WifiDetected = MatterControlApplication.Instance.IsNetworkConnected();
|
||||
bool WifiDetected = AppContext.Platform.IsNetworkConnected();
|
||||
if (!WifiDetected
|
||||
&& options != StartPageOptions.SkipWifiSetup)
|
||||
{
|
||||
|
|
|
|||
69
Program.cs
69
Program.cs
|
|
@ -1,8 +1,13 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Font;
|
||||
using MatterHackers.Agg.Platform;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.MatterControl.DataStorage;
|
||||
using MatterHackers.MatterControl.SettingsManagement;
|
||||
using Mindscape.Raygun4Net;
|
||||
|
|
@ -11,17 +16,20 @@ namespace MatterHackers.MatterControl
|
|||
{
|
||||
static class Program
|
||||
{
|
||||
private const int RaygunMaxNotifications = 15;
|
||||
private const int RaygunMaxNotifications = 15;
|
||||
|
||||
private static int raygunNotificationCount = 0;
|
||||
private static int raygunNotificationCount = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
private static RaygunClient _raygunClient = GetCorrectClient();
|
||||
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
public static void Main()
|
||||
{
|
||||
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
|
||||
|
||||
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
|
||||
|
||||
AggContext.Init(embeddedResourceName: "config.json");
|
||||
|
|
@ -29,7 +37,6 @@ namespace MatterHackers.MatterControl
|
|||
// Make sure we have the right working directory as we assume everything relative to the executable.
|
||||
Directory.SetCurrentDirectory(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location));
|
||||
|
||||
Datastore.Instance.Initialize();
|
||||
|
||||
#if !DEBUG
|
||||
// Conditionally spin up error reporting if not on the Stable channel
|
||||
|
|
@ -41,7 +48,11 @@ namespace MatterHackers.MatterControl
|
|||
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
|
||||
}
|
||||
|
||||
MatterControlApplication app = MatterControlApplication.Instance;
|
||||
// Get startup bounds from MatterControl and construct system window
|
||||
//var systemWindow = new DesktopMainWindow(400, 200)
|
||||
var (width, height) = RootSystemWindow.GetStartupBounds();
|
||||
|
||||
Application.LoadRootWindow(width, height).ShowAsSystemWindow();
|
||||
}
|
||||
|
||||
private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
|
||||
|
|
@ -64,27 +75,25 @@ namespace MatterHackers.MatterControl
|
|||
#endif
|
||||
}
|
||||
|
||||
private static RaygunClient _raygunClient = GetCorrectClient();
|
||||
private static RaygunClient GetCorrectClient()
|
||||
{
|
||||
if (AggContext.OperatingSystem == OSType.Mac)
|
||||
{
|
||||
return new RaygunClient("qmMBpKy3OSTJj83+tkO7BQ=="); // this is the Mac key
|
||||
}
|
||||
else
|
||||
{
|
||||
return new RaygunClient("hQIlyUUZRGPyXVXbI6l1dA=="); // this is the PC key
|
||||
}
|
||||
}
|
||||
|
||||
private static RaygunClient GetCorrectClient()
|
||||
{
|
||||
if (AggContext.OperatingSystem == OSType.Mac)
|
||||
{
|
||||
return new RaygunClient("qmMBpKy3OSTJj83+tkO7BQ=="); // this is the Mac key
|
||||
}
|
||||
else
|
||||
{
|
||||
return new RaygunClient("hQIlyUUZRGPyXVXbI6l1dA=="); // this is the PC key
|
||||
}
|
||||
}
|
||||
|
||||
// ** Standard Winforms Main ** //
|
||||
//[STAThread]
|
||||
//static void Main()
|
||||
//{
|
||||
// Application.EnableVisualStyles();
|
||||
// Application.SetCompatibleTextRenderingDefault(false);
|
||||
// Application.Run(new Form1());
|
||||
//}
|
||||
}
|
||||
// ** Standard Winforms Main ** //
|
||||
//[STAThread]
|
||||
//static void Main()
|
||||
//{
|
||||
// Application.EnableVisualStyles();
|
||||
// Application.SetCompatibleTextRenderingDefault(false);
|
||||
// Application.Run(new Form1());
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
376
RootSystemWindow.cs
Normal file
376
RootSystemWindow.cs
Normal file
|
|
@ -0,0 +1,376 @@
|
|||
/*
|
||||
Copyright (c) 2016, Lars Brubaker, Kevin Pope
|
||||
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;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using MatterHackers.Agg;
|
||||
using MatterHackers.Agg.Platform;
|
||||
using MatterHackers.Agg.UI;
|
||||
using MatterHackers.DataConverters3D;
|
||||
using MatterHackers.Localizations;
|
||||
using MatterHackers.MatterControl.DataStorage;
|
||||
using MatterHackers.MatterControl.PrinterCommunication;
|
||||
using MatterHackers.MatterControl.PrintQueue;
|
||||
using MatterHackers.MatterControl.SettingsManagement;
|
||||
using MatterHackers.RenderOpenGl.OpenGl;
|
||||
using MatterHackers.VectorMath;
|
||||
|
||||
namespace MatterHackers.MatterControl
|
||||
{
|
||||
public class RootSystemWindow : SystemWindow
|
||||
{
|
||||
private static Vector2 minSize { get; set; } = new Vector2(600, 600);
|
||||
|
||||
private Stopwatch totalDrawTime = new Stopwatch();
|
||||
|
||||
private bool dropWasOnChild = true;
|
||||
|
||||
private AverageMillisecondTimer millisecondTimer = new AverageMillisecondTimer();
|
||||
|
||||
internal static bool ShowMemoryUsed = false;
|
||||
|
||||
private int drawCount = 0;
|
||||
|
||||
private bool exitDialogOpen = false;
|
||||
|
||||
public RootSystemWindow(double width, double height)
|
||||
: base(width, height)
|
||||
{
|
||||
this.Name = "MatterControl";
|
||||
this.Padding = new BorderDouble(0); //To be re-enabled once native borders are turned off
|
||||
this.AnchorAll();
|
||||
|
||||
GuiWidget.DefaultEnforceIntegerBounds = true;
|
||||
|
||||
// TODO: Needs review - doesn't seem like we want to scale on Touchscreen, rather we want device specific, configuration based scaling. Suggest remove
|
||||
if (UserSettings.Instance.IsTouchScreen)
|
||||
{
|
||||
GuiWidget.DeviceScale = 1.3;
|
||||
SystemWindow.ShareSingleOsWindow = true;
|
||||
}
|
||||
|
||||
string textSizeMode = UserSettings.Instance.get(UserSettingsKey.ApplicationTextSize);
|
||||
if (!string.IsNullOrEmpty(textSizeMode))
|
||||
{
|
||||
double textSize = 1.0;
|
||||
if (double.TryParse(textSizeMode, out textSize))
|
||||
{
|
||||
GuiWidget.DeviceScale = textSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (GL.HardwareAvailable)
|
||||
{
|
||||
UseOpenGL = true;
|
||||
}
|
||||
|
||||
this.SetStartupTraits();
|
||||
}
|
||||
|
||||
public void SetStartupTraits()
|
||||
{
|
||||
string version = "2.0";
|
||||
|
||||
this.MinimumSize = minSize;
|
||||
|
||||
this.Title = "MatterHackers: MatterControl {0}".FormatWith(version);
|
||||
if (OemSettings.Instance.WindowTitleExtra != null && OemSettings.Instance.WindowTitleExtra.Trim().Length > 0)
|
||||
{
|
||||
this.Title = this.Title + " - {1}".FormatWith(version, OemSettings.Instance.WindowTitleExtra);
|
||||
}
|
||||
|
||||
this.Title = IntPtr.Size == 4 ? this.Title + " - 32Bit" : this.Title = this.Title + " - 64Bit";
|
||||
|
||||
string desktopPosition = ApplicationSettings.Instance.get(ApplicationSettingsKey.DesktopPosition);
|
||||
if (!string.IsNullOrEmpty(desktopPosition))
|
||||
{
|
||||
string[] sizes = desktopPosition.Split(',');
|
||||
|
||||
//If the desktop position is less than -10,-10, override
|
||||
int xpos = Math.Max(int.Parse(sizes[0]), -10);
|
||||
int ypos = Math.Max(int.Parse(sizes[1]), -10);
|
||||
|
||||
this.DesktopPosition = new Point2D(xpos, ypos);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.DesktopPosition = new Point2D(-1, -1);
|
||||
}
|
||||
|
||||
this.Maximized = ApplicationSettings.Instance.get(ApplicationSettingsKey.MainWindowMaximized) == "true";
|
||||
|
||||
#if IS_WINDOWS_FORMS
|
||||
if (!Clipboard.IsInitialized)
|
||||
{
|
||||
Clipboard.SetSystemClipboard(new WindowsFormsClipboard());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DEBUG && !__ANDROID__
|
||||
WinformsSystemWindow.InspectorCreator = (inspectingWindow) =>
|
||||
{
|
||||
if (inspectingWindow == this)
|
||||
{
|
||||
// If this is MatterControlApplication, include Scene
|
||||
var partContext = ApplicationController.Instance.DragDropData;
|
||||
return new InspectForm(inspectingWindow, partContext.SceneContext.Scene, partContext.View3DWidget);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, exclude Scene
|
||||
return new InspectForm(inspectingWindow);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
public static (int width, int height) GetStartupBounds(int overrideWidth = -1, int overrideHeight = -1)
|
||||
{
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
if (UserSettings.Instance.IsTouchScreen)
|
||||
{
|
||||
minSize = new Vector2(800, 480);
|
||||
}
|
||||
|
||||
// check if the app has a size already set
|
||||
string windowSize = ApplicationSettings.Instance.get(ApplicationSettingsKey.WindowSize);
|
||||
if (windowSize != null && windowSize != "")
|
||||
{
|
||||
// try and open our window matching the last size that we had for it.
|
||||
string[] sizes = windowSize.Split(',');
|
||||
|
||||
width = Math.Max(int.Parse(sizes[0]), (int)minSize.X + 1);
|
||||
height = Math.Max(int.Parse(sizes[1]), (int)minSize.Y + 1);
|
||||
}
|
||||
else // try to set it to a big size or the min size
|
||||
{
|
||||
Point2D desktopSize = AggContext.DesktopSize;
|
||||
|
||||
if (overrideWidth != -1)
|
||||
{
|
||||
width = overrideWidth;
|
||||
}
|
||||
else // try to set it to a good size
|
||||
{
|
||||
if (width < desktopSize.x)
|
||||
{
|
||||
width = 1280;
|
||||
}
|
||||
}
|
||||
|
||||
if (overrideHeight != -1)
|
||||
{
|
||||
// Height should be constrained to actual
|
||||
height = Math.Min(overrideHeight, desktopSize.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (height < desktopSize.y)
|
||||
{
|
||||
height = 720;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (width, height);
|
||||
}
|
||||
|
||||
public override void OnDraw(Graphics2D graphics2D)
|
||||
{
|
||||
totalDrawTime.Restart();
|
||||
GuiWidget.DrawCount = 0;
|
||||
using (new PerformanceTimer("Draw Timer", "MC Draw"))
|
||||
{
|
||||
base.OnDraw(graphics2D);
|
||||
}
|
||||
totalDrawTime.Stop();
|
||||
|
||||
millisecondTimer.Update((int)totalDrawTime.ElapsedMilliseconds);
|
||||
|
||||
if (ShowMemoryUsed)
|
||||
{
|
||||
long memory = GC.GetTotalMemory(false);
|
||||
this.Title = "Allocated = {0:n0} : {1:000}ms, d{2} Size = {3}x{4}, onIdle = {5:00}:{6:00}, widgetsDrawn = {7}".FormatWith(memory, millisecondTimer.GetAverage(), drawCount++, this.Width, this.Height, UiThread.CountExpired, UiThread.Count, GuiWidget.DrawCount);
|
||||
}
|
||||
|
||||
//msGraph.AddData("ms", totalDrawTime.ElapsedMilliseconds);
|
||||
//msGraph.Draw(MatterHackers.Agg.Transform.Affine.NewIdentity(), graphics2D);
|
||||
}
|
||||
|
||||
public override void OnClosing(ClosingEventArgs eventArgs)
|
||||
{
|
||||
if (this.HasBeenClosed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// save the last size of the window so we can restore it next time.
|
||||
ApplicationSettings.Instance.set(ApplicationSettingsKey.MainWindowMaximized, this.Maximized.ToString().ToLower());
|
||||
|
||||
if (!this.Maximized)
|
||||
{
|
||||
ApplicationSettings.Instance.set(ApplicationSettingsKey.WindowSize, string.Format("{0},{1}", Width, Height));
|
||||
ApplicationSettings.Instance.set(ApplicationSettingsKey.DesktopPosition, string.Format("{0},{1}", DesktopPosition.x, DesktopPosition.y));
|
||||
}
|
||||
|
||||
//Save a snapshot of the prints in queue
|
||||
QueueData.Instance.SaveDefaultQueue();
|
||||
|
||||
// If we are waiting for a response and get another request, just cancel the close until we get a response.
|
||||
if (exitDialogOpen)
|
||||
{
|
||||
eventArgs.Cancel = true;
|
||||
}
|
||||
|
||||
string caption = null;
|
||||
string message = null;
|
||||
|
||||
if (!ApplicationController.Instance.ApplicationExiting
|
||||
&& !exitDialogOpen
|
||||
&& ApplicationController.Instance.ActivePrinter.Connection.PrinterIsPrinting)
|
||||
{
|
||||
if (ApplicationController.Instance.ActivePrinter.Connection.CommunicationState != CommunicationStates.PrintingFromSd)
|
||||
{
|
||||
caption = "Abort Print".Localize();
|
||||
message = "Are you sure you want to abort the current print and close MatterControl?".Localize();
|
||||
}
|
||||
else
|
||||
{
|
||||
caption = "Exit while printing".Localize();
|
||||
message = "Are you sure you want exit while a print is running from SD Card?\n\nNote: If you exit, it is recommended you wait until the print is completed before running MatterControl again.".Localize();
|
||||
}
|
||||
}
|
||||
#if !__ANDROID__
|
||||
else if (PartsSheet.IsSaving())
|
||||
{
|
||||
caption = "Confirm Exit".Localize();
|
||||
message = "You are currently saving a parts sheet, are you sure you want to exit?".Localize();
|
||||
}
|
||||
#endif
|
||||
if (caption != null)
|
||||
{
|
||||
// Record that we are waiting for a response to the request to close
|
||||
exitDialogOpen = true;
|
||||
|
||||
// We need to show an interactive dialog to determine if the original Close request should be honored, thus cancel the current Close request
|
||||
eventArgs.Cancel = true;
|
||||
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
StyledMessageBox.ShowMessageBox(
|
||||
(exitConfirmed) =>
|
||||
{
|
||||
// Record that the exitDialog has closed
|
||||
exitDialogOpen = false;
|
||||
|
||||
// Continue with the original shutdown request if exit confirmed by user
|
||||
if (exitConfirmed)
|
||||
{
|
||||
ApplicationController.Instance.ApplicationExiting = true;
|
||||
|
||||
ApplicationController.Instance.Shutdown();
|
||||
|
||||
// Always call PrinterConnection.Disable on exit unless PrintingFromSd
|
||||
PrinterConnection printerConnection = ApplicationController.Instance.ActivePrinter.Connection;
|
||||
switch (printerConnection.CommunicationState)
|
||||
{
|
||||
case CommunicationStates.PrintingFromSd:
|
||||
case CommunicationStates.Paused when printerConnection.PrePauseCommunicationState == CommunicationStates.PrintingFromSd:
|
||||
break;
|
||||
|
||||
default:
|
||||
printerConnection.Disable();
|
||||
break;
|
||||
}
|
||||
|
||||
this.CloseOnIdle();
|
||||
}
|
||||
},
|
||||
message,
|
||||
caption,
|
||||
StyledMessageBox.MessageType.YES_NO);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplicationController.Instance.ApplicationExiting = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnClosed(ClosedEventArgs e)
|
||||
{
|
||||
UserSettings.Instance.Fields.StartCountDurringExit = UserSettings.Instance.Fields.StartCount;
|
||||
|
||||
if (ApplicationController.Instance.ActivePrinter.Connection.CommunicationState != CommunicationStates.PrintingFromSd)
|
||||
{
|
||||
ApplicationController.Instance.ActivePrinter.Connection.Disable();
|
||||
}
|
||||
//Close connection to the local datastore
|
||||
ApplicationController.Instance.ActivePrinter.Connection.HaltConnectionThread();
|
||||
ApplicationController.Instance.OnApplicationClosed();
|
||||
|
||||
Datastore.Instance.Exit();
|
||||
|
||||
base.OnClosed(e);
|
||||
}
|
||||
|
||||
public override void OnMouseMove(MouseEventArgs mouseEvent)
|
||||
{
|
||||
// run this first to make sure a child has the chance to take the drag drop event
|
||||
base.OnMouseMove(mouseEvent);
|
||||
|
||||
if (!mouseEvent.AcceptDrop && mouseEvent.DragFiles != null)
|
||||
{
|
||||
// no child has accepted the drop
|
||||
foreach (string file in mouseEvent.DragFiles)
|
||||
{
|
||||
string extension = Path.GetExtension(file).ToUpper();
|
||||
if ((extension != "" && MeshFileIo.ValidFileExtensions().Contains(extension))
|
||||
|| extension == ".GCODE"
|
||||
|| extension == ".ZIP")
|
||||
{
|
||||
//mouseEvent.AcceptDrop = true;
|
||||
}
|
||||
}
|
||||
dropWasOnChild = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
dropWasOnChild = true;
|
||||
}
|
||||
|
||||
if (GuiWidget.DebugBoundsUnderMouse)
|
||||
{
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -206,7 +206,7 @@ namespace MatterHackers.MatterControl.SettingsManagement
|
|||
await Task.Delay(20000);
|
||||
await ProfileManager.LoadOemProfileAsync(publicDevice, oem, model);
|
||||
|
||||
if (MatterControlApplication.Instance.ApplicationExiting)
|
||||
if (ApplicationController.Instance.ApplicationExiting)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ namespace MatterHackers.MatterControl
|
|||
configureButton.Margin = new BorderDouble(0, 0, 10, 0);
|
||||
configureButton.Click += (s, e) =>
|
||||
{
|
||||
MatterControlApplication.Instance.ConfigureWifi();
|
||||
MatterControl.AppContext.Platform.ConfigureWifi();
|
||||
UiThread.RunOnIdle(WizardWindow.Close, 1);
|
||||
|
||||
// We could clear the failure count allowing the user to toggle wifi, then retry sign-in
|
||||
|
|
|
|||
|
|
@ -116,13 +116,18 @@ namespace MatterHackers.MatterControl
|
|||
mainContainer.AddChild(contentRow);
|
||||
mainContainer.AddChild(footerRow);
|
||||
|
||||
mainContainer.Padding = new BorderDouble(3, 5, 3, 5);
|
||||
headerRow.Padding = new BorderDouble(0, 3, 0, 3);
|
||||
#if __ANDROID__
|
||||
if (false)
|
||||
#endif
|
||||
{
|
||||
mainContainer.Padding = new BorderDouble(3, 5, 3, 5);
|
||||
headerRow.Padding = new BorderDouble(0, 3, 0, 3);
|
||||
|
||||
headerLabel.TextWidget.PointSize = 14;
|
||||
headerLabel.TextColor = ActiveTheme.Instance.PrimaryTextColor;
|
||||
contentRow.Padding = new BorderDouble(5);
|
||||
footerRow.Margin = new BorderDouble(0, 3);
|
||||
headerLabel.TextWidget.PointSize = 14;
|
||||
headerLabel.TextColor = ActiveTheme.Instance.PrimaryTextColor;
|
||||
contentRow.Padding = new BorderDouble(5);
|
||||
footerRow.Margin = new BorderDouble(0, 3);
|
||||
}
|
||||
|
||||
this.AddChild(mainContainer);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ public class LicenseAgreementPage : DialogPage
|
|||
protected override void OnCancel(out bool abortCancel)
|
||||
{
|
||||
// Exit if EULA is not accepted
|
||||
UiThread.RunOnIdle(MatterControlApplication.Instance.Close);
|
||||
UiThread.RunOnIdle(AppContext.RootSystemWindow.Close);
|
||||
|
||||
abortCancel = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ namespace MatterHackers.MatterControl
|
|||
nextButton.Visible = true;
|
||||
skipButton.Visible = false;
|
||||
configureButton.Visible = false;
|
||||
MatterControlApplication.Instance.ConfigureWifi();
|
||||
AppContext.Platform.ConfigureWifi();
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -98,7 +98,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
|
|||
double value;
|
||||
if (!double.TryParse(textValue, out value))
|
||||
{
|
||||
MatterControlApplication.BreakInDebugger("Slicing value is not a double.");
|
||||
return valueOnError;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit e03d0344ceb98c59d24f916a9217c4a4fa0a32a1
|
||||
Subproject commit 4a00055f6ed13dc4649d13c4cb499f3b7e09b202
|
||||
|
|
@ -45,6 +45,9 @@
|
|||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.ValueTuple, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\System.ValueTuple.4.4.0\lib\net461\System.ValueTuple.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ namespace MatterHackers.MatterControl.Tests.Automation
|
|||
testRunner.CompleteDialog(
|
||||
MatterControlUtilities.GetTestItemPath("Fennec_Fox.stl"));
|
||||
|
||||
// Wait up to 3 seconds for expected outcome
|
||||
// Wait for expected outcome
|
||||
testRunner.WaitFor(() => QueueData.Instance.ItemCount == expectedCount);
|
||||
|
||||
// Assert - one part added and queue count increases by one
|
||||
|
|
@ -93,7 +93,7 @@ namespace MatterHackers.MatterControl.Tests.Automation
|
|||
MatterControlUtilities.GetTestItemPath("Batman.stl")),
|
||||
secondsToWait: 2);
|
||||
|
||||
// Wait up to 3 seconds for expected outcome
|
||||
// Wait for expected outcome
|
||||
testRunner.WaitFor(() => QueueData.Instance.ItemCount == expectedCount);
|
||||
|
||||
// Assert - two parts added and queue count increases by two
|
||||
|
|
@ -203,7 +203,7 @@ namespace MatterHackers.MatterControl.Tests.Automation
|
|||
testRunner.CompleteDialog(
|
||||
MatterControlUtilities.GetTestItemPath("Rook.amf"));
|
||||
|
||||
// Wait up to 3 seconds for expected outcome
|
||||
// Wait for expected outcome
|
||||
testRunner.WaitFor(() => QueueData.Instance.ItemCount == expectedCount);
|
||||
|
||||
// Assert - one part added and queue count increases by one
|
||||
|
|
@ -233,7 +233,7 @@ namespace MatterHackers.MatterControl.Tests.Automation
|
|||
testRunner.CompleteDialog(
|
||||
MatterControlUtilities.GetTestItemPath("Batman.stl"));
|
||||
|
||||
// Wait up to 3 seconds for expected outcome
|
||||
// Wait for expected outcome
|
||||
testRunner.WaitFor(() => QueueData.Instance.ItemCount == expectedCount);
|
||||
|
||||
// Assert - one part added and queue count increases by one
|
||||
|
|
@ -263,7 +263,7 @@ namespace MatterHackers.MatterControl.Tests.Automation
|
|||
testRunner.CompleteDialog(
|
||||
MatterControlUtilities.GetTestItemPath("chichen-itza_pyramid.gcode"));
|
||||
|
||||
// Wait up to 3 seconds for expected outcome
|
||||
// Wait for expected outcome
|
||||
testRunner.WaitFor(() => QueueData.Instance.ItemCount == expectedCount);
|
||||
|
||||
// Assert - one part added and queue count increases by one
|
||||
|
|
|
|||
|
|
@ -573,7 +573,7 @@ namespace MatterHackers.MatterControl.Tests.Automation
|
|||
testRunner.Delay(2);
|
||||
|
||||
// Confirm abort
|
||||
Assert.IsFalse(MatterControlApplication.Instance.HasBeenClosed, "Canceling Close dialog should *not* close MatterControl");
|
||||
Assert.IsFalse(AppContext.RootSystemWindow.HasBeenClosed, "Canceling Close dialog should *not* close MatterControl");
|
||||
|
||||
// Close MatterControl and cancel print
|
||||
testRunner.CloseMatterControl();
|
||||
|
|
@ -587,7 +587,7 @@ namespace MatterHackers.MatterControl.Tests.Automation
|
|||
testRunner.Delay(2);
|
||||
|
||||
// Confirm close
|
||||
Assert.IsTrue(MatterControlApplication.Instance.HasBeenClosed, "Confirming Close dialog *should* close MatterControl");
|
||||
Assert.IsTrue(AppContext.RootSystemWindow.HasBeenClosed, "Confirming Close dialog *should* close MatterControl");
|
||||
|
||||
// Wait for M106 change
|
||||
testRunner.WaitFor(() => fanChangedCount > 0, 15, 500);
|
||||
|
|
|
|||
|
|
@ -3,4 +3,5 @@
|
|||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
|
||||
<package id="NUnit" version="3.8.1" targetFramework="net461" />
|
||||
<package id="NUnit.ApplicationDomain" version="11.0.0" targetFramework="net461" />
|
||||
<package id="System.ValueTuple" version="4.4.0" targetFramework="net461" />
|
||||
</packages>
|
||||
|
|
@ -68,7 +68,9 @@ namespace MatterHackers.MatterControl.Tests.Automation
|
|||
private static string runName = DateTime.Now.ToString("yyyy-MM-ddTHH-mm-ss");
|
||||
|
||||
public static string PathToDownloadsSubFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Downloads", "-Temporary");
|
||||
|
||||
|
||||
private static SystemWindow rootSystemWindow;
|
||||
|
||||
public static void RemoveAllFromQueue(this AutomationRunner testRunner)
|
||||
{
|
||||
testRunner.ClickByName("Queue... Menu");
|
||||
|
|
@ -137,7 +139,7 @@ namespace MatterHackers.MatterControl.Tests.Automation
|
|||
|
||||
public static void CloseMatterControl(this AutomationRunner testRunner)
|
||||
{
|
||||
MatterControlApplication.Instance.Close();
|
||||
rootSystemWindow?.Close();
|
||||
}
|
||||
|
||||
public enum PrepAction
|
||||
|
|
@ -579,10 +581,8 @@ namespace MatterHackers.MatterControl.Tests.Automation
|
|||
|
||||
UserSettings.Instance.set(UserSettingsKey.ThumbnailRenderingMode, "orthographic");
|
||||
//GL.HardwareAvailable = false;
|
||||
MatterControlApplication matterControlWindow = MatterControlApplication.CreateInstance(overrideWidth, overrideHeight);
|
||||
|
||||
var config = TestAutomationConfig.Load();
|
||||
|
||||
if (config.UseAutomationDialogs)
|
||||
{
|
||||
AggContext.Config.ProviderTypes.DialogProvider = "MatterHackers.Agg.Platform.AutomationDialogProvider, GuiAutomation";
|
||||
|
|
@ -592,8 +592,14 @@ namespace MatterHackers.MatterControl.Tests.Automation
|
|||
AutomationRunner.TimeToMoveMouse = config.TimeToMoveMouse;
|
||||
AutomationRunner.UpDelaySeconds = config.MouseUpDelay;
|
||||
|
||||
var (width, height) = RootSystemWindow.GetStartupBounds();
|
||||
|
||||
rootSystemWindow = Application.LoadRootWindow(
|
||||
overrideWidth == -1 ? width : overrideWidth,
|
||||
overrideHeight == -1 ? height : overrideHeight);
|
||||
|
||||
await AutomationRunner.ShowWindowAndExecuteTests(
|
||||
matterControlWindow,
|
||||
rootSystemWindow,
|
||||
testMethod,
|
||||
maxTimeToRun,
|
||||
defaultTestImages,
|
||||
|
|
@ -605,9 +611,7 @@ namespace MatterHackers.MatterControl.Tests.Automation
|
|||
ApplicationController.Instance.ActivePrinter.Connection.Disable();
|
||||
}
|
||||
|
||||
MatterControlApplication app = MatterControlApplication.Instance;
|
||||
app.RestartOnClose = false;
|
||||
app.Close();
|
||||
rootSystemWindow.Close();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ namespace MatterHackers.MatterControl.Plugins.BrailleBuilder
|
|||
{
|
||||
UiThread.RunOnIdle(() =>
|
||||
{
|
||||
MatterControlApplication.Instance.LaunchBrowser("https://en.wikipedia.org/wiki/Braille");
|
||||
ApplicationController.Instance.LaunchBrowser("https://en.wikipedia.org/wiki/Braille");
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue